style prop improvements

Some improvements to how style={{x:y}} is handled in React:
* ignores null styles, rather than setting them.

Codez:

    var highlighted = false;
    <div style={{color: highlighted ? 'red' : null}} />

Before:

    <div style="color:;"></div>

After:

    <div></div>

Respects that 0 has no units.
This commit is contained in:
CommitSyncScript
2013-06-04 12:15:13 -07:00
committed by Paul O’Shannessy
parent 007b75f78a
commit 93fc188afb
4 changed files with 57 additions and 13 deletions
+3 -4
View File
@@ -19,20 +19,19 @@
"use strict";
/**
* CSS properties for which we do not append "px".
* CSS properties which accept numbers but are not in units of "px".
*/
var isNumber = {
var isUnitlessNumber = {
fillOpacity: true,
fontWeight: true,
opacity: true,
orphans: true,
textDecoration: true,
zIndex: true,
zoom: true
};
var CSSProperty = {
isNumber: isNumber
isUnitlessNumber: isUnitlessNumber
};
module.exports = CSSProperty;
+3 -3
View File
@@ -42,7 +42,7 @@ var CSSPropertyOperations = {
* Undefined values are ignored so that declarative programming is easier.
*
* @param {object} styles
* @return {string}
* @return {?string}
*/
createMarkupForStyles: function(styles) {
var serialized = '';
@@ -51,12 +51,12 @@ var CSSPropertyOperations = {
continue;
}
var styleValue = styles[styleName];
if (typeof styleValue !== 'undefined') {
if (styleValue != null) {
serialized += processStyleName(styleName) + ':';
serialized += dangerousStyleValue(styleName, styleValue) + ';';
}
}
return serialized;
return serialized || null;
},
/**
@@ -19,6 +19,8 @@
"use strict";
var React = require('React');
describe('CSSPropertyOperations', function() {
var CSSPropertyOperations;
@@ -41,12 +43,49 @@ describe('CSSPropertyOperations', function() {
})).toBe('display:none;');
});
it('should ignore null styles', function() {
expect(CSSPropertyOperations.createMarkupForStyles({
backgroundColor: null,
display: 'none'
})).toBe('display:none;');
});
it('should return null for no styles', function() {
expect(CSSPropertyOperations.createMarkupForStyles({
backgroundColor: null,
display: null
})).toBe(null);
});
it('should automatically append `px` to relevant styles', function() {
expect(CSSPropertyOperations.createMarkupForStyles({
left: 0,
margin: 16,
opacity: 0.5,
padding: '4px'
})).toBe('margin:16px;opacity:0.5;padding:4px;');
})).toBe('left:0;margin:16px;opacity:0.5;padding:4px;');
});
it('should set style attribute when styles exist', function() {
var styles = {
backgroundColor: '#000',
display: 'none'
};
var div = <div style={styles} />;
var root = document.createElement('div');
React.renderComponent(div, root);
expect(/style=".*"/.test(root.innerHTML)).toBe(true);
});
it('should not set style attribute when no styles exist', function() {
var styles = {
backgroundColor: null,
display: null
};
var div = <div style={styles} />;
var root = document.createElement('div');
React.renderComponent(div, root);
expect(/style=".*"/.test(root.innerHTML)).toBe(false);
});
});
+11 -5
View File
@@ -23,7 +23,8 @@ var CSSProperty = require('CSSProperty');
/**
* Convert a value into the proper css writable value. The `styleName` name
* name should be logical (no hyphens), as specified in `CSSProperty.isNumber`.
* name should be logical (no hyphens), as specified
* in `CSSProperty.isUnitlessNumber`.
*
* @param {string} styleName CSS property name such as `topMargin`.
* @param {*} value CSS property value such as `10px`.
@@ -39,13 +40,18 @@ function dangerousStyleValue(styleName, value) {
// This is not an XSS hole but instead a potential CSS injection issue
// which has lead to a greater discussion about how we're going to
// trust URLs moving forward. See #2115901
if (value === null || value === false || value === true || value === '') {
var isEmpty = value == null || typeof value === 'boolean' || value === '';
if (isEmpty) {
return '';
}
if (isNaN(value)) {
return !value ? '' : '' + value;
var isNonNumeric = isNaN(value);
if (isNonNumeric || value === 0 || CSSProperty.isUnitlessNumber[styleName]) {
return '' + value; // cast to string
}
return CSSProperty.isNumber[styleName] ? '' + value : (value + 'px');
return value + 'px';
}
module.exports = dangerousStyleValue;