From e77146ba5d624613bf284cdae79a5639ac0e5548 Mon Sep 17 00:00:00 2001 From: Hugo Wood Date: Thu, 2 Jun 2016 12:22:47 +0200 Subject: [PATCH 1/4] make npm run cover compatible with Windows --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 93cbfc3..83755a2 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "lint": "eslint . && jscs index.js test/", "pretest": "npm run lint", "test": "mocha --async-only", - "cover": "istanbul cover _mocha --report lcovonly", + "cover": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly", "coveralls": "npm run cover && istanbul-coveralls" }, "dependencies": {}, From 58d038e67a1657b84935afdf3a299d4b8ffa6091 Mon Sep 17 00:00:00 2001 From: Hugo Wood Date: Thu, 2 Jun 2016 12:23:05 +0200 Subject: [PATCH 2/4] accept function or array as type --- README.md | 8 ++++++-- index.js | 14 +++++++++++++- test/index.js | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 0e8e9ca..3f7386f 100644 --- a/README.md +++ b/README.md @@ -49,14 +49,18 @@ var result = normalize.undefined(undefined); ### `normalize(type, value[, ...appliedArguments])` -Takes a string of the `type` to match and a `value` to compare with `typeof`. Also optionally takes any extra arguments to apply to `value` if `value` is a function. +Takes a predicate function `type` to test against `value`. Also optionally takes any extra arguments to apply to `value` if `value` is a function. -If the results of `typeof value === type` is true, the value is returned. If false and `value` is a function, the function is called with any extra arguments supplied to `normalize`. +If the result of `type(value)` is true, the value is returned. If false and `value` is a function, the function is called with any extra arguments supplied to `normalize`. If `value` is neither a type match or a function, `null` is returned. If `value` is a function and the result of calling the function does not match the type, `null` is returned. +If `type` is a string, the applied predicate is `typeof value === type`. + +If `type` is an array, each element is tested against `value` in turn until one matches or none matches. + #### `normalize.object(value[, ...appliedArguments])` Convenience method for `normalize('object', ...)`. diff --git a/index.js b/index.js index a68ed95..ac6484c 100644 --- a/index.js +++ b/index.js @@ -13,7 +13,7 @@ var types = [ function normalize(type, value) { var args = Array.prototype.slice.call(arguments, 2); - var isType = typeof value === type; + var isType = conforms(type, value); var isFunction = typeof value === 'function'; if (!isType && !isFunction) { @@ -33,6 +33,18 @@ function normalize(type, value) { return result; } +function conforms(type, value) { + if (typeof type === 'string') { + return typeof value === type; + } + if (typeof type === 'function') { + return Boolean(type(value)); + } + return type.some(function(type) { + return conforms(type, value); + }); +} + // Add methods for each type types.forEach(function(type) { normalize[type] = normalize.bind(null, type); diff --git a/test/index.js b/test/index.js index 73f8e36..c695756 100644 --- a/test/index.js +++ b/test/index.js @@ -22,6 +22,53 @@ describe('normalize', function() { done(); }); + it('supports arrays for the type parameter', function(done) { + var type = ['string']; + var value = 'test string'; + var result = normalize(type, value); + expect(result).toEqual(value); + done(); + }); + + it('compares each type and the type of the value', function(done) { + var type = ['number', 'string', 'object']; + var value = 'test string'; + var result = normalize(type, value); + expect(result).toEqual(value); + done(); + }); + + it('returns null if value does not match any type', function(done) { + var type = ['string', 'undefined']; + var value = 1; + var result = normalize(type, value); + expect(result).toEqual(null); + done(); + }); + + it('supports functions for the type parameter', function(done) { + var type = function() { + return true; + }; + var value = 1; + var result = normalize(type, value); + expect(result).toEqual(value); + done(); + }); + + it('calls the type function to check validity', function(done) { + var called = false; + var type = function() { + called = true; + return false; + }; + var value = 1; + var result = normalize(type, value); + expect(result).toEqual(null); + expect(called).toEqual(true); + done(); + }); + it('calls the value if it is a function', function(done) { var type = 'string'; var expected = 'test string'; From 45fabd689bf73ab9650016d71c03f6a231595e0f Mon Sep 17 00:00:00 2001 From: Hugo Wood Date: Tue, 7 Jun 2016 15:50:44 +0200 Subject: [PATCH 3/4] improve documentation --- README.md | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 3f7386f..46a8704 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,17 @@ var count = normalize('number', function(a, b) { }, 1, 2); // count === 3 +// Values one of multiple types are returned +var isEnabled = normalize(['string', 'boolean'], true); +// isEnabled === true + +// Values matching predicate are returned +var now = new Date(); +var enabledSince = normalize(function(value) { + return value.constructor === Date; +}, now); +// enabledSince === now + // Convenience methods are available var result = normalize.object({}); var result = normalize.number(1); @@ -47,19 +58,19 @@ var result = normalize.undefined(undefined); ## API -### `normalize(type, value[, ...appliedArguments])` +### `normalize(predicate, value[, ...appliedArguments])` -Takes a predicate function `type` to test against `value`. Also optionally takes any extra arguments to apply to `value` if `value` is a function. +Takes a predicate function `predicate` to test against `value`. Also optionally takes any extra arguments to apply to `value` if `value` is a function. -If the result of `type(value)` is true, the value is returned. If false and `value` is a function, the function is called with any extra arguments supplied to `normalize`. +If the result of `predicate(value)` is true, the value is returned. If false and `value` is a function, the function is called with any extra arguments supplied to `normalize`. -If `value` is neither a type match or a function, `null` is returned. +If `value` is neither match for the predicate or a function, `null` is returned. -If `value` is a function and the result of calling the function does not match the type, `null` is returned. +If `value` is a function and the result of calling the function does not match the predicate, `null` is returned. -If `type` is a string, the applied predicate is `typeof value === type`. +If `predicate` is a string, the applied predicate is `typeof value === predicate`. -If `type` is an array, each element is tested against `value` in turn until one matches or none matches. +If `predicate` is an array, `normalized` is called with each element in turn until one matches or none matches. #### `normalize.object(value[, ...appliedArguments])` From 3e0853460aa32872cf7cdbada32bc7a9fb727dde Mon Sep 17 00:00:00 2001 From: Hugo Wood Date: Tue, 7 Jun 2016 15:51:37 +0200 Subject: [PATCH 4/4] replace Boolean by double-bang for coercion --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index ac6484c..3561d97 100644 --- a/index.js +++ b/index.js @@ -38,7 +38,7 @@ function conforms(type, value) { return typeof value === type; } if (typeof type === 'function') { - return Boolean(type(value)); + return !!type(value); } return type.some(function(type) { return conforms(type, value);