diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..15ea258 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,11 @@ +# Bowser Changelog + + +### 1.4.0 (June 28, 2016) + +- [FEATURE] Add `bowser.compareVersions` method +- [FEATURE] Add `bowser.isUnsupportedBrowser` method +- [FEATURE] Add `bowser.check` method +- [DOC] Changelog started +- [DOC] Add API section to README +- [FIX] Fix detection of browser type (A/C/X) for Chromium diff --git a/README.md b/README.md index ba35d58..c539419 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,44 @@ Also you can download minified file from [the release page](https://github.com/d ## 1.0.0 breaking changes `browser = require('bowser').browser;` becomes `browser = require('bowser');` +--- + +## API + +### bowser()`:Object` +Use it to get object with detected flags of your current browser. + +### bowser._detect(ua `:String`)`:Object` +Use it to get object with detected flags from User Agent string. + +### bowser.check(minVersions`:Object`, strictMode`:Boolean`)`:Boolean` +Use it to check if browser supported. + +``` +browser.check({msie: "11"}, window.navigator.userAgent); +// true / false +``` + +### bowser.compareVersions(versions`:Array`)`:Number` +Use it to compare two versions. + +``` +browser.compareVersions(['9.0', '10']); +// -1 +``` + +### bowser.isUnsupportedBrowser(minVersions`:Object`, [strictMode]`:Boolean`, [ua]`:string`)`:Boolean` +Use it to check if browser is unsupported. + +``` +browser.isUnsupportedBrowser({msie: "10"}, window.navigator.userAgent); +// true / false +``` + +See more examples in [tests](test/test.js). + +--- + ## Bowser Flags Your mileage may vary, but these flags should be set. See Contributing below. diff --git a/package.json b/package.json index dbceb85..aabb3c6 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "sniff", "detection" ], - "version": "1.3.0", + "version": "1.4.0", "homepage": "https://github.com/ded/bowser", "author": "Dustin Diaz (http://dustindiaz.com)", "main": "./src/bowser.js", @@ -27,7 +27,8 @@ "test": "test" }, "scripts": { - "test": "make test" + "test": "make test", + "prepublish": "make boosh" }, "license": "MIT" } diff --git a/src/bowser.js b/src/bowser.js index d966269..190f457 100644 --- a/src/bowser.js +++ b/src/bowser.js @@ -377,6 +377,7 @@ (result.opera && result.version >= 10.0) || (result.ios && result.osversion && result.osversion.split(".")[0] >= 6) || (result.blackberry && result.version >= 10.1) + || (result.chromium && result.version >= 20) ) { result.a = t; } @@ -386,6 +387,7 @@ (result.safari && result.version < 6) || (result.opera && result.version < 10.0) || (result.ios && result.osversion && result.osversion.split(".")[0] < 6) + || (result.chromium && result.version < 20) ) { result.c = t } else result.x = t @@ -407,6 +409,145 @@ return false; } + /** + * Get version precisions count + * + * @example + * getVersionPrecision("1.10.3") // 3 + * + * @param {string} version + * @return {number} + */ + function getVersionPrecision(version) { + return version.split(".").length; + } + + /** + * Array::map polyfill + * + * @param {Array} arr + * @param {Function} iterator + * @return {Array} + */ + function map(arr, iterator) { + var result = [], i; + if (Array.prototype.map) { + return Array.prototype.map.call(arr, iterator); + } + for (i = 0; i < arr.length; i++) { + result = iterator(arr[i]); + } + return result; + } + + /** + * Calculate browser version weight + * + * @example + * compareVersions(['1.10.2.1', '1.8.2.1.90']) // 1 + * compareVersions(['1.010.2.1', '1.09.2.1.90']); // 1 + * compareVersions(['1.10.2.1', '1.10.2.1']); // 0 + * compareVersions(['1.10.2.1', '1.0800.2']); // -1 + * + * @param {Array} versions versions to compare + * @return {Number} comparison result + */ + function compareVersions(versions) { + // 1) get common precision for both versions, for example for "10.0" and "9" it should be 2 + var precision = Math.max(getVersionPrecision(versions[0]), getVersionPrecision(versions[1])); + var chunks = map(versions, function (version) { + var delta = precision - getVersionPrecision(version); + + // 2) "9" -> "9.0" (for precision = 2) + version = version + new Array(delta + 1).join(".0"); + + // 3) "9.0" -> ["000000000"", "000000009"] + return map(version.split("."), function (chunk) { + return new Array(20 - chunk.length).join("0") + chunk; + }).reverse(); + }); + + // iterate in reverse order by reversed chunks array + while (--precision >= 0) { + // 4) compare: "000000009" > "000000010" = false (but "9" > "10" = true) + if (chunks[0][precision] > chunks[1][precision]) { + return 1; + } + else if (chunks[0][precision] === chunks[1][precision]) { + if (precision === 0) { + // all version chunks are same + return 0; + } + } + else { + return -1; + } + } + } + + /** + * Check if browser is unsupported + * + * @example + * bowser.isUnsupportedBrowser({ + * msie: "10", + * firefox: "23", + * chrome: "29", + * safari: "5.1", + * opera: "16", + * phantom: "534" + * }); + * + * @param {Object} minVersions map of minimal version to browser + * @param {Boolean} [strictMode = false] flag to return false if browser wasn't found in map + * @param {String} [ua] user agent string + * @return {Boolean} + */ + function isUnsupportedBrowser(minVersions, strictMode, ua) { + var _bowser = bowser; + + // make strictMode param optional with ua param usage + if (typeof strictMode === 'string') { + ua = strictMode; + strictMode = void(0); + } + + if (strictMode === void(0)) { + strictMode = false; + } + if (ua) { + _bowser = detect(ua); + } + + var version = "" + _bowser.version; + for (var browser in minVersions) { + if (minVersions.hasOwnProperty(browser)) { + if (_bowser[browser]) { + // browser version and min supported version. + if (compareVersions([version, minVersions[browser]]) < 0) { + return true; // unsupported + } + } + } + } + return strictMode; // not found + } + + /** + * Check if browser is supported + * + * @param {Object} minVersions map of minimal version to browser + * @param {Boolean} [strictMode = false] flag to return false if browser wasn't found in map + * @return {Boolean} + */ + function check(minVersions, strictMode) { + return !isUnsupportedBrowser(minVersions, strictMode); + } + + bowser.isUnsupportedBrowser = isUnsupportedBrowser; + bowser.compareVersions = compareVersions; + bowser.check = check; + /* * Set our detect method to the main bowser object so we can * reuse it to test other user agents. diff --git a/src/useragents.js b/src/useragents.js index 0ffea38..dd7fb25 100644 --- a/src/useragents.js +++ b/src/useragents.js @@ -1245,7 +1245,14 @@ module.exports.useragents = { , chromium: true , version: '35.0' , blink: true - , x: true + , a: true + } + , 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/50.0.2661.102 Chrome/50.0.2661.102 Safari/537.36': { + chromium: true + , a: true + , version: '50.0' + , linux: true + , blink: true } } , 'SlimerJS' : { diff --git a/test/test.js b/test/test.js index c11e035..cce4198 100644 --- a/test/test.js +++ b/test/test.js @@ -73,3 +73,58 @@ for (g in allUserAgents) { (function(group, userAgents) { }) })(g, allUserAgents[g])} + +var comparisionsTasks = [ + ['9.0', '10', -1], + ['11', '10', 1], + ['1.10.2.1', '1.8.2.1.90', 1], + ['1.010.2.1', '1.08.2.1.90', 1], + ['1.10.2.1', '1.10.2.1', 0], + ['1.10.2.1', '1.0800.2', -1], + ['1.0.0-alpha', '1.0.0-alpha.1', -1], + ['1.0.0-alpha.1', '1.0.0-alpha.beta', -1], + ['1.0.0-alpha.beta', '1.0.0-beta', -1], + ['1.0.0-beta', '1.0.0-beta.2', -1], + ['1.0.0-beta.11', '1.0.0-rc.1', -1], + ['1.0.0-rc.1', '1.0.0', -1] +]; + +describe('Browser versions comparision', function() { + for(g in comparisionsTasks) { + var task = comparisionsTasks[g], + version = task[0], + version2 = task[1], + matching = task[2] === 0 ? ' == ' : (task[2] > 0) ? ' > ' : ' < '; + it('version ' + version + ' should be' + matching + 'version ' + version2, function(){ + assert.equal(browser.compareVersions([version, version2]), task[2]); + }); + } +}); + +describe('Unsupported browser check', function() { + + before(function() { + this.ie10_6 = "Mozilla/5.0 (compatible; MSIE 10.6; Windows NT 6.1; Trident/5.0; InfoPath.2; SLCC1; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET CLR 2.0.50727) 3gpp-gba UNTRUSTED/1.0"; + }); + + it('should be passed by #isUnsupportedBrowser for IE10.6 and for IE10 miminal version specified', function() { + var unsupported = browser.isUnsupportedBrowser({msie: "10"}, this.ie10_6); + assert.equal(unsupported, false); + }); + + it('should NOT be passed by #check for IE10.6 and for IE11 miminal version specified', function() { + var supported = browser.check({msie: "11"}, this.ie10_6); + assert.equal(supported, false); + }); + + it('should be passed by #check for IE10.6 when version was not specified', function() { + var supported = browser.check({}, this.ie10_6); + assert.equal(supported, true); + }); + + it('should NOT be passed by #check for IE10.6 when version was not specified in strict mode', function() { + var supported = browser.check({}, true, this.ie10_6); + assert.equal(supported, false); + }); + +})