3
3
var find = require ( 'property-information/find' )
4
4
var normalize = require ( 'property-information/normalize' )
5
5
var parseSelector = require ( 'hast-util-parse-selector' )
6
- var spaces = require ( 'space-separated-tokens' ) . parse
7
- var commas = require ( 'comma-separated-tokens' ) . parse
6
+ var spaceSeparated = require ( 'space-separated-tokens' )
7
+ var commaSeparated = require ( 'comma-separated-tokens' )
8
8
9
9
module . exports = factory
10
10
11
11
var own = { } . hasOwnProperty
12
12
13
13
function factory ( schema , defaultTagName , caseSensitive ) {
14
- var adjust = caseSensitive ? createAdjustMap ( caseSensitive ) : null
14
+ var adjust = caseSensitive && createAdjustMap ( caseSensitive )
15
15
16
16
return h
17
17
18
18
// Hyperscript compatible DSL for creating virtual hast trees.
19
19
function h ( selector , properties ) {
20
20
var node = parseSelector ( selector , defaultTagName )
21
- var children = Array . prototype . slice . call ( arguments , 2 )
22
21
var name = node . tagName . toLowerCase ( )
22
+ var index = 1
23
23
var property
24
24
25
+ // Normalize the name.
25
26
node . tagName = adjust && own . call ( adjust , name ) ? adjust [ name ] : name
26
27
27
- if ( properties && isChildren ( properties , node ) ) {
28
- children . unshift ( properties )
29
- properties = null
30
- }
31
-
28
+ // Handle props.
32
29
if ( properties ) {
33
- for ( property in properties ) {
34
- addProperty ( node . properties , property , properties [ property ] )
30
+ if (
31
+ typeof properties === 'string' ||
32
+ 'length' in properties ||
33
+ isNode ( name , properties )
34
+ ) {
35
+ // Nope, it’s something for `children`.
36
+ index --
37
+ } else {
38
+ for ( property in properties ) {
39
+ addProperty ( schema , node . properties , property , properties [ property ] )
40
+ }
35
41
}
36
42
}
37
43
38
- addChild ( node . children , children )
44
+ // Handle children.
45
+ while ( ++ index < arguments . length ) {
46
+ addChild ( node . children , arguments [ index ] )
47
+ }
39
48
40
- if ( node . tagName === 'template' ) {
49
+ if ( name === 'template' ) {
41
50
node . content = { type : 'root' , children : node . children }
42
51
node . children = [ ]
43
52
}
44
53
45
54
return node
46
55
}
47
-
48
- function addProperty ( properties , key , value ) {
49
- var info
50
- var property
51
- var result
52
-
53
- // Ignore nullish and NaN values.
54
- if ( value === null || value === undefined || value !== value ) {
55
- return
56
- }
57
-
58
- info = find ( schema , key )
59
- property = info . property
60
- result = value
61
-
62
- // Handle list values.
63
- if ( typeof result === 'string' ) {
64
- if ( info . spaceSeparated ) {
65
- result = spaces ( result )
66
- } else if ( info . commaSeparated ) {
67
- result = commas ( result )
68
- } else if ( info . commaOrSpaceSeparated ) {
69
- result = spaces ( commas ( result ) . join ( ' ' ) )
70
- }
71
- }
72
-
73
- // Accept `object` on style.
74
- if ( property === 'style' && typeof value !== 'string' ) {
75
- result = style ( result )
76
- }
77
-
78
- // Class-names (which can be added both on the `selector` and here).
79
- if ( property === 'className' && properties . className ) {
80
- result = properties . className . concat ( result )
81
- }
82
-
83
- properties [ property ] = parsePrimitives ( info , property , result )
84
- }
85
56
}
86
57
87
- function isChildren ( value , node ) {
88
- return (
89
- typeof value === 'string' ||
90
- 'length' in value ||
91
- isNode ( node . tagName , value )
92
- )
93
- }
94
-
95
- function isNode ( tagName , value ) {
58
+ function isNode ( name , value ) {
96
59
var type = value . type
97
60
98
- if ( tagName === 'input' || ! type || typeof type !== 'string' ) {
61
+ if ( name === 'input' || ! type || typeof type !== 'string' ) {
99
62
return false
100
63
}
101
64
@@ -105,7 +68,7 @@ function isNode(tagName, value) {
105
68
106
69
type = type . toLowerCase ( )
107
70
108
- if ( tagName === 'button' ) {
71
+ if ( name === 'button' ) {
109
72
return (
110
73
type !== 'menu' &&
111
74
type !== 'submit' &&
@@ -117,70 +80,81 @@ function isNode(tagName, value) {
117
80
return 'value' in value
118
81
}
119
82
120
- function addChild ( nodes , value ) {
121
- var index
122
- var length
83
+ function addProperty ( schema , properties , key , value ) {
84
+ var info = find ( schema , key )
85
+ var result = value
86
+ var index = - 1
87
+ var finalResult
123
88
124
- if ( typeof value === 'string' || typeof value === 'number' ) {
125
- nodes . push ( { type : 'text' , value : String ( value ) } )
89
+ // Ignore nullish and NaN values.
90
+ if ( result == null || result !== result ) {
126
91
return
127
92
}
128
93
129
- if ( typeof value === 'object' && 'length' in value ) {
130
- index = - 1
131
- length = value . length
132
-
133
- while ( ++ index < length ) {
134
- addChild ( nodes , value [ index ] )
94
+ // Handle list values.
95
+ if ( typeof result === 'string' ) {
96
+ if ( info . spaceSeparated ) {
97
+ result = spaceSeparated . parse ( result )
98
+ } else if ( info . commaSeparated ) {
99
+ result = commaSeparated . parse ( result )
100
+ } else if ( info . commaOrSpaceSeparated ) {
101
+ result = spaceSeparated . parse ( commaSeparated . parse ( result ) . join ( ' ' ) )
135
102
}
136
-
137
- return
138
103
}
139
104
140
- if ( typeof value !== 'object' || ! ( 'type' in value ) ) {
141
- throw new Error ( 'Expected node, nodes, or string, got `' + value + '`' )
105
+ // Accept `object` on style.
106
+ if ( info . property === 'style' && typeof result !== 'string' ) {
107
+ result = style ( result )
142
108
}
143
109
144
- nodes . push ( value )
145
- }
146
-
147
- // Parse a (list of) primitives.
148
- function parsePrimitives ( info , name , value ) {
149
- var index
150
- var length
151
- var result
110
+ // Class names (which can be added both on the `selector` and here).
111
+ if ( info . property === 'className' && properties . className ) {
112
+ result = properties . className . concat ( result )
113
+ }
152
114
153
- if ( typeof value !== 'object' || ! ( 'length' in value ) ) {
154
- return parsePrimitive ( info , name , value )
115
+ if ( typeof result === 'object' && 'length' in result ) {
116
+ finalResult = [ ]
117
+ while ( ++ index < result . length ) {
118
+ finalResult [ index ] = parsePrimitive ( info , info . property , result [ index ] )
119
+ }
120
+ } else {
121
+ finalResult = parsePrimitive ( info , info . property , result )
155
122
}
156
123
157
- length = value . length
158
- index = - 1
159
- result = [ ]
124
+ properties [ info . property ] = finalResult
125
+ }
160
126
161
- while ( ++ index < length ) {
162
- result [ index ] = parsePrimitive ( info , name , value [ index ] )
163
- }
127
+ function addChild ( nodes , value ) {
128
+ var index = - 1
164
129
165
- return result
130
+ if ( typeof value === 'string' || typeof value === 'number' ) {
131
+ nodes . push ( { type : 'text' , value : String ( value ) } )
132
+ } else if ( typeof value === 'object' && 'length' in value ) {
133
+ while ( ++ index < value . length ) {
134
+ addChild ( nodes , value [ index ] )
135
+ }
136
+ } else if ( typeof value === 'object' && 'type' in value ) {
137
+ nodes . push ( value )
138
+ } else {
139
+ throw new Error ( 'Expected node, nodes, or string, got `' + value + '`' )
140
+ }
166
141
}
167
142
168
143
// Parse a single primitives.
169
144
function parsePrimitive ( info , name , value ) {
170
145
var result = value
171
146
172
- if ( info . number || info . positiveNumber ) {
173
- if ( ! isNaN ( result ) && result !== '' ) {
174
- result = Number ( result )
175
- }
176
- } else if ( info . boolean || info . overloadedBoolean ) {
177
- // Accept `boolean` and `string`.
178
- if (
179
- typeof result === 'string' &&
180
- ( result === '' || normalize ( value ) === normalize ( name ) )
181
- ) {
182
- result = true
183
- }
147
+ if ( ( info . number || info . positiveNumber ) && ! isNaN ( result ) && result !== '' ) {
148
+ result = Number ( result )
149
+ }
150
+
151
+ // Accept `boolean` and `string`.
152
+ if (
153
+ ( info . boolean || info . overloadedBoolean ) &&
154
+ typeof result === 'string' &&
155
+ ( result === '' || normalize ( value ) === normalize ( name ) )
156
+ ) {
157
+ result = true
184
158
}
185
159
186
160
return result
@@ -198,14 +172,11 @@ function style(value) {
198
172
}
199
173
200
174
function createAdjustMap ( values ) {
201
- var length = values . length
202
- var index = - 1
203
175
var result = { }
204
- var value
176
+ var index = - 1
205
177
206
- while ( ++ index < length ) {
207
- value = values [ index ]
208
- result [ value . toLowerCase ( ) ] = value
178
+ while ( ++ index < values . length ) {
179
+ result [ values [ index ] . toLowerCase ( ) ] = values [ index ]
209
180
}
210
181
211
182
return result
0 commit comments