mirror of
https://github.com/lancedikson/bowser
synced 2024-10-27 20:34:22 +00:00
Merge pull request #241 from udivankin/develop
Adds loose comparison support
This commit is contained in:
commit
6434c76184
@ -111,6 +111,13 @@ const isValidBrowser = browser.satisfies({
|
|||||||
chrome: ">20.1.1432",
|
chrome: ">20.1.1432",
|
||||||
firefox: ">31",
|
firefox: ">31",
|
||||||
opera: ">22"
|
opera: ">22"
|
||||||
|
|
||||||
|
// also supports equality operator
|
||||||
|
chrome: "=20.1.1432", // will match particular build only
|
||||||
|
|
||||||
|
// and loose-equality operator
|
||||||
|
chrome: "~20" // will match any 20.* sub-version
|
||||||
|
chrome: "~20.1" // will match any 20.1.* sub-version (20.1.19 as well as 20.1.12.42-alpha.1)
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -397,6 +397,7 @@ class Parser {
|
|||||||
compareVersion(version) {
|
compareVersion(version) {
|
||||||
let expectedResult = 0;
|
let expectedResult = 0;
|
||||||
let comparableVersion = version;
|
let comparableVersion = version;
|
||||||
|
let isLoose = false;
|
||||||
|
|
||||||
if (version[0] === '>') {
|
if (version[0] === '>') {
|
||||||
expectedResult = 1;
|
expectedResult = 1;
|
||||||
@ -406,8 +407,12 @@ class Parser {
|
|||||||
comparableVersion = version.substr(1);
|
comparableVersion = version.substr(1);
|
||||||
} else if (version[0] === '=') {
|
} else if (version[0] === '=') {
|
||||||
comparableVersion = version.substr(1);
|
comparableVersion = version.substr(1);
|
||||||
|
} else if (version[0] === '~') {
|
||||||
|
isLoose = true;
|
||||||
|
comparableVersion = version.substr(1);
|
||||||
}
|
}
|
||||||
return compareVersions(this.getBrowserVersion(), comparableVersion) === expectedResult;
|
|
||||||
|
return compareVersions(this.getBrowserVersion(), comparableVersion, isLoose) === expectedResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
isOS(osName) {
|
isOS(osName) {
|
||||||
|
30
src/utils.js
30
src/utils.js
@ -68,23 +68,26 @@ class Utils {
|
|||||||
* Calculate browser version weight
|
* Calculate browser version weight
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* compareVersions(['1.10.2.1', '1.8.2.1.90']) // 1
|
* compareVersions('1.10.2.1', '1.8.2.1.90') // 1
|
||||||
* compareVersions(['1.010.2.1', '1.09.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.10.2.1'); // 0
|
||||||
* compareVersions(['1.10.2.1', '1.0800.2']); // -1
|
* compareVersions('1.10.2.1', '1.0800.2'); // -1
|
||||||
|
* compareVersions('1.10.2.1', '1.10', true); // 0
|
||||||
*
|
*
|
||||||
* @param {String} versionA versions versions to compare
|
* @param {String} versionA versions versions to compare
|
||||||
* @param {String} versionB versions versions to compare
|
* @param {String} versionB versions versions to compare
|
||||||
|
* @param {boolean} [isLoose] enable loose comparison
|
||||||
* @return {Number} comparison result: -1 when versionA is lower,
|
* @return {Number} comparison result: -1 when versionA is lower,
|
||||||
* 1 when versionA is bigger, 0 when both equal
|
* 1 when versionA is bigger, 0 when both equal
|
||||||
*/
|
*/
|
||||||
/* eslint consistent-return: 1 */
|
/* eslint consistent-return: 1 */
|
||||||
static compareVersions(versionA, versionB) {
|
static compareVersions(versionA, versionB, isLoose = false) {
|
||||||
// 1) get common precision for both versions, for example for "10.0" and "9" it should be 2
|
// 1) get common precision for both versions, for example for "10.0" and "9" it should be 2
|
||||||
let precision = Math.max(
|
const versionAPrecision = Utils.getVersionPrecision(versionA);
|
||||||
Utils.getVersionPrecision(versionA),
|
const versionBPrecision = Utils.getVersionPrecision(versionB);
|
||||||
Utils.getVersionPrecision(versionB),
|
|
||||||
);
|
let precision = Math.max(versionAPrecision, versionBPrecision);
|
||||||
|
let lastPrecision = 0;
|
||||||
|
|
||||||
const chunks = Utils.map([versionA, versionB], (version) => {
|
const chunks = Utils.map([versionA, versionB], (version) => {
|
||||||
const delta = precision - Utils.getVersionPrecision(version);
|
const delta = precision - Utils.getVersionPrecision(version);
|
||||||
@ -96,14 +99,19 @@ class Utils {
|
|||||||
return Utils.map(_version.split('.'), chunk => new Array(20 - chunk.length).join('0') + chunk).reverse();
|
return Utils.map(_version.split('.'), chunk => new Array(20 - chunk.length).join('0') + chunk).reverse();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// adjust precision for loose comparison
|
||||||
|
if (isLoose) {
|
||||||
|
lastPrecision = precision - Math.min(versionAPrecision, versionBPrecision);
|
||||||
|
}
|
||||||
|
|
||||||
// iterate in reverse order by reversed chunks array
|
// iterate in reverse order by reversed chunks array
|
||||||
precision -= 1;
|
precision -= 1;
|
||||||
while (precision >= 0) {
|
while (precision >= lastPrecision) {
|
||||||
// 4) compare: "000000009" > "000000010" = false (but "9" > "10" = true)
|
// 4) compare: "000000009" > "000000010" = false (but "9" > "10" = true)
|
||||||
if (chunks[0][precision] > chunks[1][precision]) {
|
if (chunks[0][precision] > chunks[1][precision]) {
|
||||||
return 1;
|
return 1;
|
||||||
} else if (chunks[0][precision] === chunks[1][precision]) {
|
} else if (chunks[0][precision] === chunks[1][precision]) {
|
||||||
if (precision === 0) {
|
if (precision === lastPrecision) {
|
||||||
// all version chunks are same
|
// all version chunks are same
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -57,8 +57,13 @@ test('Skip parsing shouldn\'t parse', (t) => {
|
|||||||
t.deepEqual((new Parser(UA, true)).getResult(), {});
|
t.deepEqual((new Parser(UA, true)).getResult(), {});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Parser.check should make simple comparison', (t) => {
|
test('Parser.check should make simple comparisons', (t) => {
|
||||||
|
// also covers Parser.compareVersion() method
|
||||||
t.is(parser.satisfies({ opera: '>42' }), true);
|
t.is(parser.satisfies({ opera: '>42' }), true);
|
||||||
|
t.is(parser.satisfies({ opera: '<44' }), true);
|
||||||
|
t.is(parser.satisfies({ opera: '=43.0.2442.1165' }), true);
|
||||||
|
t.is(parser.satisfies({ opera: '~43.0' }), true);
|
||||||
|
t.is(parser.satisfies({ opera: '~43' }), true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Parser.check should make complex comparison', (t) => {
|
test('Parser.check should make complex comparison', (t) => {
|
||||||
|
@ -22,6 +22,9 @@ test('compareVersions', (t) => {
|
|||||||
['1.10.2.1', '1.8.2.1.90', 1],
|
['1.10.2.1', '1.8.2.1.90', 1],
|
||||||
['1.010.2.1', '1.08.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.10.2.1', 0],
|
||||||
|
['1.10.2.1', '1.10.2', 0, true],
|
||||||
|
['1.10.2.1', '1.10', 0, true],
|
||||||
|
['1.10.2.1', '1', 0, true],
|
||||||
['1.10.2.1', '1.0800.2', -1],
|
['1.10.2.1', '1.0800.2', -1],
|
||||||
['1.0.0-alpha', '1.0.0-alpha.1', -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.1', '1.0.0-alpha.beta', -1],
|
||||||
@ -35,7 +38,8 @@ test('compareVersions', (t) => {
|
|||||||
const versionA = testingParams[0];
|
const versionA = testingParams[0];
|
||||||
const versionB = testingParams[1];
|
const versionB = testingParams[1];
|
||||||
const result = testingParams[2];
|
const result = testingParams[2];
|
||||||
let matching = ' == ';
|
const isLoose = testingParams.length > 3 ? testingParams[3] : false;
|
||||||
|
let matching = isLoose ? '~' : ' == ';
|
||||||
|
|
||||||
if (result > 0) {
|
if (result > 0) {
|
||||||
matching = ' > ';
|
matching = ' > ';
|
||||||
@ -43,6 +47,6 @@ test('compareVersions', (t) => {
|
|||||||
matching = ' < ';
|
matching = ' < ';
|
||||||
}
|
}
|
||||||
|
|
||||||
t.is(compareVersions(versionA, versionB), result, `version ${versionA} should be ${matching} version ${versionB}`);
|
t.is(compareVersions(versionA, versionB, isLoose), result, `version ${versionA} should be ${matching} version ${versionB}`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user