Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add void element checking to TagElementType #2

Merged
merged 2 commits into from
Jan 29, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# React HTML Parser

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.
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.

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

Expand Down
10 changes: 7 additions & 3 deletions src/elementTypes/TagElementType.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react';
import ProcessNodes from '../utils/ProcessNodes';
import GeneratePropsFromAttributes from '../utils/GeneratePropsFromAttributes';
import TransformTagName from '../utils/TransformTagName';
import isVoidElement from '../utils/isVoidElement';

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

// If the node has children process them
const children = ProcessNodes(node.children);

// generate props
const props = GeneratePropsFromAttributes(node.attribs, key);

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

// If the node is not a void element and has children then process them
let children = null;
if (!isVoidElement(tagName)) {
children = ProcessNodes(node.children);
}

// create and return the element
return React.createElement(tagName, props, children);
}
24 changes: 24 additions & 0 deletions src/utils/isVoidElement.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
const voidElements = [
'area',
'base',
'br',
'col',
'command',
'embed',
'hr',
'img',
'input',
'keygen',
'link',
'meta',
'param',
'source',
'track',
'wbr'
];

export default function isVoidElement(element) {

return voidElements.indexOf(element) >= 0;

}
4 changes: 4 additions & 0 deletions test/integration/integration.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,8 @@ describe('Integration tests: ', () => {
test('<body>test</body>', '<div>test</div>');
});

it('should not allow nesting of void elements', () => {
test('<img><p>test</p></img>', '<img/><p>test</p>');
});

});
22 changes: 21 additions & 1 deletion test/unit/elementTypes/TagElementType.spec.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
const GeneratePropsFromAttributes = jasmine.createSpy('GeneratePropsFromAttributes').and.callFake(attrs => attrs);
const ProcessNodes = jasmine.createSpy('ProcessNodes').and.returnValue('children');
const isVoidElement = jasmine.createSpy('isVoidElement').and.returnValue(false);

const TagElementType = require('inject!elementTypes/TagElementType')({
'../utils/GeneratePropsFromAttributes': GeneratePropsFromAttributes,
'../utils/ProcessNodes': ProcessNodes
'../utils/ProcessNodes': ProcessNodes,
'../utils/isVoidElement': isVoidElement
}).default;

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

beforeEach(() => {
GeneratePropsFromAttributes.calls.reset();
ProcessNodes.calls.reset();
isVoidElement.calls.reset();
});

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

});

it('should not pass though children for void elements', () => {

const voidNode = {
name: 'void',
attribs: {
id: 'test'
},
children: 'child'
};
isVoidElement.and.returnValue(true);

const voidElement = TagElementType(voidNode, 'key');
expect(voidElement.type).toBe('void');
expect(voidElement.props.children).toBe(null);

});

});
12 changes: 12 additions & 0 deletions test/unit/utils/isVoidElement.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import isVoidElement from 'utils/isVoidElement';

describe('Testing `utils/isVoidElement`', () => {

it('should return whether the element is a void element', () => {
expect(isVoidElement('img')).toBe(true);
expect(isVoidElement('br')).toBe(true);
expect(isVoidElement('div')).toBe(false);
expect(isVoidElement('p')).toBe(false);
});

});