Skip to content

Commit 714c9e0

Browse files
pl12133developit
authored andcommitted
Address vhtml#11: Add ability to directly set innerHTML of a component using the dangerouslySetInnerHTML attribute. (#12)
* Address vhtml#11: Add ability to directly set innerHTML of a component using the `dangerouslySetInnerHTML` attribute. * Remove check for valid `__html` property of `dangerouslySetInnerHTML * Hoist line that is always executed out of conditional block Saves 4 bytes. * Hoist declaration of `s` to avoid extra `let` statement. Saves 3 bytes. * Hoist default assignment of `attrs` to the top of `h`. This allows us to assume that `attrs` is a plain object, and remove multiple guards. Saves 6B.
1 parent a111d56 commit 714c9e0

File tree

2 files changed

+19
-10
lines changed

2 files changed

+19
-10
lines changed

src/vhtml.js

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import emptyTags from './empty-tags';
33
// escape an attribute
44
let esc = str => String(str).replace(/[&<>"']/g, s=>`&${map[s]};`);
55
let map = {'&':'amp','<':'lt','>':'gt','"':'quot',"'":'apos'};
6+
let setInnerHTMLAttr = 'dangerouslySetInnerHTML';
67
let DOMAttributeNames = {
78
className: 'class',
89
htmlFor: 'for'
@@ -12,29 +13,31 @@ let sanitized = {};
1213

1314
/** Hyperscript reviver that constructs a sanitized HTML string. */
1415
export default function h(name, attrs) {
15-
let stack=[];
16+
let stack=[], s = `<${name}`;
17+
attrs = attrs || {};
1618
for (let i=arguments.length; i-- > 2; ) {
1719
stack.push(arguments[i]);
1820
}
1921

2022
// Sortof component support!
2123
if (typeof name==='function') {
22-
(attrs || (attrs = {})).children = stack.reverse();
24+
attrs.children = stack.reverse();
2325
return name(attrs);
2426
// return name(attrs, stack.reverse());
2527
}
2628

27-
let s = `<${name}`;
28-
if (attrs) for (let i in attrs) {
29-
if (attrs[i]!==false && attrs[i]!=null) {
29+
for (let i in attrs) {
30+
if (attrs[i]!==false && attrs[i]!=null && i !== setInnerHTMLAttr) {
3031
s += ` ${DOMAttributeNames[i] ? DOMAttributeNames[i] : esc(i)}="${esc(attrs[i])}"`;
3132
}
3233
}
34+
s += '>';
3335

3436
if (emptyTags.indexOf(name) === -1) {
35-
s += '>';
36-
37-
while (stack.length) {
37+
if (attrs[setInnerHTMLAttr]) {
38+
s += attrs[setInnerHTMLAttr].__html;
39+
}
40+
else while (stack.length) {
3841
let child = stack.pop();
3942
if (child) {
4043
if (child.pop) {
@@ -47,8 +50,6 @@ export default function h(name, attrs) {
4750
}
4851

4952
s += `</${name}>`;
50-
} else {
51-
s += '>';
5253
}
5354

5455
sanitized[s] = true;

test/vhtml.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,14 @@ describe('vhtml', () => {
4040
);
4141
});
4242

43+
it('should not sanitize the "dangerouslySetInnerHTML" attribute, and directly set its `__html` property as innerHTML', () => {
44+
expect(
45+
<div dangerouslySetInnerHTML={{ __html: "<span>Injected HTML</span>" }} />
46+
).to.equal(
47+
`<div><span>Injected HTML</span></div>`
48+
);
49+
});
50+
4351
it('should flatten children', () => {
4452
expect(
4553
<div>

0 commit comments

Comments
 (0)