Skip to content

Commit 1f3b063

Browse files
committed
Fix property/node detection
Adds a more robust detection method, when two parameters are provided, betweeen whether that second value are the children of the parent node or its properties.
1 parent 56720cf commit 1f3b063

File tree

2 files changed

+102
-6
lines changed

2 files changed

+102
-6
lines changed

index.js

+27-5
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,32 @@ function addChild(nodes, value) {
177177
nodes.push(value);
178178
}
179179

180+
/**
181+
* Check if `value` is a valid child node of
182+
* `tagName`.
183+
*
184+
* @param {string} tagName - Parent tag-name.
185+
* @param {Object} value - Node or properties like value.
186+
* @return {boolean} - Whether `value` is a node.
187+
*/
188+
function isNode(tagName, value) {
189+
var type = value.type;
190+
191+
if (tagName === 'input' || !type || typeof type !== 'string') {
192+
return false;
193+
}
194+
195+
if (typeof value.children === 'object' && 'length' in value.children) {
196+
return true;
197+
}
198+
199+
if (tagName === 'button') {
200+
return type !== 'submit' && type !== 'reset' && type !== 'button';
201+
}
202+
203+
return 'value' in value;
204+
}
205+
180206
/**
181207
* Hyperscript compatible DSL for creating virtual HAST
182208
* trees.
@@ -197,11 +223,7 @@ function h(selector, properties, children) {
197223
(
198224
typeof properties === 'string' ||
199225
'length' in properties ||
200-
// Only allow a node at the `properties`
201-
// position when it isn’t an `input`, as those
202-
// use HTML `type` and `value` attributes too
203-
// and are void.
204-
(node.tagName !== 'input' && 'type' in properties)
226+
isNode(node.tagName, properties)
205227
)
206228
) {
207229
children = properties;

test.js

+75-1
Original file line numberDiff line numberDiff line change
@@ -624,7 +624,81 @@ test('hastscript', function (t) {
624624
'children': []
625625
},
626626
'should *not* allow omitting `properties` for ' +
627-
'an `input[type=text]`, as those are void and clash'
627+
'an `input[type=text][value]`, as those are void and clash'
628+
);
629+
630+
st.deepEqual(
631+
h('a', {
632+
'type': 'text/html'
633+
}),
634+
{
635+
'type': 'element',
636+
'tagName': 'a',
637+
'properties': {
638+
'type': 'text/html'
639+
},
640+
'children': []
641+
},
642+
'should *not* allow omitting `properties` for ' +
643+
'an `[type]`, without `value` or `children`'
644+
);
645+
646+
st.deepEqual(
647+
h('foo', {
648+
'type': 'text/html',
649+
'children': {
650+
'bar': 'baz'
651+
}
652+
}),
653+
{
654+
'type': 'element',
655+
'tagName': 'foo',
656+
'properties': {
657+
'type': 'text/html',
658+
'children': {
659+
'bar': 'baz'
660+
}
661+
},
662+
'children': []
663+
},
664+
'should *not* allow omitting `properties` when ' +
665+
'`children` is not set to an array'
666+
);
667+
668+
st.deepEqual(
669+
h('button', {
670+
'type': 'submit',
671+
'value': 'Send'
672+
}),
673+
{
674+
'type': 'element',
675+
'tagName': 'button',
676+
'properties': {
677+
'type': 'submit',
678+
'value': 'Send'
679+
},
680+
'children': []
681+
},
682+
'should *not* allow omitting `properties` when ' +
683+
'a button has a valid type'
684+
);
685+
686+
st.deepEqual(
687+
h('button', {
688+
'type': 'text',
689+
'value': 'Send'
690+
}),
691+
{
692+
'type': 'element',
693+
'tagName': 'button',
694+
'properties': {},
695+
'children': [{
696+
'type': 'text',
697+
'value': 'Send'
698+
}]
699+
},
700+
'should allow omitting `properties` when ' +
701+
'a button has an invalid type'
628702
);
629703

630704
st.throws(

0 commit comments

Comments
 (0)