@hedgedoc/html-to-react
Version:
Parse HTML into React components
144 lines • 7.33 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const server_1 = require("react-dom/server");
const convertHtmlToReact_js_1 = require("./convertHtmlToReact.js");
const convertNodeToReactElement_js_1 = require("./convertNodeToReactElement.js");
const domhandler_1 = require("domhandler");
const react_1 = __importDefault(require("react"));
const globals_1 = require("@jest/globals");
const expectSameHtml = function (html, options = {}) {
const actual = (0, server_1.renderToStaticMarkup)(react_1.default.createElement("div", null, (0, convertHtmlToReact_js_1.convertHtmlToReact)(html, options)));
const expected = `<div>${html}</div>`;
(0, globals_1.expect)(actual).toBe(expected);
};
const expectOtherHtml = function (html, override, options = {}) {
const actual = (0, server_1.renderToStaticMarkup)(react_1.default.createElement("div", null, (0, convertHtmlToReact_js_1.convertHtmlToReact)(html, options)));
const expected = `<div>${override}</div>`;
(0, globals_1.expect)(actual).toBe(expected);
};
(0, globals_1.describe)('Integration tests: ', () => {
(0, globals_1.it)('should render a simple element', () => {
expectSameHtml('<div>test</div>');
});
(0, globals_1.it)('should render multiple sibling elements', () => {
expectSameHtml('<div>test1</div><span>test2</span><footer>test3</footer>');
});
(0, globals_1.it)('should render nested elements', () => {
expectSameHtml('<div><span>test1</span><div><ul><li>test2</li><li>test3</li></ul></div></div>');
});
(0, globals_1.it)('should handle bad html', () => {
expectOtherHtml('<div class=test>test<ul><li>test1<li>test2</ul><span>test</span></div>', '<div class="test">test<ul><li>test1</li><li>test2</li></ul><span>test</span></div>');
});
(0, globals_1.it)('should ignore doctypes', () => {
expectOtherHtml('<!doctype html><div>test</div>', '<div>test</div>');
});
(0, globals_1.it)('should ignore comments', () => {
expectOtherHtml('<div>test1</div><!-- comment --><div>test2</div>', '<div>test1</div><div>test2</div>');
});
(0, globals_1.it)('should ignore script tags', () => {
expectOtherHtml('<script>alert(1)</script>', '');
});
(0, globals_1.it)('should ignore event handlers', () => {
expectOtherHtml('<a href="#" onclick="alert(1)">test</a>', '<a href="#">test</a>');
});
(0, globals_1.it)('should handle attributes', () => {
expectSameHtml('<div class="test" id="test" aria-valuetext="test" data-test="test">test</div>');
});
(0, globals_1.it)('should handle inline styles', () => {
expectSameHtml('<div style="border-radius:1px;background:red">test</div>');
});
(0, globals_1.it)('should ignore inline styles that are empty strings', () => {
expectOtherHtml('<div style="">test</div>', '<div>test</div>');
});
(0, globals_1.it)('should not allow nesting of void elements', () => {
expectOtherHtml('<input><p>test</p></input>', '<input/><p>test</p>');
});
(0, globals_1.it)('should convert boolean attribute values', () => {
expectOtherHtml('<input disabled>', '<input disabled=""/>');
expectOtherHtml('<input disabled="">', '<input disabled=""/>');
expectOtherHtml('<input disabled="disabled">', '<input disabled=""/>');
});
[
['CONTENTEDITABLE', 'contentEditable'],
['LABEL', 'label'],
['iTemREF', 'itemRef']
].forEach(([attr, prop]) => {
(0, globals_1.it)(`should convert attribute ${attr} to prop ${prop}`, () => {
const nodes = (0, convertHtmlToReact_js_1.convertHtmlToReact)(`<div ${attr}/>`, {});
(0, globals_1.expect)(nodes).toHaveLength(1);
(0, globals_1.expect)(nodes[0].props).toHaveProperty(prop);
});
});
(0, globals_1.it)('should decode html entities by default', () => {
expectOtherHtml('<span>!</span>', '<span>!</span>');
});
(0, globals_1.it)('should not decode html entities when the option is disabled', () => {
expectOtherHtml('<span>!</span>', '<span>&excl;</span>', {
decodeEntities: false
});
});
(0, globals_1.describe)('transform function', () => {
(0, globals_1.it)('should use the response when it is not undefined', () => {
expectOtherHtml('<span>test</span><div>another</div>', '<p>transformed</p><p>transformed</p>', {
transform(node, index) {
return react_1.default.createElement("p", { key: index }, "transformed");
}
});
});
(0, globals_1.it)('should not render elements and children when returning null', () => {
expectOtherHtml('<p>test<span>inner test<b>bold child</b></span></p>', '<p>test</p>', {
transform(node) {
if ((0, domhandler_1.isTag)(node) && node.type === 'tag' && node.name === 'span') {
return null;
}
}
});
});
(0, globals_1.it)('should allow modifying nodes', () => {
expectOtherHtml('<a href="/test">test link</a>', '<a href="/changed">test link</a>', {
transform(node, index) {
if ((0, domhandler_1.isTag)(node)) {
node.attribs.href = '/changed';
}
return (0, convertNodeToReactElement_js_1.convertNodeToReactElement)(node, index);
}
});
});
(0, globals_1.it)('should allow passing the transform function down to children', () => {
const transform = (node, index) => {
if ((0, domhandler_1.isTag)(node)) {
if (node.name === 'ul') {
node.attribs.class = 'test';
return (0, convertNodeToReactElement_js_1.convertNodeToReactElement)(node, index, transform);
}
}
else if ((0, domhandler_1.isText)(node)) {
return node.data.replace(/list/, 'changed');
}
else {
return null;
}
};
expectOtherHtml('<ul><li>list 1</li><li>list 2</li></ul>', '<ul class="test"><li>changed 1</li><li>changed 2</li></ul>', {
transform
});
});
});
(0, globals_1.it)('should not render invalid tags', () => {
expectOtherHtml('<div>test<test</div>', '<div>test</div>');
});
(0, globals_1.it)('should not render invalid attributes', () => {
expectOtherHtml('<div data-test<="test" class="test">content</div>', '<div class="test">content</div>');
});
(0, globals_1.it)('should preprocess nodes correctly', () => {
expectOtherHtml('<div>preprocess test</div>', '<div>preprocess test</div><div>preprocess test</div>', {
preprocessNodes(document) {
return new domhandler_1.Document([...document.childNodes, ...document.childNodes]);
}
});
});
});
//# sourceMappingURL=index.spec.js.map