Skip to content

Commit

Permalink
Merge pull request #3 from dodoas/render-interpolated-values-correctly
Browse files Browse the repository at this point in the history
Render interpolated values correctly
  • Loading branch information
odinhb authored Mar 8, 2024
2 parents 3fc484b + da5a52b commit d586b27
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 3 deletions.
31 changes: 31 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Changed

- Render nulls, undefined, zeroes and false correctly and more in line with how template strings do.

### [3.0.0] - 2023-07-07

- This version marks the fork from [vhtml](https://www.npmjs.com/package/vhtml)

### Added

- Typescript support (no additional @types/ package is required) (thanks to [pastelmind](https://github.com/pastelmind) for his type definitions for vhtml, these are simply adapted from his by @odinhb)
- New way to skip sanitization by passing a string with `_stringjsx_sanitized = true` set. ([remziatay](https://github.com/remziatay) had the idea [here](https://github.com/developit/vhtml/issues/34#issuecomment-1460436783))

### Changed

- Returns a `String` (object, not primitive) ([remziatay](https://github.com/remziatay) had the idea [here](https://github.com/developit/vhtml/issues/34#issuecomment-1460436783))
- Rewrote the source code itself (@odinhb)

### Fixed

- Fix [injection possibility](https://github.com/developit/vhtml/issues/34)
- Fix [memory leak](https://github.com/developit/vhtml/issues/20)
10 changes: 7 additions & 3 deletions src/stringjsx.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,9 @@ function render(tagName, attributes) {

const children = extractChildren(arguments);
let result = '';
const isFragment = tagName !== null && tagName !== undefined;

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

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

if (!child) continue;
if (child === undefined || child === null) {
result += child;
continue;
}

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

if (tagName) result += `</${tagName}>`;
if (isFragment) result += `</${tagName}>`;
}

// Read about the fun world of javascript strings
Expand Down
105 changes: 105 additions & 0 deletions test/stringjsx.js
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,14 @@ describe('stringjsx', () => {
);
});

it('also supports fragments w/ undefined', () => {
expect(
h(h.Fragment, null, <p>foo</p>, <em>bar</em>, <div class="qqqqqq">baz</div>).toString()
).to.equal(
'<p>foo</p><em>bar</em><div class="qqqqqq">baz</div>'
);
});

// regression test for https://github.com/developit/vhtml/issues/34
it('does not allow cache-based html injection anymore', () => {
const injectable = '<h1>test</h1>';
Expand Down Expand Up @@ -302,4 +310,101 @@ describe('stringjsx', () => {
'<line class="second" y2="-38"></line></g></svg>'
)
});

describe('literal rendering', () => {
it('renders the empty string', () => {
expect(
<div>{''}</div>.toString()
).to.equal('<div></div>')
});

it('renders blank strings', () => {
expect(
<div>{' '} and also {'\n\n\n \t\t\t'}</div>.toString()
).to.equal('<div> and also \n\n\n \t\t\t</div>')
});

it('renders a goofy string', () => {
expect(
<div>{'haha'}</div>.toString()
).to.equal('<div>haha</div>')
});

it('renders numbers', () => {
expect(
<div>
{63452}
<span>num: {12385}</span>
<p>{-882}, {942}</p>
</div>.toString()
).to.equal('<div>63452<span>num: 12385</span><p>-882, 942</p></div>')
});

it('renders infinities', () => {
// impressive
expect(
<div>
{Infinity}+{-Infinity}
</div>.toString()
).to.equal('<div>Infinity+-Infinity</div>')
});

it('renders a "very big" number', () => {
expect(
<div>{5463454363452342352665745632523423423}</div>.toString()
).to.equal('<div>5.463454363452342e+36</div>')
});

// TODO: hmm maybe isn't supported by any node tooling yet?
// it('renders a bigint', () => {
// expect(
// <div>{5463454363452342352665745632523423423n}</div>.toString()
// ).to.equal('<div>5463454363452342352665745632523423423</div>')
// });

// regression test for https://github.com/developit/vhtml/issues/40
it('renders zero', () => {
expect(
<div>{0} elephants carrying {0} trees</div>.toString()
).to.equal('<div>0 elephants carrying 0 trees</div>')
});

it('renders booleans', () => {
expect(
<div>
<p>{true} love</p>
<th>{false} promises</th>
</div>.toString()
).to.equal('<div><p>true love</p><th>false promises</th></div>')
});

it('renders undefined', () => {
expect(<div>{undefined} behaviour</div>.toString())
.to.equal('<div>undefined behaviour</div>')
});

it('renders null', () => {
expect(<div>{null} and void</div>.toString())
.to.equal('<div>null and void</div>')
});

it('"renders" an object', () => {
expect(<div>object? {{}} object</div>.toString())
.to.equal('<div>object? [object Object] object</div>')
});

it('renders an array', () => {
expect(<div>little bit of {['a', 'b']}</div>.toString())
.to.equal('<div>little bit of ab</div>')
});

it('renders toString', () => {
const instrument = {
toString: function() { return 'ukulele' },
}

expect(<div>instrument: {instrument}</div>.toString())
.to.equal('<div>instrument: ukulele</div>')
});
});
});

0 comments on commit d586b27

Please sign in to comment.