Skip to content

Commit 79e1be4

Browse files
committed
Render literals like vanilla js template strings
fixes developit#40 and developit#37 inspired by developit#41 The only place we don't have parity right now is arrays (because that's how children are passed) and bigint (because I'm not gonna do dependency wrangling rn)
1 parent 3fc484b commit 79e1be4

File tree

2 files changed

+108
-3
lines changed

2 files changed

+108
-3
lines changed

src/stringjsx.js

+7-3
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,9 @@ function render(tagName, attributes) {
8787

8888
const children = extractChildren(arguments);
8989
let result = '';
90+
const isFragment = tagName !== null && tagName !== undefined;
9091

91-
if (tagName) { // null is passed when rendering a fragment
92+
if (isFragment) {
9293
result += '<';
9394

9495
result += tagName;
@@ -104,7 +105,10 @@ function render(tagName, attributes) {
104105
} else while(children.length) {
105106
const child = children.shift();
106107

107-
if (!child) continue;
108+
if (child === undefined || child === null) {
109+
result += child;
110+
continue;
111+
}
108112

109113
if (isCollection(child)) {
110114
for (let i = child.length - 1; i >= 0; i--) {
@@ -116,7 +120,7 @@ function render(tagName, attributes) {
116120
}
117121
}
118122

119-
if (tagName) result += `</${tagName}>`;
123+
if (isFragment) result += `</${tagName}>`;
120124
}
121125

122126
// Read about the fun world of javascript strings

test/stringjsx.js

+101
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,14 @@ describe('stringjsx', () => {
269269
);
270270
});
271271

272+
it('also supports fragments w/ undefined', () => {
273+
expect(
274+
h(h.Fragment, null, <p>foo</p>, <em>bar</em>, <div class="qqqqqq">baz</div>).toString()
275+
).to.equal(
276+
'<p>foo</p><em>bar</em><div class="qqqqqq">baz</div>'
277+
);
278+
});
279+
272280
// regression test for https://github.com/developit/vhtml/issues/34
273281
it('does not allow cache-based html injection anymore', () => {
274282
const injectable = '<h1>test</h1>';
@@ -302,4 +310,97 @@ describe('stringjsx', () => {
302310
'<line class="second" y2="-38"></line></g></svg>'
303311
)
304312
});
313+
314+
describe('literal rendering', () => {
315+
it('renders the empty string', () => {
316+
expect(
317+
<div>{''}</div>.toString()
318+
).to.equal('<div></div>')
319+
});
320+
321+
it('renders blank strings', () => {
322+
expect(
323+
<div>{' '} and also {'\n\n\n \t\t\t'}</div>.toString()
324+
).to.equal('<div> and also \n\n\n \t\t\t</div>')
325+
});
326+
327+
it('renders a goofy string', () => {
328+
expect(
329+
<div>{'haha'}</div>.toString()
330+
).to.equal('<div>haha</div>')
331+
});
332+
333+
it('renders numbers', () => {
334+
expect(
335+
<div>
336+
{63452}
337+
<span>num: {12385}</span>
338+
<p>{-882}, {942}</p>
339+
</div>.toString()
340+
).to.equal('<div>63452<span>num: 12385</span><p>-882, 942</p></div>')
341+
});
342+
343+
it('renders infinities', () => {
344+
// impressive
345+
expect(
346+
<div>
347+
{Infinity}+{-Infinity}
348+
</div>.toString()
349+
).to.equal('<div>Infinity+-Infinity</div>')
350+
});
351+
352+
it('renders a "very big" number', () => {
353+
expect(
354+
<div>{5463454363452342352665745632523423423}</div>.toString()
355+
).to.equal('<div>5.463454363452342e+36</div>')
356+
});
357+
358+
// TODO: hmm maybe isn't supported by any node tooling yet?
359+
// it('renders a bigint', () => {
360+
// expect(
361+
// <div>{5463454363452342352665745632523423423n}</div>.toString()
362+
// ).to.equal('<div>5463454363452342352665745632523423423</div>')
363+
// });
364+
365+
// regression test for https://github.com/developit/vhtml/issues/40
366+
it('renders zero', () => {
367+
expect(
368+
<div>{0} elephants carrying {0} trees</div>.toString()
369+
).to.equal('<div>0 elephants carrying 0 trees</div>')
370+
});
371+
372+
it('renders booleans', () => {
373+
expect(
374+
<div>
375+
<p>{true} love</p>
376+
<th>{false} promises</th>
377+
</div>.toString()
378+
).to.equal('<div><p>true love</p><th>false promises</th></div>')
379+
});
380+
381+
it('renders undefined', () => {
382+
expect(<div>{undefined} behaviour</div>.toString())
383+
.to.equal('<div>undefined behaviour</div>')
384+
});
385+
386+
it('renders null', () => {
387+
expect(<div>{null} and void</div>.toString())
388+
.to.equal('<div>null and void</div>')
389+
});
390+
391+
it('"renders" an object', () => {
392+
expect(<div>object? {{}} object</div>.toString())
393+
.to.equal('<div>object? [object Object] object</div>')
394+
});
395+
396+
it('renders an array', () => {
397+
expect(<div>little bit of {['a', 'b']}</div>.toString())
398+
.to.equal('<div>little bit of ab</div>')
399+
});
400+
401+
it('renders a date', () => {
402+
expect(<div>@ {new Date(8.64e15)}</div>.toString())
403+
.to.equal('<div>@ Sat Sep 13 275760 02:00:00 GMT+0200 (Central European Summer Time)</div>')
404+
});
405+
});
305406
});

0 commit comments

Comments
 (0)