[Pkg-javascript-commits] [node-cssstyle] 21/39: 0 -> 0px, 0 -> 0%, empty and null values special cases, width and height use parseMeasurement, more test cases
Wolfgang Borgert
debacle at moszumanska.debian.org
Sat Sep 20 20:22:35 UTC 2014
This is an automated email from the git hooks/post-receive script.
debacle pushed a commit to branch master
in repository node-cssstyle.
commit 9ac39a2a109bf37570725d521573713782f6ae9b
Author: Chad Walker <chad at chad-cat-lore-eddie.com>
Date: Tue Nov 26 15:12:03 2013 -0600
0 -> 0px, 0 -> 0%, empty and null values special cases, width and height use parseMeasurement, more test cases
- all parsers that can accept just numbers change those into strings
- all parsers check that their values are strings
- empty string and null values are special cased to pass through
- parseLength special cases 0 and '0' and returns '0px'
- parsePercent special cases 0 and '0' and return '0%'
- parseMeasurement calls parseLength first and if that succeeds, returns it, otherwise calls parsePercent
- width and height use parseMeasurement
- test cases for all of the above
---
lib/parsers.js | 143 +++++++++++++++++++++++++++++++-----------
lib/properties/borderColor.js | 15 ++++-
lib/properties/borderStyle.js | 14 ++++-
lib/properties/borderWidth.js | 29 ++++++++-
lib/properties/height.js | 4 +-
lib/properties/width.js | 4 +-
tests/tests.js | 40 ++++++++++--
7 files changed, 199 insertions(+), 50 deletions(-)
diff --git a/lib/parsers.js b/lib/parsers.js
index 3707270..6e31bc5 100644
--- a/lib/parsers.js
+++ b/lib/parsers.js
@@ -13,13 +13,14 @@ exports.TYPES = {
COLOR: 6,
STRING: 7,
ANGLE: 8,
- KEYWORD: 9
+ KEYWORD: 9,
+ NULL_OR_EMPTY_STR: 10
};
// rough regular expressions
var integerRegEx = /^[\-+]?[0-9]+$/;
var numberRegEx = /^[\-+]?[0-9]*\.[0-9]+$/;
-var lengthRegEx = /^[\-+]?[0-9]?\.?[0-9]+(in|cm|mm|pt|pc|px)$/;
+var lengthRegEx = /^(0|[\-+]?[0-9]?\.?[0-9]+(in|cm|mm|pt|pc|px))$/;
var percentRegEx = /^[\-+]?[0-9]?\.?[0-9]+%$/;
var urlRegEx = /^url\(\s*([^\)]*)\s*\)$/;
var stringRegEx = /^("[^"]*"|'[^']*')$/;
@@ -30,11 +31,22 @@ var angleRegEx = /^([\-+]?[0-9]?\.?[0-9]+)(deg|grad|rad)$/;
// This will return one of the above types based on the passed in string
exports.valueType = function valueType(val) {
- if (integerRegEx.test(val)) {
- return exports.TYPES.INTEGER;
+ if (val === '' || val === null) {
+ return exports.TYPES.NULL_OR_EMPTY_STR;
}
- if (numberRegEx.test(val)) {
- return exports.TYPES.NUMBER;
+ if (typeof val === 'number') {
+ val = val.toString();
+ if (integerRegEx.test(val)) {
+ return exports.TYPES.INTEGER;
+ }
+ if (numberRegEx.test(val)) {
+ return exports.TYPES.NUMBER;
+ }
+ // shouldn't get here
+ return undefined;
+ }
+ if (typeof val !== 'string') {
+ return undefined;
}
if (lengthRegEx.test(val)) {
return exports.TYPES.LENGTH;
@@ -133,42 +145,69 @@ exports.valueType = function valueType(val) {
};
exports.parseInteger = function parseInteger(val) {
- if (exports.valueType(val) !== exports.TYPES.INTEGER) {
+ var type = exports.valueType(val);
+ if (type === exports.TYPES.NULL_OR_EMPTY_STR) {
+ return val;
+ }
+ if (type !== exports.TYPES.INTEGER) {
return undefined;
}
return String(parseInt(val, 10));
};
exports.parseNumber = function parseNumber(val) {
- if (exports.valueType(val) !== exports.TYPES.NUMBER) {
+ var type = exports.valueType(val);
+ if (type === exports.TYPES.NULL_OR_EMPTY_STR) {
+ return val;
+ }
+ if (type !== exports.TYPES.NUMBER) {
return undefined;
}
return String(parseFloat(val, 10));
};
exports.parseLength = function parseLength(val) {
- if (exports.valueType(val) !== exports.TYPES.LENGTH) {
+ if (val === 0 || val === '0') {
+ return '0px';
+ }
+ var type = exports.valueType(val);
+ if (type === exports.TYPES.NULL_OR_EMPTY_STR) {
+ return val;
+ }
+ if (type !== exports.TYPES.LENGTH) {
return undefined;
}
return val;
};
exports.parsePercent = function parsePercent(val) {
- if (exports.valueType(val) !== exports.TYPES.PERCENT) {
+ if (val === 0 || val === '0') {
+ return '0%';
+ }
+ var type = exports.valueType(val);
+ if (type === exports.TYPES.NULL_OR_EMPTY_STR) {
+ return val;
+ }
+ if (type !== exports.TYPES.PERCENT) {
return undefined;
}
return val;
};
+// either a length or a percent
exports.parseMeasurement = function parseMeasurement(val) {
- var type = exports.valueType(val);
- if (type !== exports.TYPES.LENGTH && type !== exports.TYPES.PERCENT) {
- return undefined;
+ var length = exports.parseLength(val);
+ if (length !== undefined) {
+ return length;
}
- return val;
+ return exports.parsePercent(val);
};
exports.parseUrl = function parseUrl(val) {
+ var type = exports.valueType(val);
+ if (type === exports.TYPES.NULL_OR_EMPTY_STR) {
+ return val;
+ }
var res = urlRegEx.exec(val);
// does it match the regex?
if (!res) {
@@ -203,7 +242,11 @@ exports.parseUrl = function parseUrl(val) {
};
exports.parseString = function parseString(val) {
- if (exports.valueType(val) !== exports.TYPES.STRING) {
+ var type = exports.valueType(val);
+ if (type === exports.TYPES.NULL_OR_EMPTY_STR) {
+ return val;
+ }
+ if (type !== exports.TYPES.STRING) {
return undefined;
}
var i;
@@ -226,6 +269,10 @@ exports.parseString = function parseString(val) {
};
exports.parseColor = function parseColor(val) {
+ var type = exports.valueType(val);
+ if (type === exports.TYPES.NULL_OR_EMPTY_STR) {
+ return val;
+ }
var red, green, blue, alpha = 1;
var parts;
var res = colorRegEx1.exec(val);
@@ -296,14 +343,18 @@ exports.parseColor = function parseColor(val) {
return 'rgba(' + red + ', ' + green + ', ' + blue + ', ' + alpha + ')';
}
- if (exports.valueType(val) === exports.TYPES.COLOR) {
+ if (type === exports.TYPES.COLOR) {
return val;
}
return undefined;
};
exports.parseAngle = function parseAngle(val) {
- if (exports.valueType(val) !== exports.TYPES.ANGLE) {
+ var type = exports.valueType(val);
+ if (type === exports.TYPES.NULL_OR_EMPTY_STR) {
+ return val;
+ }
+ if (type !== exports.TYPES.ANGLE) {
return undefined;
}
var res = angleRegEx.exec(val);
@@ -346,6 +397,19 @@ var dashedToCamelCase = function (dashed) {
* on them
*/
exports.shorthandParser = function parse(v, shorthand_for) {
+ var type = exports.valueType(v);
+ if (type === exports.TYPES.NULL_OR_EMPTY_STR) {
+ return v;
+ }
+
+ if (typeof v === 'number') {
+ v = v.toString();
+ }
+
+ if (typeof v !== 'string') {
+ return undefined;
+ }
+
if (v.toLowerCase() === 'inherit') {
return {};
}
@@ -379,6 +443,8 @@ exports.shorthandSetter = function (property, shorthand_for) {
// *its* subpropertiesX
var camel = dashedToCamelCase(subprop);
this[camel] = obj[subprop];
+ // in case it gets translated into something else (0 -> 0px)
+ obj[subprop] = this[camel];
this.removeProperty(subprop);
this._values[subprop] = obj[subprop];
}, this);
@@ -410,12 +476,19 @@ exports.shorthandGetter = function (property, shorthand_for) {
// if two, the first applies to the top and bottom, and the second to left and right
// if three, the first applies to the top, the second to left and right, the third bottom
// if four, top, right, bottom, left
-exports.implicitSetter = function (property_before, property_after, isValid) {
+exports.implicitSetter = function (property_before, property_after, isValid, parser) {
property_after = property_after || '';
if (property_after !== '') {
property_after = '-' + property_after;
}
+
return function (v) {
+ if (typeof v === 'number') {
+ v = v.toString();
+ }
+ if (typeof v !== 'string') {
+ return undefined;
+ }
if (v.toLowerCase() === 'inherit') {
return this.setProperty(property_before + property_after, v);
}
@@ -428,7 +501,7 @@ exports.implicitSetter = function (property_before, property_after, isValid) {
return undefined;
}
- this.setProperty(property_before + property_after, v);
+ this.setProperty(property_before + property_after, parser(v));
this.removeProperty(property_before + '-top' + property_after);
this.removeProperty(property_before + '-right' + property_after);
@@ -436,28 +509,28 @@ exports.implicitSetter = function (property_before, property_after, isValid) {
this.removeProperty(property_before + '-left' + property_after);
switch (parts.length) {
case 1:
- this._values[property_before + '-top' + property_after] = parts[0];
- this._values[property_before + '-right' + property_after] = parts[0];
- this._values[property_before + '-bottom' + property_after] = parts[0];
- this._values[property_before + '-left' + property_after] = parts[0];
+ this._values[property_before + '-top' + property_after] = parser(parts[0]);
+ this._values[property_before + '-right' + property_after] = parser(parts[0]);
+ this._values[property_before + '-bottom' + property_after] = parser(parts[0]);
+ this._values[property_before + '-left' + property_after] = parser(parts[0]);
return v;
case 2:
- this._values[property_before + '-top' + property_after] = parts[0];
- this._values[property_before + '-right' + property_after] = parts[1];
- this._values[property_before + '-bottom' + property_after] = parts[0];
- this._values[property_before + '-left' + property_after] = parts[1];
+ this._values[property_before + '-top' + property_after] = parser(parts[0]);
+ this._values[property_before + '-right' + property_after] = parser(parts[1]);
+ this._values[property_before + '-bottom' + property_after] = parser(parts[0]);
+ this._values[property_before + '-left' + property_after] = parser(parts[1]);
return v;
case 3:
- this._values[property_before + '-top' + property_after] = parts[0];
- this._values[property_before + '-right' + property_after] = parts[1];
- this._values[property_before + '-bottom' + property_after] = parts[2];
- this._values[property_before + '-left' + property_after] = parts[1];
+ this._values[property_before + '-top' + property_after] = parser(parts[0]);
+ this._values[property_before + '-right' + property_after] = parser(parts[1]);
+ this._values[property_before + '-bottom' + property_after] = parser(parts[2]);
+ this._values[property_before + '-left' + property_after] = parser(parts[1]);
return v;
case 4:
- this._values[property_before + '-top' + property_after] = parts[0];
- this._values[property_before + '-right' + property_after] = parts[1];
- this._values[property_before + '-bottom' + property_after] = parts[2];
- this._values[property_before + '-left' + property_after] = parts[3];
+ this._values[property_before + '-top' + property_after] = parser(parts[0]);
+ this._values[property_before + '-right' + property_after] = parser(parts[1]);
+ this._values[property_before + '-bottom' + property_after] = parser(parts[2]);
+ this._values[property_before + '-left' + property_after] = parser(parts[3]);
return v;
}
};
diff --git a/lib/properties/borderColor.js b/lib/properties/borderColor.js
index ab0bb2e..0390096 100644
--- a/lib/properties/borderColor.js
+++ b/lib/properties/borderColor.js
@@ -3,12 +3,23 @@
var parsers = require('../parsers');
var implicitSetter = require('../parsers').implicitSetter;
-var isValid = module.exports.isValid = function parse(v) {
+module.exports.isValid = function parse(v) {
+ if (typeof v !== 'string') {
+ return false;
+ }
return (v.toLowerCase() === 'transparent' || parsers.valueType(v) === parsers.TYPES.COLOR);
};
+var isValid = module.exports.isValid;
+
+var parser = function (v) {
+ if (isValid(v)) {
+ return v.toLowerCase();
+ }
+ return undefined;
+};
module.exports.definition = {
- set: implicitSetter('border', 'color', isValid),
+ set: implicitSetter('border', 'color', isValid, parser),
get: function () {
return this.getPropertyValue('border-color');
},
diff --git a/lib/properties/borderStyle.js b/lib/properties/borderStyle.js
index c08eecc..ae20b2d 100644
--- a/lib/properties/borderStyle.js
+++ b/lib/properties/borderStyle.js
@@ -5,12 +5,20 @@ var implicitSetter = require('../parsers').implicitSetter;
// the valid border-styles:
var styles = ['none', 'hidden', 'dotted', 'dashed', 'solid', 'double', 'groove', 'ridge', 'inset', 'outset'];
-var isValid = module.exports.isValid = function parse(v) {
- return styles.indexOf(v) !== -1;
+module.exports.isValid = function parse(v) {
+ return typeof v === 'string' && styles.indexOf(v) !== -1;
+};
+var isValid = module.exports.isValid;
+
+var parser = function (v) {
+ if (isValid(v)) {
+ return v.toLowerCase();
+ }
+ return undefined;
};
module.exports.definition = {
- set: implicitSetter('border', 'style', isValid),
+ set: implicitSetter('border', 'style', isValid, parser),
get: function () {
return this.getPropertyValue('border-style');
},
diff --git a/lib/properties/borderWidth.js b/lib/properties/borderWidth.js
index 578f27e..73f178f 100644
--- a/lib/properties/borderWidth.js
+++ b/lib/properties/borderWidth.js
@@ -7,12 +7,35 @@ var implicitSetter = require('../parsers').implicitSetter;
// the valid border-widths:
var widths = ['thin', 'medium', 'thick'];
-var isValid = module.exports.isValid = function parse(v) {
- return (widths.indexOf(v.toLowerCase()) !== -1) || parsers.parseLength(v);
+module.exports.isValid = function parse(v) {
+ var length = parsers.parseLength(v);
+ if (length !== undefined) {
+ return true;
+ }
+ if (typeof v !== 'string') {
+ return false;
+ }
+ v = v.toLowerCase();
+ if (widths.indexOf(v) === -1) {
+ return false;
+ }
+ return true;
+};
+var isValid = module.exports.isValid;
+
+var parser = function (v) {
+ var length = parsers.parseLength(v);
+ if (length !== undefined) {
+ return length;
+ }
+ if (isValid(v)) {
+ return v.toLowerCase();
+ }
+ return undefined;
};
module.exports.definition = {
- set: implicitSetter('border', 'width', isValid),
+ set: implicitSetter('border', 'width', isValid, parser),
get: function () {
return this.getPropertyValue('border-width');
},
diff --git a/lib/properties/height.js b/lib/properties/height.js
index 2e6fdbc..96362eb 100644
--- a/lib/properties/height.js
+++ b/lib/properties/height.js
@@ -1,8 +1,10 @@
'use strict';
+var parseMeasurement = require('../parsers').parseMeasurement;
+
module.exports.definition = {
set: function (v) {
- this.setProperty('height', v);
+ this.setProperty('height', parseMeasurement(v));
},
get: function () {
return this.getPropertyValue('height');
diff --git a/lib/properties/width.js b/lib/properties/width.js
index 8237d91..f22bf50 100644
--- a/lib/properties/width.js
+++ b/lib/properties/width.js
@@ -1,8 +1,10 @@
'use strict';
+var parseMeasurement = require('../parsers').parseMeasurement;
+
module.exports.definition = {
set: function (v) {
- this.setProperty('width', v);
+ this.setProperty('width', parseMeasurement(v));
},
get: function () {
return this.getPropertyValue('width');
diff --git a/tests/tests.js b/tests/tests.js
index c74d61b..9e4f0a0 100644
--- a/tests/tests.js
+++ b/tests/tests.js
@@ -1,5 +1,5 @@
"use strict";
-
+var util = require('util');
var cssstyle = require('../lib/CSSStyleDeclaration');
/**
@@ -73,20 +73,50 @@ module.exports = {
test.ok('background-color' === style[0], 'style[0] is not background-color');
test.done();
},
- 'Test Shorthand and Implicit Properties': function (test) {
+ 'Test Shorthand Properties': function (test) {
var style = new cssstyle.CSSStyleDeclaration();
test.expect(9);
style.background = 'blue url(http://www.example.com/some_img.jpg)';
test.ok('blue' === style.backgroundColor, 'backgroundColor is not blue');
test.ok('url(http://www.example.com/some_img.jpg)' === style.backgroundImage, 'backgroundImage is wrong');
test.ok('blue url(http://www.example.com/some_img.jpg)' === style.background, 'background is different');
- style.border = '1px solid black';
- test.ok('1px', style.borderWidth, 'borderWidth is not 1px');
+ style.border = '0 solid black';
+ test.ok('0px', style.borderWidth, 'borderWidth is not 0px');
test.ok('solid', style.borderStyle, 'borderStyle is not solid');
test.ok('black', style.borderColor, 'borderColor is not black');
- test.ok('1px', style.borderTopWidth, 'borderTopWidth is not 1px');
+ test.ok('0px', style.borderTopWidth, 'borderTopWidth is not 0px');
test.ok('solid', style.borderLeftStyle, 'borderLeftStyle is not solid');
test.ok('black', style.borderBottomColor, 'borderBottomColor is not black');
test.done();
+ },
+ 'Test width and height Properties and null and empty strings': function (test) {
+ var style = new cssstyle.CSSStyleDeclaration();
+ test.expect(7);
+ style.height = 6;
+ test.ok('' === style.height, 'height does not remain unset');
+ style.width = 0;
+ test.ok('0px' === style.width, 'width is not 0px');
+ style.height = '34%';
+ test.ok('34%' === style.height, 'height is not 34%');
+ style.height = '';
+ test.ok(style.length === 1, 'length is not 1');
+ test.ok('width: 0px;' === style.cssText, 'cssText is not "width: 0px;"');
+ style.width = null;
+ test.ok(style.length === 0, 'length is not 0');
+ test.ok('' === style.cssText, 'cssText is not empty string');
+ test.done();
+ },
+ 'Test Implicit Properties': function (test) {
+ var style = new cssstyle.CSSStyleDeclaration();
+ test.expect(7);
+ style.borderWidth = 0;
+ test.ok(style.length === 1, 'length is not 1');
+ test.ok('0px', style.borderWidth, 'borderWidth is not 0px');
+ test.ok('0px', style.borderTopWidth, 'borderTopWidth is not 0px');
+ test.ok('0px', style.borderBottomWidth, 'borderBottomWidth is not 0px');
+ test.ok('0px', style.borderLeftWidth, 'borderLeftWidth is not 0px');
+ test.ok('0px', style.borderRightWidth, 'borderRightWidth is not 0px');
+ test.ok('border-width: 0px;' === style.cssText, 'cssText is not "border-width: 0px", "' + style.cssText + '"');
+ test.done();
}
};
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-cssstyle.git
More information about the Pkg-javascript-commits
mailing list