@mapbox/hast-util-to-jsx
Version:
242 lines (205 loc) • 7.79 kB
JavaScript
'use strict';
// These tests are copied from the htmltojsx package, to ensure feature parity.
const unified = require('unified');
const rehypeParse = require('rehype-parse');
const toJsx = require('..');
function htmlToJsx(html) {
const ast = unified()
.use(rehypeParse, { fragment: true })
.parse(html);
return toJsx(ast);
}
test('should handle basic HTML', function() {
expect(htmlToJsx('<div>Hello world!</div>')).toBe('<div>Hello world!</div>');
});
test('should handle HTML comments', function() {
expect(htmlToJsx('<!-- Hello World -->')).toBe('{/* Hello World */}');
});
test('should convert tags to lowercase', function() {
expect(htmlToJsx('<DIV>Hello world!</DIV>')).toBe('<div>Hello world!</div>');
});
test('handles single-line script tag', function() {
expect(htmlToJsx('<div>foo<script>lol</script>bar</div>')).toBe(
'<div>foo<script>lol</script>bar</div>'
);
});
test('handles multi-line script tag', function() {
const input = `<div>foo<script>
lol
lolz
</script>bar</div>`;
expect(htmlToJsx(input)).toBe(input);
});
describe('escaped characters', function() {
test('should handle escaped < symbols', function() {
expect(htmlToJsx('<div><</div>')).toBe('<div><</div>');
});
test('should handle unescaped copyright symbols', function() {
expect(htmlToJsx('<div>©</div>')).toBe('<div>©</div>');
});
});
describe('Attribute transformations', function() {
test('should convert basic "style" attributes', function() {
expect(htmlToJsx('<div style="color: red">Test</div>')).toBe(
'<div style={{color: "red"}}>Test</div>'
);
});
test('should convert CSS shorthand "style" values', function() {
expect(
htmlToJsx('<div style="padding: 10px 15px 20px 25px;">Test</div>')
).toBe('<div style={{padding: "10px 15px 20px 25px"}}>Test</div>');
});
test('should convert numeric "style" attributes', function() {
expect(htmlToJsx('<div style="width: 100px">Test</div>')).toBe(
'<div style={{width: "100px"}}>Test</div>'
);
});
test('should convert dashed "style" attributes', function() {
expect(htmlToJsx('<div style="font-size: 12pt">Test</div>')).toBe(
'<div style={{fontSize: "12pt"}}>Test</div>'
);
});
test('should convert vendor-prefix "style" attributes', function() {
expect(
htmlToJsx(
'<div style="-moz-hyphens: auto; -webkit-hyphens: auto">Test</div>'
)
).toBe(
'<div style={{MozHyphens: "auto", WebkitHyphens: "auto"}}>Test</div>'
);
});
// Waiting on fix in postcss-js ...
// test('should convert uppercase vendor-prefix "style" attributes', function() {
// expect(
// htmlToJsx(
// '<div style="-MOZ-HYPHENS: auto; -WEBKIT-HYPHENS: auto">Test</div>'
// )
// ).toBe(
// '<div style={{MozHyphens: "auto", WebkitHyphens: "auto"}}>Test</div>'
// );
// });
test('should convert "style" attributes with vendor prefix-like strings in the middle and mixed case', function() {
expect(
htmlToJsx(
'<div style="myclass-moz-hyphens: auto; myclass-webkit-hyphens: auto">Test</div>'
)
).toBe(
'<div style={{myclassMozHyphens: "auto", myclassWebkitHyphens: "auto"}}>Test</div>'
);
});
test('should convert -ms- prefix "style" attributes', function() {
expect(htmlToJsx('<div style="-ms-hyphens: auto">Test</div>')).toBe(
'<div style={{msHyphens: "auto"}}>Test</div>'
);
});
test('should convert "style" attributes with -ms- in the middle', function() {
expect(htmlToJsx('<div style="myclass-ms-hyphens: auto">Test</div>')).toBe(
'<div style={{myclassMsHyphens: "auto"}}>Test</div>'
);
});
// Waiting on fix in postcss-js ...
// test('should convert uppercase "style" attributes', function() {
// expect(htmlToJsx('<div style="TEXT-ALIGN: center">Test</div>')).toBe(
// '<div style={{textAlign: "center"}}>Test</div>'
// );
// });
test('should convert "class" attribute', function() {
expect(htmlToJsx('<div class="awesome">Test</div>')).toBe(
'<div className="awesome">Test</div>'
);
});
test('should convert "for" attribute', function() {
expect(htmlToJsx('<label for="potato">Test</label>')).toBe(
'<label htmlFor="potato">Test</label>'
);
});
test('should convert "maxlength" attribute to "maxLength"', function() {
expect(htmlToJsx('<input maxlength=2></input>')).toBe(
'<input maxLength={2} />'
);
});
test('should convert "http-equiv" attribute to "httpEquiv"', function() {
expect(htmlToJsx('<meta http-equiv="refresh">')).toBe(
'<meta httpEquiv="refresh" />'
);
});
test('should convert "accept-charset" attribute to "acceptCharset"', function() {
expect(htmlToJsx('<form accept-charset="UTF-8">Test</form>')).toBe(
'<form acceptCharset="UTF-8">Test</form>'
);
});
test('should convert "enctype" attribute to "encType"', function() {
expect(
htmlToJsx(
'<form method="post" enctype="application/x-www-form-urlencoded">Test</form>'
)
).toBe(
'<form method="post" encType="application/x-www-form-urlencoded">Test</form>'
);
});
test('should maintain value-less attributes', function() {
expect(htmlToJsx('<input disabled>')).toBe('<input disabled={true} />');
});
test('should set <input> "value" to "defaultValue" to allow input editing', function() {
expect(htmlToJsx('<input value="Darth Vader">')).toBe(
'<input defaultValue="Darth Vader" />'
);
});
test('should not set "value" to "defaultValue" for non-<input> elements', function() {
expect(htmlToJsx('<select><option value="Hans"></select>')).toBe(
'<select><option value="Hans" /></select>'
);
});
test('should set <input> "checked" to "defaultChecked" to allow box checking', function() {
expect(htmlToJsx('<input type="checkbox" checked>')).toBe(
'<input type="checkbox" defaultChecked={true} />'
);
});
// HAST does not handle SVG well yet.
// test('should convert SVG attributes', function() {
// expect(
// htmlToJsx(
// '<svg height="100" width="100"><circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" fill-rule="evenodd"/></svg>'
// )
// ).toBe(
// '<svg height={100} width={100}><circle cx={50} cy={50} r={40} stroke="black" strokeWidth={3} fill="red" fillRule="evenodd" /></svg>'
// );
// });
});
describe('special tags', function() {
test('should use "defaultValue" for textareas', function() {
expect(htmlToJsx('<textarea>hello\nworld</textarea>')).toBe(
'<textarea defaultValue="hello\\nworld" />'
);
});
test('should do magic voodoo for <pre>', function() {
expect(htmlToJsx('<pre>hello\nworld{foo}</pre>')).toBe(
'<pre>hello{"\\n"}world{"{"}foo{"}"}</pre>'
);
});
test('should handle <pre> tags with children', function() {
expect(
htmlToJsx('<pre><b>Hello world yo</b>this is a<i> test</i></pre>')
).toBe(
'<pre><b>Hello world{" "}yo</b>this{" "}is{" "}a<i>{" "}test</i></pre>'
);
});
test('should dangerously set <style> tag contents', function() {
expect(
htmlToJsx(
'<style>\nh1 {\n background: url("http://foo.bar/img.jpg";\n}\n</style>'
)
).toBe(
'<style dangerouslySetInnerHTML={{__html: "\\nh1 {\\n background: url(\\"http://foo.bar/img.jpg\\";\\n}\\n" }} />'
);
});
test('should convert svg tag names', function() {
expect(
htmlToJsx(
'<svg><clipPath><feSpotLight><linearGradient></linearGradient></feSpotLight></clipPath></svg>'
)
).toBe(
'<svg><clipPath><feSpotLight><linearGradient /></feSpotLight></clipPath></svg>'
);
});
});