diff --git a/README.md b/README.md
index ace28d5..8d8a2fb 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@ A small, fast and rich-API browser/platform/engine detector for both browser and
Don't hesitate to support the project on Github or [OpenCollective](https://opencollective.com/bowser) if you like it ❤️ Also, contributors are always welcome!
-[![Build Status](https://travis-ci.org/lancedikson/bowser.svg?branch=master)](https://travis-ci.org/lancedikson/bowser/) [![Greenkeeper badge](https://badges.greenkeeper.io/lancedikson/bowser.svg)](https://greenkeeper.io/) [![Coverage Status](https://coveralls.io/repos/github/lancedikson/bowser/badge.svg?branch=master)](https://coveralls.io/github/lancedikson/bowser?branch=master) ![Downloads](https://img.shields.io/npm/dm/bowser)
+[![Financial Contributors on Open Collective](https://opencollective.com/bowser/all/badge.svg?label=financial+contributors)](https://opencollective.com/bowser) [![Build Status](https://travis-ci.org/lancedikson/bowser.svg?branch=master)](https://travis-ci.org/lancedikson/bowser/) [![Greenkeeper badge](https://badges.greenkeeper.io/lancedikson/bowser.svg)](https://greenkeeper.io/) [![Coverage Status](https://coveralls.io/repos/github/lancedikson/bowser/badge.svg?branch=master)](https://coveralls.io/github/lancedikson/bowser?branch=master) ![Downloads](https://img.shields.io/npm/dm/bowser)
# Contents
- [Overview](#overview)
@@ -145,5 +145,35 @@ list of aliases can be found in [the file](src/constants.js).
## Similar Projects
* [Kong](https://github.com/BigBadBleuCheese/Kong) - A C# port of Bowser.
+## Contributors
+
+### Code Contributors
+
+This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].
+
+
+### Financial Contributors
+
+Become a financial contributor and help us sustain our community. [[Contribute](https://opencollective.com/bowser/contribute)]
+
+#### Individuals
+
+
+
+#### Organizations
+
+Support this project with your organization. Your logo will show up here with a link to your website. [[Contribute](https://opencollective.com/bowser/contribute)]
+
+
+
+
+
+
+
+
+
+
+
+
## License
Licensed as MIT. All rights not explicitly granted in the MIT license are reserved. See the included LICENSE file for more details.
diff --git a/index.d.ts b/index.d.ts
index 46c2230..4ef7345 100644
--- a/index.d.ts
+++ b/index.d.ts
@@ -22,6 +22,14 @@ declare namespace Bowser {
function parse(UA: string): Parser.ParsedResult;
+ /**
+ * Constants exposed via bowser getters
+ */
+ const BROWSER_MAP: Record;
+ const ENGINE_MAP: Record;
+ const OS_MAP: Record;
+ const PLATFORMS_MAP: Record;
+
namespace Parser {
interface Parser {
constructor(UA: string, skipParsing?: boolean): Parser.Parser;
diff --git a/package-lock.json b/package-lock.json
index c62a635..b97b57b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1325,33 +1325,33 @@
"dev": true
},
"@sinonjs/commons": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.6.0.tgz",
- "integrity": "sha512-w4/WHG7C4WWFyE5geCieFJF6MZkbW4VAriol5KlmQXpAQdxvV0p26sqNZOW6Qyw6Y0l9K4g+cHvvczR2sEEpqg==",
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.7.0.tgz",
+ "integrity": "sha512-qbk9AP+cZUsKdW1GJsBpxPKFmCJ0T8swwzVje3qFd+AkQb74Q/tiuzrdfFg8AD2g5HH/XbE/I8Uc1KYHVYWfhg==",
"dev": true,
"requires": {
"type-detect": "4.0.8"
}
},
"@sinonjs/formatio": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.1.tgz",
- "integrity": "sha512-tsHvOB24rvyvV2+zKMmPkZ7dXX6LSLKZ7aOtXY6Edklp0uRcgGpOsQTTGTcWViFyx4uhWc6GV8QdnALbIbIdeQ==",
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-4.0.1.tgz",
+ "integrity": "sha512-asIdlLFrla/WZybhm0C8eEzaDNNrzymiTqHMeJl6zPW2881l3uuVRpm0QlRQEjqYWv6CcKMGYME3LbrLJsORBw==",
"dev": true,
"requires": {
"@sinonjs/commons": "^1",
- "@sinonjs/samsam": "^3.1.0"
+ "@sinonjs/samsam": "^4.2.0"
}
},
"@sinonjs/samsam": {
- "version": "3.3.3",
- "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.3.tgz",
- "integrity": "sha512-bKCMKZvWIjYD0BLGnNrxVuw4dkWCYsLqFOUWw8VgKF/+5Y+mE7LfHWPIYoDXowH+3a9LsWDMo0uAP8YDosPvHQ==",
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-4.2.0.tgz",
+ "integrity": "sha512-yG7QbUz38ZPIegfuSMEcbOo0kkLGmPa8a0Qlz4dk7+cXYALDScWjIZzAm/u2+Frh+bcdZF6wZJZwwuJjY0WAjA==",
"dev": true,
"requires": {
- "@sinonjs/commons": "^1.3.0",
+ "@sinonjs/commons": "^1.6.0",
"array-from": "^2.1.1",
- "lodash": "^4.17.15"
+ "lodash.get": "^4.4.2"
}
},
"@sinonjs/text-encoding": {
@@ -2369,15 +2369,230 @@
}
},
"babel-plugin-istanbul": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-5.2.0.tgz",
- "integrity": "sha512-5LphC0USA8t4i1zCtjbbNb6jJj/9+X6P37Qfirc/70EQ34xKlMW+a1RHGwxGI+SwWpNwZ27HqvzAobeqaXwiZw==",
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz",
+ "integrity": "sha512-AF55rZXpe7trmEylbaE1Gv54wn6rwU03aptvRoVIGP8YykoSxqdVLV1TfwflBCE/QtHmqtP8SWlTENqbK8GCSQ==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.0.0",
- "find-up": "^3.0.0",
- "istanbul-lib-instrument": "^3.3.0",
- "test-exclude": "^5.2.3"
+ "@istanbuljs/load-nyc-config": "^1.0.0",
+ "@istanbuljs/schema": "^0.1.2",
+ "istanbul-lib-instrument": "^4.0.0",
+ "test-exclude": "^6.0.0"
+ },
+ "dependencies": {
+ "@babel/code-frame": {
+ "version": "7.5.5",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz",
+ "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==",
+ "dev": true,
+ "requires": {
+ "@babel/highlight": "^7.0.0"
+ }
+ },
+ "@babel/core": {
+ "version": "7.7.7",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.7.7.tgz",
+ "integrity": "sha512-jlSjuj/7z138NLZALxVgrx13AOtqip42ATZP7+kYl53GvDV6+4dCek1mVUo8z8c8Xnw/mx2q3d9HWh3griuesQ==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.5.5",
+ "@babel/generator": "^7.7.7",
+ "@babel/helpers": "^7.7.4",
+ "@babel/parser": "^7.7.7",
+ "@babel/template": "^7.7.4",
+ "@babel/traverse": "^7.7.4",
+ "@babel/types": "^7.7.4",
+ "convert-source-map": "^1.7.0",
+ "debug": "^4.1.0",
+ "json5": "^2.1.0",
+ "lodash": "^4.17.13",
+ "resolve": "^1.3.2",
+ "semver": "^5.4.1",
+ "source-map": "^0.5.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true
+ }
+ }
+ },
+ "@babel/generator": {
+ "version": "7.7.7",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.7.tgz",
+ "integrity": "sha512-/AOIBpHh/JU1l0ZFS4kiRCBnLi6OTHzh0RPk3h9isBxkkqELtQNFi1Vr/tiG9p1yfoUdKVwISuXWQR+hwwM4VQ==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.7.4",
+ "jsesc": "^2.5.1",
+ "lodash": "^4.17.13",
+ "source-map": "^0.5.0"
+ }
+ },
+ "@babel/helper-function-name": {
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz",
+ "integrity": "sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-get-function-arity": "^7.7.4",
+ "@babel/template": "^7.7.4",
+ "@babel/types": "^7.7.4"
+ }
+ },
+ "@babel/helper-get-function-arity": {
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz",
+ "integrity": "sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.7.4"
+ }
+ },
+ "@babel/helper-split-export-declaration": {
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz",
+ "integrity": "sha512-guAg1SXFcVr04Guk9eq0S4/rWS++sbmyqosJzVs8+1fH5NI+ZcmkaSkc7dmtAFbHFva6yRJnjW3yAcGxjueDug==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.7.4"
+ }
+ },
+ "@babel/helpers": {
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.7.4.tgz",
+ "integrity": "sha512-ak5NGZGJ6LV85Q1Zc9gn2n+ayXOizryhjSUBTdu5ih1tlVCJeuQENzc4ItyCVhINVXvIT/ZQ4mheGIsfBkpskg==",
+ "dev": true,
+ "requires": {
+ "@babel/template": "^7.7.4",
+ "@babel/traverse": "^7.7.4",
+ "@babel/types": "^7.7.4"
+ }
+ },
+ "@babel/parser": {
+ "version": "7.7.7",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.7.tgz",
+ "integrity": "sha512-WtTZMZAZLbeymhkd/sEaPD8IQyGAhmuTuvTzLiCFM7iXiVdY0gc0IaI+cW0fh1BnSMbJSzXX6/fHllgHKwHhXw==",
+ "dev": true
+ },
+ "@babel/template": {
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.4.tgz",
+ "integrity": "sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.0.0",
+ "@babel/parser": "^7.7.4",
+ "@babel/types": "^7.7.4"
+ }
+ },
+ "@babel/traverse": {
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.7.4.tgz",
+ "integrity": "sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.5.5",
+ "@babel/generator": "^7.7.4",
+ "@babel/helper-function-name": "^7.7.4",
+ "@babel/helper-split-export-declaration": "^7.7.4",
+ "@babel/parser": "^7.7.4",
+ "@babel/types": "^7.7.4",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0",
+ "lodash": "^4.17.13"
+ }
+ },
+ "@babel/types": {
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz",
+ "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==",
+ "dev": true,
+ "requires": {
+ "esutils": "^2.0.2",
+ "lodash": "^4.17.13",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "convert-source-map": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz",
+ "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "~5.1.1"
+ }
+ },
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "glob": {
+ "version": "7.1.6",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
+ "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "istanbul-lib-coverage": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz",
+ "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==",
+ "dev": true
+ },
+ "istanbul-lib-instrument": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.0.tgz",
+ "integrity": "sha512-Nm4wVHdo7ZXSG30KjZ2Wl5SU/Bw7bDx1PdaiIFzEStdjs0H12mOTncn1GVYuqQSaZxpg87VGBRsVRPGD2cD1AQ==",
+ "dev": true,
+ "requires": {
+ "@babel/core": "^7.7.5",
+ "@babel/parser": "^7.7.5",
+ "@babel/template": "^7.7.4",
+ "@babel/traverse": "^7.7.4",
+ "@istanbuljs/schema": "^0.1.2",
+ "istanbul-lib-coverage": "^3.0.0",
+ "semver": "^6.3.0"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ },
+ "test-exclude": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
+ "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==",
+ "dev": true,
+ "requires": {
+ "@istanbuljs/schema": "^0.1.2",
+ "glob": "^7.1.4",
+ "minimatch": "^3.0.4"
+ }
+ }
}
},
"backbone": {
@@ -4172,9 +4387,9 @@
"dev": true
},
"diff": {
- "version": "3.5.0",
- "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
- "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.1.tgz",
+ "integrity": "sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q==",
"dev": true
},
"diffie-hellman": {
@@ -8295,6 +8510,12 @@
"integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=",
"dev": true
},
+ "lodash.get": {
+ "version": "4.4.2",
+ "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
+ "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=",
+ "dev": true
+ },
"lodash.isarguments": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
@@ -8341,10 +8562,13 @@
}
},
"lolex": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/lolex/-/lolex-4.2.0.tgz",
- "integrity": "sha512-gKO5uExCXvSm6zbF562EvM+rd1kQDnB9AZBbiQVzf1ZmdDpxUSvpnAaVOP83N/31mRK8Ml8/VE8DMvsAZQ+7wg==",
- "dev": true
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/lolex/-/lolex-5.1.2.tgz",
+ "integrity": "sha512-h4hmjAvHTmd+25JSwrtTIuwbKdwg5NzZVRMLn9saij4SZaepCrTCxPr35H/3bjwfMJtN+t3CX8672UIkglz28A==",
+ "dev": true,
+ "requires": {
+ "@sinonjs/commons": "^1.7.0"
+ }
},
"loose-envify": {
"version": "1.4.0",
@@ -8879,15 +9103,16 @@
"dev": true
},
"nise": {
- "version": "1.5.2",
- "resolved": "https://registry.npmjs.org/nise/-/nise-1.5.2.tgz",
- "integrity": "sha512-/6RhOUlicRCbE9s+94qCUsyE+pKlVJ5AhIv+jEE7ESKwnbXqulKZ1FYU+XAtHHWE9TinYvAxDUJAb912PwPoWA==",
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/nise/-/nise-3.0.0.tgz",
+ "integrity": "sha512-EObFx5tioBMePHpU/gGczaY2YDqL255iwjmZwswu2CiwEW8xIGrr3E2xij+efIppS1nLQo9NyXSIUySGHUOhHQ==",
"dev": true,
"requires": {
- "@sinonjs/formatio": "^3.2.1",
+ "@sinonjs/commons": "^1.7.0",
+ "@sinonjs/formatio": "^4.0.1",
"@sinonjs/text-encoding": "^0.7.1",
"just-extend": "^4.0.2",
- "lolex": "^4.1.0",
+ "lolex": "^5.0.1",
"path-to-regexp": "^1.7.0"
}
},
@@ -9918,9 +10143,9 @@
"dev": true
},
"path-to-regexp": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz",
- "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=",
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz",
+ "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==",
"dev": true,
"requires": {
"isarray": "0.0.1"
@@ -11029,29 +11254,18 @@
"dev": true
},
"sinon": {
- "version": "7.5.0",
- "resolved": "https://registry.npmjs.org/sinon/-/sinon-7.5.0.tgz",
- "integrity": "sha512-AoD0oJWerp0/rY9czP/D6hDTTUYGpObhZjMpd7Cl/A6+j0xBE+ayL/ldfggkBXUs0IkvIiM1ljM8+WkOc5k78Q==",
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/sinon/-/sinon-8.0.0.tgz",
+ "integrity": "sha512-9ugfO9tMrxTzqViG0hGhJoLXj8M01FZwfXMpYSmQT1AuV2jyXDJZUMpbENHBY9/2c2u6RKkHOcbYINx2FttUkg==",
"dev": true,
"requires": {
"@sinonjs/commons": "^1.4.0",
- "@sinonjs/formatio": "^3.2.1",
- "@sinonjs/samsam": "^3.3.3",
- "diff": "^3.5.0",
- "lolex": "^4.2.0",
- "nise": "^1.5.2",
- "supports-color": "^5.5.0"
- },
- "dependencies": {
- "supports-color": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
- "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
- "dev": true,
- "requires": {
- "has-flag": "^3.0.0"
- }
- }
+ "@sinonjs/formatio": "^4.0.1",
+ "@sinonjs/samsam": "^4.0.1",
+ "diff": "^4.0.1",
+ "lolex": "^5.1.2",
+ "nise": "^3.0.0",
+ "supports-color": "^7.1.0"
}
},
"slash": {
diff --git a/package.json b/package.json
index b2a94cf..0bf8477 100644
--- a/package.json
+++ b/package.json
@@ -38,7 +38,7 @@
"babel-eslint": "^10.0.3",
"babel-loader": "^8.0.6",
"babel-plugin-add-module-exports": "^1.0.2",
- "babel-plugin-istanbul": "^5.2.0",
+ "babel-plugin-istanbul": "^6.0.0",
"compression-webpack-plugin": "^3.0.0",
"coveralls": "^3.0.6",
"docdash": "^1.1.1",
@@ -49,7 +49,7 @@
"gh-pages": "^2.1.1",
"jsdoc": "^3.6.3",
"nyc": "^15.0.0",
- "sinon": "^7.5.0",
+ "sinon": "^8.0.0",
"testem": "^3.0.0",
"webpack": "^4.41.0",
"webpack-bundle-analyzer": "^3.5.2",
diff --git a/src/bowser.js b/src/bowser.js
index f79e6e0..9b1449e 100644
--- a/src/bowser.js
+++ b/src/bowser.js
@@ -74,4 +74,10 @@ class Bowser {
}
}
+export {
+ BROWSER_MAP,
+ ENGINE_MAP,
+ OS_MAP,
+ PLATFORMS_MAP,
+} from './constants.js';
export default Bowser;
diff --git a/src/constants.js b/src/constants.js
index ca1f5ed..f335032 100644
--- a/src/constants.js
+++ b/src/constants.js
@@ -7,6 +7,7 @@ export const BROWSER_ALIASES_MAP = {
BlackBerry: 'blackberry',
Chrome: 'chrome',
Chromium: 'chromium',
+ Electron: 'electron',
Epiphany: 'epiphany',
Firefox: 'firefox',
Focus: 'focus',
@@ -48,6 +49,7 @@ export const BROWSER_MAP = {
blackberry: 'BlackBerry',
chrome: 'Chrome',
chromium: 'Chromium',
+ electron: 'Electron',
epiphany: 'Epiphany',
firefox: 'Firefox',
focus: 'Focus',
diff --git a/src/parser-browsers.js b/src/parser-browsers.js
index b330d26..7fb4292 100644
--- a/src/parser-browsers.js
+++ b/src/parser-browsers.js
@@ -531,6 +531,21 @@ const browsersList = [
return browser;
},
},
+ {
+ test: [/electron/i],
+ describe(ua) {
+ const browser = {
+ name: 'Electron',
+ };
+ const version = Utils.getFirstMatch(/(?:electron)\/(\d+(\.?_?\d+)+)/i, ua);
+
+ if (version) {
+ browser.version = version;
+ }
+
+ return browser;
+ },
+ },
{
test: [/chromium/i],
describe(ua) {
diff --git a/src/parser-os.js b/src/parser-os.js
index a66a118..c95992d 100644
--- a/src/parser-os.js
+++ b/src/parser-os.js
@@ -28,7 +28,7 @@ export default [
/* Windows */
{
- test: [/windows/i],
+ test: [/windows /i],
describe(ua) {
const version = Utils.getFirstMatch(/Windows ((NT|XP)( \d\d?.\d)?)/i, ua);
const versionName = Utils.getWindowsVersionName(version);
@@ -41,6 +41,18 @@ export default [
},
},
+ /* Firefox on iPad */
+ {
+ test: [/Macintosh(.*?) FxiOS(.*?) Version\//],
+ describe(ua) {
+ const version = Utils.getSecondMatch(/(Version\/)(\d[\d.]+)/, ua);
+ return {
+ name: OS_MAP.iOS,
+ version,
+ };
+ },
+ },
+
/* macOS */
{
test: [/macintosh/i],
diff --git a/src/parser-platforms.js b/src/parser-platforms.js
index f9553bd..9c191ba 100644
--- a/src/parser-platforms.js
+++ b/src/parser-platforms.js
@@ -57,6 +57,18 @@ export default [
},
},
+ /* Firefox on iPad */
+ {
+ test: [/Macintosh(.*?) FxiOS(.*?) Version\//],
+ describe() {
+ return {
+ type: PLATFORMS_MAP.tablet,
+ vendor: 'Apple',
+ model: 'iPad',
+ };
+ },
+ },
+
/* Amazon Kindle Fire */
{
test: [/kftt build/i],
diff --git a/src/parser.js b/src/parser.js
index 1b3681f..2fcfcab 100644
--- a/src/parser.js
+++ b/src/parser.js
@@ -82,7 +82,7 @@ class Parser {
parseBrowser() {
this.parsedResult.browser = {};
- const browserDescriptor = browserParsersList.find((_browser) => {
+ const browserDescriptor = Utils.find(browserParsersList, (_browser) => {
if (typeof _browser.test === 'function') {
return _browser.test(this);
}
@@ -165,7 +165,7 @@ class Parser {
parseOS() {
this.parsedResult.os = {};
- const os = osParsersList.find((_os) => {
+ const os = Utils.find(osParsersList, (_os) => {
if (typeof _os.test === 'function') {
return _os.test(this);
}
@@ -241,7 +241,7 @@ class Parser {
parsePlatform() {
this.parsedResult.platform = {};
- const platform = platformParsersList.find((_platform) => {
+ const platform = Utils.find(platformParsersList, (_platform) => {
if (typeof _platform.test === 'function') {
return _platform.test(this);
}
@@ -292,7 +292,7 @@ class Parser {
parseEngine() {
this.parsedResult.engine = {};
- const engine = enginesParsersList.find((_engine) => {
+ const engine = Utils.find(enginesParsersList, (_engine) => {
if (typeof _engine.test === 'function') {
return _engine.test(this);
}
@@ -328,7 +328,7 @@ class Parser {
* @return {ParsedResult}
*/
getResult() {
- return Object.assign({}, this.parsedResult);
+ return Utils.assign({}, this.parsedResult);
}
/**
@@ -370,7 +370,7 @@ class Parser {
if (platformsAndOSCounter > 0) {
const platformsAndOSNames = Object.keys(platformsAndOSes);
- const OSMatchingDefinition = platformsAndOSNames.find(name => (this.isOS(name)));
+ const OSMatchingDefinition = Utils.find(platformsAndOSNames, name => (this.isOS(name)));
if (OSMatchingDefinition) {
const osResult = this.satisfies(platformsAndOSes[OSMatchingDefinition]);
@@ -380,7 +380,10 @@ class Parser {
}
}
- const platformMatchingDefinition = platformsAndOSNames.find(name => (this.isPlatform(name)));
+ const platformMatchingDefinition = Utils.find(
+ platformsAndOSNames,
+ name => (this.isPlatform(name)),
+ );
if (platformMatchingDefinition) {
const platformResult = this.satisfies(platformsAndOSes[platformMatchingDefinition]);
@@ -392,7 +395,7 @@ class Parser {
if (browsersCounter > 0) {
const browserNames = Object.keys(browsers);
- const matchingDefinition = browserNames.find(name => (this.isBrowser(name, true)));
+ const matchingDefinition = Utils.find(browserNames, name => (this.isBrowser(name, true)));
if (matchingDefinition !== void 0) {
return this.compareVersion(browsers[matchingDefinition]);
diff --git a/src/utils.js b/src/utils.js
index 7e36f8f..d1174bf 100644
--- a/src/utils.js
+++ b/src/utils.js
@@ -210,6 +210,8 @@ export default class Utils {
return -1;
}
}
+
+ return undefined;
}
/**
@@ -231,6 +233,54 @@ export default class Utils {
return result;
}
+ /**
+ * Array::find polyfill
+ *
+ * @param {Array} arr
+ * @param {Function} predicate
+ * @return {Array}
+ */
+ static find(arr, predicate) {
+ let i;
+ let l;
+ if (Array.prototype.find) {
+ return Array.prototype.find.call(arr, predicate);
+ }
+ for (i = 0, l = arr.length; i < l; i += 1) {
+ const value = arr[i];
+ if (predicate(value, i)) {
+ return value;
+ }
+ }
+ return undefined;
+ }
+
+ /**
+ * Object::assign polyfill
+ *
+ * @param {Object} obj
+ * @param {Object} ...objs
+ * @return {Object}
+ */
+ static assign(obj, ...assigners) {
+ const result = obj;
+ let i;
+ let l;
+ if (Object.assign) {
+ return Object.assign(obj, ...assigners);
+ }
+ for (i = 0, l = assigners.length; i < l; i += 1) {
+ const assigner = assigners[i];
+ if (typeof assigner === 'object' && assigner !== null) {
+ const keys = Object.keys(assigner);
+ keys.forEach((key) => {
+ result[key] = assigner[key];
+ });
+ }
+ }
+ return obj;
+ }
+
/**
* Get short version/alias for a browser name
*
@@ -250,10 +300,10 @@ export default class Utils {
* @example
* getBrowserAlias('edge') // Microsoft Edge
*
- * @param {string} browserName
+ * @param {string} browserAlias
* @return {string}
*/
- static getBrowserTypeByAlias(browserAlia) {
- return BROWSER_MAP[browserAlia] || '';
+ static getBrowserTypeByAlias(browserAlias) {
+ return BROWSER_MAP[browserAlias] || '';
}
}
diff --git a/test/acceptance/useragentstrings.yml b/test/acceptance/useragentstrings.yml
index 77821e8..b2a47de 100644
--- a/test/acceptance/useragentstrings.yml
+++ b/test/acceptance/useragentstrings.yml
@@ -1823,6 +1823,22 @@
engine:
name: "Gecko"
version: "20100101"
+ -
+ ua: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15) AppleWebKit/605.1.15 (KHTML, like Gecko) FxiOS/21.0 Version/13.0.3 Safari/605.1.15"
+ spec:
+ browser:
+ name: "Firefox"
+ version: "21.0"
+ os:
+ name: "iOS"
+ version: "13.0.3"
+ platform:
+ type: "tablet"
+ vendor: "Apple"
+ model: "iPad"
+ engine:
+ name: "WebKit"
+ version: "605.1.15"
SeaMonkey:
-
ua: "Mozilla/5.0 (Windows NT 5.2; rv:10.0.1) Gecko/20100101 Firefox/10.0.1 SeaMonkey/2.7.1"
@@ -2505,6 +2521,22 @@
engine:
name: "WebKit"
version: "537.51.1"
+ -
+ ua: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 MicroMessenger/6.5.2.501 NetType/WIFI WindowsWechat"
+ spec:
+ browser:
+ name: "WeChat"
+ version: "6.5.2.501"
+ os:
+ name: "macOS"
+ version: "10.15.1"
+ versionName: "Catalina"
+ platform:
+ type: "desktop"
+ vendor: "Apple"
+ engine:
+ name: "WebKit"
+ version: "605.1.15"
UC Browser:
-
ua: "Mozilla/5.0 (iPad; U; CPU OS 9 like Mac OS X; en-us; iPad4,4) AppleWebKit/534.46 (KHTML, like Gecko) UCBrowser/2.4.0.367 U3/1 Safari/7543.48.3"
@@ -2908,3 +2940,59 @@
engine:
name: "WebKit"
version: "605.1.15"
+ Electron:
+ -
+ ua: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) my-app/1.0.0 Chrome/78.0.3904.113 Electron/7.1.2 Safari/537.36"
+ spec:
+ browser:
+ name: "Electron"
+ version: "7.1.2"
+ os:
+ name: "Windows"
+ version: "NT 10.0"
+ versionName: "10"
+ platform:
+ type: "desktop"
+ engine:
+ name: "Blink"
+ -
+ ua: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.146 Electron/6.1.5 Safari/537.36"
+ spec:
+ browser:
+ name: "Electron"
+ version: "6.1.5"
+ os:
+ name: "Windows"
+ version: "NT 10.0"
+ versionName: "10"
+ platform:
+ type: "desktop"
+ engine:
+ name: "Blink"
+ -
+ ua: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.113 Electron/7.1.2 Safari/537.36"
+ spec:
+ browser:
+ name: "Electron"
+ version: "7.1.2"
+ os:
+ name: "macOS"
+ version: "10.15.1"
+ versionName: "Catalina"
+ platform:
+ type: "desktop"
+ vendor: 'Apple'
+ engine:
+ name: "Blink"
+ -
+ ua: "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.113 Electron/7.1.2 Safari/537.36"
+ spec:
+ browser:
+ name: "Electron"
+ version: "7.1.2"
+ os:
+ name: "Linux"
+ platform:
+ type: "desktop"
+ engine:
+ name: "Blink"
diff --git a/test/unit/utils.js b/test/unit/utils.js
index b41843e..1c2a9d5 100644
--- a/test/unit/utils.js
+++ b/test/unit/utils.js
@@ -1,11 +1,18 @@
import test from 'ava';
import {
- getBrowserAlias,
getFirstMatch,
+ getSecondMatch,
+ matchAndReturnConst,
getWindowsVersionName,
getMacOSVersionName,
getAndroidVersionName,
+ getVersionPrecision,
compareVersions,
+ map,
+ find,
+ assign,
+ getBrowserAlias,
+ getBrowserTypeByAlias
} from '../../src/utils';
test('getFirstMatch', (t) => {
@@ -13,6 +20,16 @@ test('getFirstMatch', (t) => {
t.is(matchedVersion, '11.11.11');
});
+test('getSecondMatch', (t) => {
+ const matchedVersion = getSecondMatch(/version\/(\S+).*version\/(\S+)/i, 'Chrome Version/11.11.11 Chrome Version/22.22.22');
+ t.is(matchedVersion, '22.22.22');
+});
+
+test('matchAndReturnConst', (t) => {
+ const _const = matchAndReturnConst(/version/i, 'version', "_const");
+ t.is(_const, '_const');
+});
+
test('getWindowsVersionName', (t) => {
t.is(getWindowsVersionName('NT 5.0'), '2000');
t.is(getWindowsVersionName('XXX'), void 0);
@@ -32,6 +49,11 @@ test('getAndroidVersionName', (t) => {
t.is(getAndroidVersionName('XXX'), void 0);
});
+test('getVersionPrecision', (t) => {
+ const precision = getVersionPrecision("10.14.5");
+ t.is(precision, 3);
+});
+
test('compareVersions', (t) => {
const comparisionsTasks = [
['9.0', '10', -1],
@@ -68,7 +90,51 @@ test('compareVersions', (t) => {
});
});
+test('map', (t) => {
+ const result = map([1,2], (value) => value+2);
+ t.is(result[0], 3);
+ t.is(result[1], 4);
+ const original = Array.prototype.map;
+ delete Array.prototype.map;
+ const polyfillResult = map([1,2], (value) => value+2);
+ Array.prototype.map = original;
+ t.is(polyfillResult[0], 3);
+ t.is(polyfillResult[1], 4);
+});
+
+test('find', (t) => {
+ const result = find([1,2], (value) => value==2);
+ t.is(result, 2);
+ const original = Array.prototype.find;
+ delete Array.prototype.find;
+ const polyfillResultFound = find([1,2], (value) => value==2);
+ const polyfillResultNotFound = find([1,2], (value) => value==3);
+ Array.prototype.find = original;
+ t.is(polyfillResultFound, 2);
+ t.is(polyfillResultNotFound, undefined);
+});
+
+test('assign', (t) => {
+ const result = assign({}, { a: 1 }, { b: 1 }, { b: 2, c: 3 });
+ t.is(result['a'], 1);
+ t.is(result['b'], 2);
+ t.is(result['c'], 3);
+ const original = Object.assign;
+ delete Object.assign;
+ const polyfillResult = assign({}, { a: 1 }, { b: 1 }, null, { b: 2, c: 3 });
+ Object.assign = original;
+ t.is(polyfillResult['a'], 1);
+ t.is(polyfillResult['b'], 2);
+ t.is(polyfillResult['c'], 3);
+});
+
test('getBrowserAlias', (t) => {
t.is(getBrowserAlias('Microsoft Edge'), 'edge');
t.is(getBrowserAlias('Unexisting Browser'), void 0);
});
+
+test('getBrowserTypeByAlias', (t) => {
+ t.is(getBrowserTypeByAlias('edge'), 'Microsoft Edge');
+ t.is(getBrowserTypeByAlias(void 0), '');
+});
+