Skip to content

Commit f46e762

Browse files
committed
Add support for infinitely nested Arrays of children, while improving performance and decreasing library size 🎈 /cc @NekR
1 parent 24a3fdf commit f46e762

2 files changed

Lines changed: 29 additions & 10 deletions

File tree

src/vhtml.js

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,31 @@
22
let esc = str => String(str).replace(/[&<>"']/g, s=>`&${map[s]};`);
33
let map = {'&':'amp','<':'lt','>':'gt','"':'quot',"'":'apos'};
44

5-
// sanitize text children and filter out falsey values
6-
let child = s => truthy(s) ? (sanitized[s]===true ? s : esc(s)) : '';
7-
8-
// check that a value is not false, undefined or null
9-
let truthy = v => v!==false && v!=null;
10-
115
let sanitized = {};
126

137
/** Hyperscript reviver that constructs a sanitized HTML string. */
14-
export default function h(name, attrs, ...children) {
8+
export default function h(name, attrs) {
159
let s = `<${name}`;
1610
if (attrs) for (let i in attrs) {
17-
if (attrs.hasOwnProperty(i) && truthy(attrs[i])) {
11+
if (attrs[i]!==false && attrs[i]!=null) {
1812
s += ` ${esc(i)}="${esc(attrs[i])}"`;
1913
}
2014
}
21-
s += `>${[].concat(...children).map(child).join('')}</${name}>`;
22-
sanitized[s] = true;
15+
s += '>';
16+
let stack=[];
17+
for (let i=arguments.length; i-- > 2; ) stack.push(arguments[i]);
18+
while (stack.length) {
19+
let child = stack.pop();
20+
if (child) {
21+
if (child.pop) {
22+
for (let i=child.length; i--; ) stack.push(child[i]);
23+
}
24+
else {
25+
s += sanitized[child]===true ? child : esc(child);
26+
}
27+
}
28+
}
29+
sanitized[s += `</${name}>`] = true;
2330
return s;
2431
}
2532

test/vhtml.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,16 @@ describe('vhtml', () => {
3939
`<div onclick="&amp;&lt;&gt;&quot;&apos;"></div>`
4040
);
4141
});
42+
43+
it('should flatten children', () => {
44+
expect(
45+
<div>
46+
{[['a','b']]}
47+
<c>d</c>
48+
{['e',['f'],[['g']]]}
49+
</div>
50+
).to.equal(
51+
`<div>ab<c>d</c>efg</div>`
52+
);
53+
});
4254
});

0 commit comments

Comments
 (0)