Skip to content

Commit 50d6f09

Browse files
Bunch of fixes for attributes with SSR (#115)
* Add failing attribute tests for SSR * fix empty values, event handlers with or without quotes * fix boolean props * fix object spread * reduce
1 parent 85abb02 commit 50d6f09

File tree

2 files changed

+76
-5
lines changed

2 files changed

+76
-5
lines changed

lib/server.js

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
var BOOL_PROPS = require('./bool-props')
2+
3+
var boolPropRx = new RegExp('(' + BOOL_PROPS.join('|') + ')=["\']?$', 'i')
4+
15
module.exports = nanothtmlServer
26

37
function nanothtmlServer (src, filename, options, done) {
@@ -9,12 +13,28 @@ function nanothtmlServer (src, filename, options, done) {
913
return require('./babel').apply(this, arguments)
1014
}
1115

16+
var boolMatch
1217
var pieces = arguments[0]
1318
var output = ''
1419
for (var i = 0; i < pieces.length; i++) {
15-
output += pieces[i]
20+
var piece = pieces[i]
1621
if (i < pieces.length - 1) {
17-
output += handleValue(arguments[i + 1])
22+
if ((boolMatch = boolPropRx.exec(piece))) {
23+
output += piece.slice(0, boolMatch.index)
24+
if (arguments[i + 1]) {
25+
output += boolMatch[1] + '="' + boolMatch[1] + '"'
26+
}
27+
continue
28+
}
29+
30+
var value = handleValue(arguments[i + 1])
31+
if (piece[piece.length - 1] === '=') {
32+
output += piece + '"' + value + '"'
33+
} else {
34+
output += piece + value
35+
}
36+
} else {
37+
output += piece
1838
}
1939
}
2040

@@ -32,9 +52,26 @@ function handleValue (value) {
3252

3353
// Ignore event handlers. `onclick=${(e) => doSomething(e)}`
3454
// will become. `onclick=""`
35-
if (typeof value === 'function') return '""'
55+
if (typeof value === 'function') return ''
3656
if (value === null || value === undefined) return ''
3757
if (value.__encoded) return value
58+
59+
if (typeof value === 'object') {
60+
return Object.keys(value).reduce(function (str, key, i) {
61+
if (str.length > 0) str += ' '
62+
63+
if (BOOL_PROPS.indexOf(key) !== -1) {
64+
if (value[key]) {
65+
return str + key + '="' + key + '"'
66+
}
67+
return str
68+
}
69+
70+
var handled = handleValue(value[key])
71+
return str + key + '="' + handled + '"'
72+
}, '')
73+
}
74+
3875
var str = value.toString()
3976
return str
4077
.replace(/&/g, '&amp;')

tests/server/index.js

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ test('unescape html', function (t) {
3939
var expected = '<span>Hello <strong>there</strong></span>'
4040
var result = raw('<span>Hello <strong>there</strong></span>').toString()
4141

42-
t.equal(expected, result)
42+
t.equal(result, expected)
4343
t.end()
4444
})
4545

@@ -49,6 +49,40 @@ test('unescape html inside html', function (t) {
4949
var expected = '<span>Hello <strong>there</strong></span>'
5050
var result = html`${raw('<span>Hello <strong>there</strong></span>')}`.toString()
5151

52-
t.equal(expected, result)
52+
t.equal(result, expected)
53+
t.end()
54+
})
55+
56+
test('event attribute', function (t) {
57+
t.plan(1)
58+
59+
var expected = '<div onmouseover="" onmouseout="">Hello</div>'
60+
var result = html`<div onmouseover=${onmouseover} onmouseout="${onmouseout}">Hello</div>`.toString()
61+
62+
t.equal(result, expected)
63+
t.end()
64+
65+
function onmouseover () {}
66+
function onmouseout () {}
67+
})
68+
69+
test('boolean attribute', function (t) {
70+
t.plan(1)
71+
72+
var expected = '<input disabled="disabled" >'
73+
var result = html`<input disabled=${true} autofocus=${false}>`.toString()
74+
75+
t.equal(result, expected)
76+
t.end()
77+
})
78+
79+
test('spread attributes', function (t) {
80+
t.plan(1)
81+
82+
var expected = '<div class="abc" id="def">Hello</div>'
83+
var props = { class: 'abc', id: 'def' }
84+
var result = html`<div ${props}>Hello</div>`.toString()
85+
86+
t.equal(result, expected)
5387
t.end()
5488
})

0 commit comments

Comments
 (0)