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), ''); +}); +