33var find = require ( 'property-information/find' )
44var normalize = require ( 'property-information/normalize' )
55var 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' )
88
99module . exports = factory
1010
1111var own = { } . hasOwnProperty
1212
1313function factory ( schema , defaultTagName , caseSensitive ) {
14- var adjust = caseSensitive ? createAdjustMap ( caseSensitive ) : null
14+ var adjust = caseSensitive && createAdjustMap ( caseSensitive )
1515
1616 return h
1717
1818 // Hyperscript compatible DSL for creating virtual hast trees.
1919 function h ( selector , properties ) {
2020 var node = parseSelector ( selector , defaultTagName )
21- var children = Array . prototype . slice . call ( arguments , 2 )
2221 var name = node . tagName . toLowerCase ( )
22+ var index = 1
2323 var property
2424
25+ // Normalize the name.
2526 node . tagName = adjust && own . call ( adjust , name ) ? adjust [ name ] : name
2627
27- if ( properties && isChildren ( properties , node ) ) {
28- children . unshift ( properties )
29- properties = null
30- }
31-
28+ // Handle props.
3229 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+ }
3541 }
3642 }
3743
38- addChild ( node . children , children )
44+ // Handle children.
45+ while ( ++ index < arguments . length ) {
46+ addChild ( node . children , arguments [ index ] )
47+ }
3948
40- if ( node . tagName === 'template' ) {
49+ if ( name === 'template' ) {
4150 node . content = { type : 'root' , children : node . children }
4251 node . children = [ ]
4352 }
4453
4554 return node
4655 }
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- }
8556}
8657
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 ) {
9659 var type = value . type
9760
98- if ( tagName === 'input' || ! type || typeof type !== 'string' ) {
61+ if ( name === 'input' || ! type || typeof type !== 'string' ) {
9962 return false
10063 }
10164
@@ -105,7 +68,7 @@ function isNode(tagName, value) {
10568
10669 type = type . toLowerCase ( )
10770
108- if ( tagName === 'button' ) {
71+ if ( name === 'button' ) {
10972 return (
11073 type !== 'menu' &&
11174 type !== 'submit' &&
@@ -117,70 +80,81 @@ function isNode(tagName, value) {
11780 return 'value' in value
11881}
11982
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
12388
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 ) {
12691 return
12792 }
12893
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 ( ' ' ) )
135102 }
136-
137- return
138103 }
139104
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 )
142108 }
143109
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+ }
152114
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 )
155122 }
156123
157- length = value . length
158- index = - 1
159- result = [ ]
124+ properties [ info . property ] = finalResult
125+ }
160126
161- while ( ++ index < length ) {
162- result [ index ] = parsePrimitive ( info , name , value [ index ] )
163- }
127+ function addChild ( nodes , value ) {
128+ var index = - 1
164129
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+ }
166141}
167142
168143// Parse a single primitives.
169144function parsePrimitive ( info , name , value ) {
170145 var result = value
171146
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
184158 }
185159
186160 return result
@@ -198,14 +172,11 @@ function style(value) {
198172}
199173
200174function createAdjustMap ( values ) {
201- var length = values . length
202- var index = - 1
203175 var result = { }
204- var value
176+ var index = - 1
205177
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 ]
209180 }
210181
211182 return result
0 commit comments