Skip to content

Commit

Permalink
update htmlparser2 to v6 (#126)
Browse files Browse the repository at this point in the history
  • Loading branch information
pveyes authored Feb 18, 2021
1 parent a954d3b commit ffedb0f
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 184 deletions.
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
"homepage": "https://github.com/pveyes/htmr#readme",
"dependencies": {
"html-entities": "^1.2.1",
"htmlparser2": "^3.10.1"
"htmlparser2": "^6.0.0"
},
"peerDependencies": {
"react": "^15.6.1 || ^16.0.0"
Expand All @@ -61,6 +61,7 @@
"@types/react": "^16.8.8",
"benchmark": "^2.1.4",
"bundlesize": "^0.17.1",
"domhandler": "^4.0.0",
"husky": "^1.3.1",
"jest": "^24.5.0",
"npm-run-all": "^4.0.2",
Expand All @@ -74,7 +75,7 @@
"rollup-plugin-json": "^4.0.0",
"rollup-plugin-terser": "^5.0.0",
"rollup-plugin-typescript2": "^0.21.0",
"typescript": "^3.3.4000"
"typescript": "^4.1.5"
},
"husky": {
"hooks": {
Expand Down
33 changes: 16 additions & 17 deletions src/server.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { ReactNode } from 'react';
import Parser from 'htmlparser2';
import { parseDocument } from 'htmlparser2';
import { Node } from 'domhandler';
import { AllHtmlEntities as HtmlEntity } from 'html-entities';
import mapAttribute from './mapAttribute';

Expand All @@ -20,17 +21,15 @@ type TextNode = {
parent?: HTMLNode
}

type Node = HTMLNode | TextNode;

const TABLE_ELEMENTS = ['table', 'tbody', 'thead', 'tfoot', 'tr'];

function transform(node: Node, key: string, options: HtmrOptions): ReactNode {
function transform(childNode: Node, key: string, options: HtmrOptions): ReactNode {
const defaultTransform = options.transform._;

switch (node.type) {
switch (childNode.type) {
case 'script':
case 'style':
case 'tag': {
const node: HTMLNode = childNode as any;
const { name, attribs } = node;

// decode all attribute value
Expand All @@ -48,17 +47,16 @@ function transform(node: Node, key: string, options: HtmrOptions): ReactNode {

// if the tags children should be set dangerously
if (options.dangerouslySetChildren.indexOf(name) > -1) {

// Script tag can have empty children
// Tag can have empty children
if (node.children.length > 0) {
const childNode = <TextNode>(
node.children[0]
);
props.dangerouslySetInnerHTML = {
__html: childNode.data.trim(),
};
const childNode: TextNode = node.children[0] as any;
const html = name === 'style'
// preserve encoding on style tag
? childNode.data.trim()
: HtmlEntity.encode(childNode.data.trim());
props.dangerouslySetInnerHTML = { __html: html };
}

return customElement
? React.createElement(customElement as any, props, null)
: defaultTransform
Expand Down Expand Up @@ -86,6 +84,7 @@ function transform(node: Node, key: string, options: HtmrOptions): ReactNode {
return React.createElement(name, props, children);
}
case 'text': {
const node: TextNode = childNode as any;
let str = node.data;

if (node.parent && TABLE_ELEMENTS.indexOf(node.parent.name) > -1) {
Expand All @@ -112,8 +111,8 @@ export default function convertServer(html: string, options: Partial<HtmrOptions
dangerouslySetChildren: options.dangerouslySetChildren || ["style"],
};

const ast = Parser.parseDOM(html.trim(), {}) as Array<HTMLNode>;
const components = ast.map((node, index) => transform(node, index.toString(), opts));
const doc = parseDocument(html.trim(), {});
const components = doc.childNodes.map((node, index) => transform(node, index.toString(), opts));

if (components.length > 1) {
return components;
Expand Down
31 changes: 24 additions & 7 deletions test/convert.test.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
/* eslint-env jest */
import React from 'react';
import ReactDOM from 'react-dom';
import { renderToStaticMarkup, renderToString } from 'react-dom/server';
import renderer from 'react-test-renderer';
import { render } from '@testing-library/react';
import snapshot from 'jest-snapshot';
import diff from 'jest-diff';

import convertServer from '../src/server';
import convertBrowser from '../src/browser';
import htmrServer from '../src/server';
import htmrBrowser from '../src/browser';

test('convert correctly', () => {
const html = '<p id="test">This is cool</p>';
Expand All @@ -21,8 +23,8 @@ test('make sure HTML is string', () => {
expect.assertions(fixtures.length * 2);

fixtures.forEach(fixture => {
expect(() => convertServer(fixture)).toThrow(error);
expect(() => convertBrowser(fixture)).toThrow(error);
expect(() => htmrServer(fixture)).toThrow(error);
expect(() => htmrBrowser(fixture)).toThrow(error);
});
});

Expand Down Expand Up @@ -248,7 +250,7 @@ test('correctly handle boolean attributes', () => {
testRender(html);

// more test case just to make sure
const { container } = render(convertBrowser(html));
const { container } = render(htmrBrowser(html));
expect(container.querySelector('iframe').getAttribute('allowfullscreen')).toEqual('');
});

Expand Down Expand Up @@ -318,11 +320,26 @@ expect.extend({
*/

function testRender(html, options) {
let server = convertServer(html, options);
let browser = convertBrowser(html, options);
const server = htmrServer(html, options);
const browser = htmrBrowser(html, options);

expect({ server, browser }).toRenderConsistently(html);

// assert SSR
expect(() => renderToString(server)).not.toThrow();
expect(() => renderToStaticMarkup(server)).not.toThrow();

// assert CSR
const el = document.createElement('div');
try {
document.body.appendChild(el);
expect(() => {
ReactDOM.render(browser, el)
}).not.toThrow();
} finally {
document.body.removeChild(el);
}

// assert snapshot, doesn't matter from server or browser
// because we've already done assert equal between them
expect(renderer.create(server)).toMatchSnapshot();
Expand Down
118 changes: 0 additions & 118 deletions types/htmlparser2.d.ts

This file was deleted.

Loading

0 comments on commit ffedb0f

Please sign in to comment.