Skip to content

Commit 6194604

Browse files
committed
Serialize object style attributes to style strings. Fixes #7. Thanks @rmales!
1 parent b7745c6 commit 6194604

File tree

2 files changed

+40
-0
lines changed

2 files changed

+40
-0
lines changed

src/index.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,13 @@ const VOID_ELEMENTS = [
2727
'wbr'
2828
];
2929

30+
// DOM properties that should NOT have "px" added when numeric
31+
export const NON_DIMENSION_PROPS = {
32+
boxFlex:1, boxFlexGroup:1, columnCount:1, fillOpacity:1, flex:1, flexGrow:1,
33+
flexPositive:1, flexShrink:1, flexNegative:1, fontWeight:1, lineClamp:1, lineHeight:1,
34+
opacity:1, order:1, orphans:1, strokeOpacity:1, widows:1, zIndex:1, zoom:1
35+
};
36+
3037
// components without names, kept as a hash for later comparison to return consistent UnnamedComponentXX names.
3138
const UNNAMED = [];
3239

@@ -42,10 +49,33 @@ let escapeChar = a => ESC[a] || a;
4249

4350
let falsey = v => v==null || v===false;
4451

52+
let memoize = (fn, mem={}) => v => mem[v] || (mem[v] = fn(v));
53+
4554
let indent = (s, char) => String(s).replace(/(\n+)/g, '$1' + (char || '\t'));
4655

4756
let isLargeString = s => (String(s).length>40 || String(s).indexOf('\n')!==-1 || String(s).indexOf('<')!==-1);
4857

58+
function styleObjToCss(s) {
59+
let str = '';
60+
for (let prop in s) {
61+
let val = s[prop];
62+
if (val!=null) {
63+
if (str) str += ' ';
64+
str += jsToCss(prop);
65+
str += ': ';
66+
str += val;
67+
if (typeof val==='number' && !NON_DIMENSION_PROPS[prop]) {
68+
str += 'px';
69+
}
70+
str += ';';
71+
}
72+
}
73+
return str;
74+
}
75+
76+
// Convert a JavaScript camel-case CSS property name to a CSS property name
77+
let jsToCss = memoize( s => s.replace(/([A-Z])/g,'-$1').toLowerCase() );
78+
4979
function assign(obj, props) {
5080
for (let i in props) obj[i] = props[i];
5181
return obj;
@@ -152,6 +182,9 @@ export default function renderToString(vnode, context, opts, inner) {
152182
if (attributes['class']) continue;
153183
name = 'class';
154184
}
185+
if (name==='style' && v && typeof v==='object') {
186+
v = styleObjToCss(v);
187+
}
155188
if (name==='dangerouslySetInnerHTML') {
156189
html = v && v.__html;
157190
}

test/render.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,13 @@ describe('render', () => {
6464

6565
expect(rendered).to.equal(expected);
6666
});
67+
68+
it('should serialize object styles', () => {
69+
let rendered = render(<div style={{ color:'red', border:'none' }} />),
70+
expected = `<div style="color: red; border: none;"></div>`;
71+
72+
expect(rendered).to.equal(expected);
73+
});
6774
});
6875

6976
describe('Functional Components', () => {

0 commit comments

Comments
 (0)