Skip to content

Commit 492441b

Browse files
committed
Merge pull request #2 from wrakky/void_elements
Add void element checking to TagElementType
2 parents 8b179c8 + 91729ec commit 492441b

File tree

6 files changed

+69
-5
lines changed

6 files changed

+69
-5
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# React HTML Parser
22

3-
A utility library for converting HTML strings into [React](https://facebook.github.io/react/) components. Avoids the use of dangerouslySetInnerHTML and converts standard HTML elements, attributes and inline styles into their React equivalents.
3+
A utility for converting HTML strings into [React](https://facebook.github.io/react/) components. Avoids the use of dangerouslySetInnerHTML and converts standard HTML elements, attributes and inline styles into their React equivalents.
44

55
[Try the Live Demo](https://wrakky.github.io/react-html-parser)
66

src/elementTypes/TagElementType.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React from 'react';
22
import ProcessNodes from '../utils/ProcessNodes';
33
import GeneratePropsFromAttributes from '../utils/GeneratePropsFromAttributes';
44
import TransformTagName from '../utils/TransformTagName';
5+
import isVoidElement from '../utils/isVoidElement';
56

67
/**
78
* Converts any element (excluding style - see StyleElementType - and script) to a react element.
@@ -12,15 +13,18 @@ import TransformTagName from '../utils/TransformTagName';
1213
*/
1314
export default function TagElementType(node, key) {
1415

15-
// If the node has children process them
16-
const children = ProcessNodes(node.children);
17-
1816
// generate props
1917
const props = GeneratePropsFromAttributes(node.attribs, key);
2018

2119
// transform the tag name if needed
2220
const tagName = TransformTagName(node.name);
2321

22+
// If the node is not a void element and has children then process them
23+
let children = null;
24+
if (!isVoidElement(tagName)) {
25+
children = ProcessNodes(node.children);
26+
}
27+
2428
// create and return the element
2529
return React.createElement(tagName, props, children);
2630
}

src/utils/isVoidElement.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
const voidElements = [
2+
'area',
3+
'base',
4+
'br',
5+
'col',
6+
'command',
7+
'embed',
8+
'hr',
9+
'img',
10+
'input',
11+
'keygen',
12+
'link',
13+
'meta',
14+
'param',
15+
'source',
16+
'track',
17+
'wbr'
18+
];
19+
20+
export default function isVoidElement(element) {
21+
22+
return voidElements.indexOf(element) >= 0;
23+
24+
}

test/integration/integration.spec.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,8 @@ describe('Integration tests: ', () => {
7373
test('<body>test</body>', '<div>test</div>');
7474
});
7575

76+
it('should not allow nesting of void elements', () => {
77+
test('<img><p>test</p></img>', '<img/><p>test</p>');
78+
});
79+
7680
});

test/unit/elementTypes/TagElementType.spec.js

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
11
const GeneratePropsFromAttributes = jasmine.createSpy('GeneratePropsFromAttributes').and.callFake(attrs => attrs);
22
const ProcessNodes = jasmine.createSpy('ProcessNodes').and.returnValue('children');
3+
const isVoidElement = jasmine.createSpy('isVoidElement').and.returnValue(false);
34

45
const TagElementType = require('inject!elementTypes/TagElementType')({
56
'../utils/GeneratePropsFromAttributes': GeneratePropsFromAttributes,
6-
'../utils/ProcessNodes': ProcessNodes
7+
'../utils/ProcessNodes': ProcessNodes,
8+
'../utils/isVoidElement': isVoidElement
79
}).default;
810

911
describe('Testing `elementTypes/TagElementType', () => {
1012

1113
beforeEach(() => {
1214
GeneratePropsFromAttributes.calls.reset();
1315
ProcessNodes.calls.reset();
16+
isVoidElement.calls.reset();
1417
});
1518

1619
it('should return a React element corresponding to the node name', () => {
@@ -33,4 +36,21 @@ describe('Testing `elementTypes/TagElementType', () => {
3336

3437
});
3538

39+
it('should not pass though children for void elements', () => {
40+
41+
const voidNode = {
42+
name: 'void',
43+
attribs: {
44+
id: 'test'
45+
},
46+
children: 'child'
47+
};
48+
isVoidElement.and.returnValue(true);
49+
50+
const voidElement = TagElementType(voidNode, 'key');
51+
expect(voidElement.type).toBe('void');
52+
expect(voidElement.props.children).toBe(null);
53+
54+
});
55+
3656
});
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import isVoidElement from 'utils/isVoidElement';
2+
3+
describe('Testing `utils/isVoidElement`', () => {
4+
5+
it('should return whether the element is a void element', () => {
6+
expect(isVoidElement('img')).toBe(true);
7+
expect(isVoidElement('br')).toBe(true);
8+
expect(isVoidElement('div')).toBe(false);
9+
expect(isVoidElement('p')).toBe(false);
10+
});
11+
12+
});

0 commit comments

Comments
 (0)