[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