Skip to content

Commit 7d3ccd4

Browse files
Add support for Fragments (#79)
* Add support for Fragments * Add test for sibling Fragments
1 parent fd7fa37 commit 7d3ccd4

File tree

4 files changed

+115
-4
lines changed

4 files changed

+115
-4
lines changed

src/index.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { encodeEntities, indent, isLargeString, styleObjToCss, assign, getChildren } from './util';
22
import { ENABLE_PRETTY } from '../env';
3-
import { options } from 'preact';
3+
import { options, Fragment } from 'preact';
44

55
const SHALLOW = { shallow: true };
66

@@ -59,6 +59,16 @@ function renderToString(vnode, context, opts, inner, isSvgMode) {
5959
if (opts.shallow && (inner || opts.renderRootComponent===false)) {
6060
nodeName = getComponentName(nodeName);
6161
}
62+
else if (nodeName===Fragment) {
63+
let rendered = '';
64+
let children = [];
65+
getChildren(children, vnode.props.children);
66+
67+
for (let i = 0; i < children.length; i++) {
68+
rendered += renderToString(children[i], context, opts, opts.shallowHighOrder!==false, isSvgMode);
69+
}
70+
return rendered;
71+
}
6272
else {
6373
let rendered;
6474

test/pretty.js

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { render as basicRender } from '../src';
22
import { render } from '../src/jsx';
3-
import { h } from 'preact';
3+
import { h, Fragment } from 'preact';
44
import chai, { expect } from 'chai';
55
import sinonChai from 'sinon-chai';
66
chai.use(sinonChai);
@@ -65,4 +65,35 @@ describe('pretty', () => {
6565
</div>
6666
)).to.equal(`<div>\n\t<span></span>\n</div>`);
6767
});
68+
69+
it('should not increase indentation with Fragments', () => {
70+
expect(prettyRender(
71+
<div>
72+
<Fragment><span /></Fragment>
73+
</div>
74+
)).to.equal(`<div>\n\t<span></span>\n</div>`);
75+
});
76+
77+
it('should not increase indentation with nested Fragments', () => {
78+
expect(prettyRender(
79+
<div>
80+
<Fragment>
81+
<Fragment><span /></Fragment>
82+
</Fragment>
83+
</div>
84+
)).to.equal(`<div>\n\t<span></span>\n</div>`);
85+
});
86+
87+
it('should not increase indentation with sibling Fragments', () => {
88+
expect(prettyRender(
89+
<div>
90+
<Fragment>
91+
<div>A</div>
92+
</Fragment>
93+
<Fragment>
94+
<div>B</div>
95+
</Fragment>
96+
</div>
97+
)).to.equal(`<div>\n\t<div>A</div>\n\t<div>B</div>\n</div>`);
98+
});
6899
});

test/render.js

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { render, shallowRender } from '../src';
2-
import { h, Component, createContext } from 'preact';
2+
import { h, Component, createContext, Fragment } from 'preact';
33
import { useState, useContext, useEffect } from 'preact/hooks';
44
import chai, { expect } from 'chai';
55
import { spy, stub, match } from 'sinon';
@@ -608,6 +608,67 @@ describe('render', () => {
608608
});
609609
});
610610

611+
describe('Fragments', () => {
612+
it('should skip Fragment node', () => {
613+
let html = render(<div><Fragment>foo</Fragment></div>);
614+
expect(html).to.equal('<div>foo</div>');
615+
});
616+
617+
it('should skip Fragment node with multiple children', () => {
618+
let html = render(
619+
<div>
620+
<Fragment>
621+
foo
622+
<span>bar</span>
623+
</Fragment>
624+
</div>
625+
);
626+
expect(html).to.equal('<div>foo<span>bar</span></div>');
627+
});
628+
629+
it('should skip Fragment node with multiple children #2', () => {
630+
let html = render(
631+
<div>
632+
<Fragment>
633+
<div>foo</div>
634+
<div>bar</div>
635+
</Fragment>
636+
</div>
637+
);
638+
expect(html).to.equal('<div><div>foo</div><div>bar</div></div>');
639+
});
640+
641+
it('should skip Fragment even if it has props', () => {
642+
let html = render(
643+
<div>
644+
<Fragment key="2">foo</Fragment>
645+
</div>
646+
);
647+
expect(html).to.equal('<div>foo</div>');
648+
});
649+
650+
it('should skip sibling Fragments', () => {
651+
let html = render(
652+
<div>
653+
<Fragment>foo</Fragment>
654+
<Fragment>bar</Fragment>
655+
</div>
656+
);
657+
expect(html).to.equal('<div>foobar</div>');
658+
});
659+
660+
it('should skip nested Fragments', () => {
661+
let html = render(
662+
<div>
663+
<Fragment>
664+
<Fragment>foo</Fragment>
665+
</Fragment>
666+
</div>
667+
);
668+
expect(html).to.equal('<div>foo</div>');
669+
});
670+
});
671+
611672
describe('hooks', () => {
612673
it('should not crash with hooks', () => {
613674
function Foo() {

test/shallowRender.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { shallowRender } from '../src';
2-
import { h } from 'preact';
2+
import { h, Fragment } from 'preact';
33
import chai, { expect } from 'chai';
44
import { spy } from 'sinon';
55
import sinonChai from 'sinon-chai';
@@ -33,4 +33,13 @@ describe('shallowRender()', () => {
3333
expect(rendered).to.equal(`<div bar="1"><b>test child</b><span>asdf</span></div>`);
3434
expect(Test).to.have.been.calledOnce;
3535
});
36+
37+
it('should ignore Fragments', () => {
38+
let rendered = shallowRender(
39+
<Fragment>
40+
<div>foo</div>
41+
</Fragment>
42+
);
43+
expect(rendered).to.equal(`<div>foo</div>`);
44+
});
3645
});

0 commit comments

Comments
 (0)