mirror of
https://github.com/faisalman/ua-parser-js.git
synced 2025-11-19 08:50:34 +03:00
Compare commits
4 Commits
2.0.0-alph
...
0.7.34
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3218051f07 | ||
|
|
551ad88474 | ||
|
|
097f736c4d | ||
|
|
73c25771dc |
2
.github/FUNDING.yml
vendored
2
.github/FUNDING.yml
vendored
@@ -1,6 +1,6 @@
|
|||||||
# These are supported funding model platforms
|
# These are supported funding model platforms
|
||||||
|
|
||||||
github: faisalman
|
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||||
patreon: # Replace with a single Patreon username
|
patreon: # Replace with a single Patreon username
|
||||||
open_collective: ua-parser-js
|
open_collective: ua-parser-js
|
||||||
ko_fi: # Replace with a single Ko-fi username
|
ko_fi: # Replace with a single Ko-fi username
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "ua-parser-js",
|
"name": "ua-parser-js",
|
||||||
"version": "2.0.0-alpha.2",
|
"version": "0.7.34",
|
||||||
"authors": [
|
"authors": [
|
||||||
"Faisal Salman <f@faisalman.com>"
|
"Faisal Salman <f@faisalman.com>"
|
||||||
],
|
],
|
||||||
|
|||||||
30
changelog.md
30
changelog.md
@@ -1,39 +1,9 @@
|
|||||||
# UAParser.js Changelog
|
# UAParser.js Changelog
|
||||||
|
|
||||||
# Version 2.0
|
|
||||||
- What's breaking:
|
|
||||||
- Browser detection on mobile device: `"Chrome" => "Mobile Chrome"`, `"Firefox" => "Mobile Firefox"`
|
|
||||||
- OS detection: `"Mac OS" => "macOS"`, `"Chromium OS" => "Chrome OS"`
|
|
||||||
- What's new:
|
|
||||||
- Add some new methods in result object:
|
|
||||||
- Add support for client hints: `withClientHints()`
|
|
||||||
- Utility for easy comparison: `is()`
|
|
||||||
- Utility to print full-name: `toString()`
|
|
||||||
- Add support for ES module `import { UAParser } from 'ua-parser-js'`
|
|
||||||
- Provide Enums `'ua-parser-js/enums'`
|
|
||||||
- Provide Extensions `'ua-parser-js/extensions'`
|
|
||||||
|
|
||||||
## Version 2.0.0-alpha.2
|
|
||||||
- Fix browser result always returning Chromium when using `withClientHints()`
|
|
||||||
- Fix infinite-loop when await-ing `withClientHints()` in non-client-hints browser
|
|
||||||
|
|
||||||
## Version 2.0.0-alpha.1
|
|
||||||
- Initial work on new major version
|
|
||||||
|
|
||||||
|
|
||||||
# Version 0.7 / 1.0
|
# Version 0.7 / 1.0
|
||||||
|
|
||||||
Version 1.0.x is basically the equivalent of version 0.7.x. See [#536](https://github.com/faisalman/ua-parser-js/issues/536) for the reason behind this confusion.
|
Version 1.0.x is basically the equivalent of version 0.7.x. See [#536](https://github.com/faisalman/ua-parser-js/issues/536) for the reason behind this confusion.
|
||||||
|
|
||||||
## Version 0.7.35 / 1.0.35
|
|
||||||
- Fix result from user-supplied user-agent being altered
|
|
||||||
- Add new browser: Heytap, TikTok
|
|
||||||
- Add new engine: LibWeb
|
|
||||||
- Add new OS: SerenityOS
|
|
||||||
- Improve browser detection: Yandex
|
|
||||||
- Improve device detection: iPhone, Amazon Echo
|
|
||||||
- Improve OS detection: iOS
|
|
||||||
|
|
||||||
## Version 0.7.34 / 1.0.34
|
## Version 0.7.34 / 1.0.34
|
||||||
- Fix Sharp Mobile detected as Huawei Tablet
|
- Fix Sharp Mobile detected as Huawei Tablet
|
||||||
- Fix IE8 bug
|
- Fix IE8 bug
|
||||||
|
|||||||
6
dist/ua-parser.min.js
vendored
6
dist/ua-parser.min.js
vendored
File diff suppressed because one or more lines are too long
6
dist/ua-parser.pack.js
vendored
6
dist/ua-parser.pack.js
vendored
File diff suppressed because one or more lines are too long
@@ -1,6 +1,6 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2012-2023 Faisal Salman <<f@faisalman.com>>
|
Copyright (c) 2012-2021 Faisal Salman <<f@faisalman.com>>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
Package.describe({
|
Package.describe({
|
||||||
name: 'faisalman:ua-parser-js',
|
name: 'faisalman:ua-parser-js',
|
||||||
version: '2.0.0-alpha.2',
|
version: '0.7.34',
|
||||||
summary: 'Lightweight JavaScript-based user-agent string parser',
|
summary: 'Lightweight JavaScript-based user-agent string parser',
|
||||||
git: 'https://github.com/faisalman/ua-parser-js.git',
|
git: 'https://github.com/faisalman/ua-parser-js.git',
|
||||||
documentation: 'readme.md'
|
documentation: 'readme.md'
|
||||||
|
|||||||
28
package.json
28
package.json
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"title": "UAParser.js",
|
"title": "UAParser.js",
|
||||||
"name": "ua-parser-js",
|
"name": "ua-parser-js",
|
||||||
"version": "2.0.0-alpha.2",
|
"version": "0.7.34",
|
||||||
"author": "Faisal Salman <f@faisalman.com> (http://faisalman.com)",
|
"author": "Faisal Salman <f@faisalman.com> (http://faisalman.com)",
|
||||||
"description": "Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data. Supports browser & node.js environment",
|
"description": "Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data. Supports browser & node.js environment",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
@@ -140,31 +140,15 @@
|
|||||||
"Yun Young-jin <yupmin@yupmin-office-macmini.local>",
|
"Yun Young-jin <yupmin@yupmin-office-macmini.local>",
|
||||||
"Zach Bjornson <zbbjornson@gmail.com>"
|
"Zach Bjornson <zbbjornson@gmail.com>"
|
||||||
],
|
],
|
||||||
"type": "commonjs",
|
|
||||||
"main": "src/ua-parser.js",
|
"main": "src/ua-parser.js",
|
||||||
"module": "src/ua-parser.mjs",
|
|
||||||
"exports": {
|
|
||||||
".": {
|
|
||||||
"require": "./src/ua-parser.js",
|
|
||||||
"import": "./src/ua-parser.mjs"
|
|
||||||
},
|
|
||||||
"./enums": {
|
|
||||||
"require": "./src/enum/ua-parser-enum.js",
|
|
||||||
"import": "./src/enum/ua-parser-enum.mjs"
|
|
||||||
},
|
|
||||||
"./extensions": {
|
|
||||||
"require": "./src/extension/ua-parser-extension.js",
|
|
||||||
"import": "./src/extension/ua-parser-extension.mjs"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist",
|
||||||
"src"
|
"src"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "uglifyjs src/ua-parser.js -o dist/ua-parser.min.js --comments '/^ UA/' && uglifyjs src/ua-parser.js -o dist/ua-parser.pack.js --comments '/^ UA/' --compress --mangle && node -e \"const fs=require('fs');fs.writeFileSync('src/ua-parser.mjs','// Generated ESM version of UAParser.js\\n// DO NOT EDIT THIS FILE!\\n// Source: /src/ua-parser.js\\n\\nconst window = undefined;\\n\\n'+fs.readFileSync('src/ua-parser.js','utf-8').replace(/\\(func[\\s\\S]+strict\\';/ig,'').replace(/\\/[\\/\\s]+export[\\s\\S]+/ig,'export {UAParser};'),'utf-8');fs.writeFileSync('src/enum/ua-parser-enum.mjs','// Generated ESM version of UAParser.js enums\\n// DO NOT EDIT THIS FILE!\\n// Source: /src/enum/ua-parser-enum.js\\n\\n'+fs.readFileSync('src/enum/ua-parser-enum.js','utf-8').replace(/module\\.exports =/ig,'export'),'utf-8');fs.writeFileSync('src/extension/ua-parser-extension.mjs','// Generated ESM version of UAParser.js extensions\\n// DO NOT EDIT THIS FILE!\\n// Source: /src/extension/ua-parser-extension.js\\n\\n'+fs.readFileSync('src/extension/ua-parser-extension.js','utf-8').replace(/const UA.+\\)/ig,'import UAParser from \\'ua-parser-js\\'').replace(/module\\.exports =/ig,'export'),'utf-8')\"",
|
"build": "uglifyjs src/ua-parser.js -o dist/ua-parser.min.js --comments '/^ UA/' && uglifyjs src/ua-parser.js -o dist/ua-parser.pack.js --comments '/^ UA/' --compress --mangle",
|
||||||
"test": "jshint src/ua-parser.js && mocha -R nyan test",
|
"test": "jshint src/ua-parser.js && mocha -R nyan test/test.js",
|
||||||
"test-ci": "jshint src/ua-parser.js && mocha -R spec test",
|
"test-ci": "jshint src/ua-parser.js && mocha -R spec test/test.js",
|
||||||
"verup": "node ./node_modules/verup",
|
"verup": "node ./node_modules/verup",
|
||||||
"version": "node ./node_modules/verup 0"
|
"version": "node ./node_modules/verup 0"
|
||||||
},
|
},
|
||||||
@@ -213,10 +197,6 @@
|
|||||||
{
|
{
|
||||||
"type": "paypal",
|
"type": "paypal",
|
||||||
"url": "https://paypal.me/faisalman"
|
"url": "https://paypal.me/faisalman"
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/faisalman"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
347
readme.md
347
readme.md
@@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
# UAParser.js
|
# UAParser.js
|
||||||
|
|
||||||
JavaScript library to detect Browser, Engine, OS, CPU, and Device type/model from User-Agent & Client-Hints data that can be used either in browser (client-side) or node.js (server-side).
|
JavaScript library to detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data with relatively small footprint (~17KB minified, ~6KB gzipped) that can be used either in browser (client-side) or node.js (server-side).
|
||||||
|
|
||||||
* Author : Faisal Salman <<f@faisalman.com>>
|
* Author : Faisal Salman <<f@faisalman.com>>
|
||||||
* Demo : https://faisalman.github.io/ua-parser-js
|
* Demo : https://faisalman.github.io/ua-parser-js
|
||||||
@@ -26,7 +26,7 @@ JavaScript library to detect Browser, Engine, OS, CPU, and Device type/model fro
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td align="center" width="200px" rowspan="2"><a href="https://www.npmjs.com/package/@51degrees/ua-parser-js"><img src="images/51degrees.svg" alt="51degrees" width="75%" height="75%" ></a></td>
|
<td align="center" width="200px" rowspan="3"><a href="https://www.npmjs.com/package/@51degrees/ua-parser-js"><img src="images/51degrees.svg" alt="51degrees" width="75%" height="75%" ></a></td>
|
||||||
<td align="left" width="400px"><a href="https://www.npmjs.com/package/@51degrees/ua-parser-js">↗ @51degrees/ua-parser-js</a></td>
|
<td align="left" width="400px"><a href="https://www.npmjs.com/package/@51degrees/ua-parser-js">↗ @51degrees/ua-parser-js</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -34,45 +34,46 @@ JavaScript library to detect Browser, Engine, OS, CPU, and Device type/model fro
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2">
|
<td>
|
||||||
<a href="https://opencollective.com/ua-parser-js">↗ Become a sponsor</a>
|
<p>On 6 March, we’ll be hosting a demonstration of the 51Degrees UAParser. Register your place for the webinar <a href="https://event.webinarjam.com/register/36/6k2gqu5p">↗ here</a>.</p></td>
|
||||||
</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# Version 2.0
|
|
||||||
What's new & breaking, please read [CHANGELOG](changelog.md) before upgrading.
|
|
||||||
|
|
||||||
# Documentation
|
# Documentation
|
||||||
### UAParser([user-agent:string][,extensions:object][,headers:object(since@2.0)])
|
### UAParser([user-agent][,extensions])
|
||||||
|
typeof `user-agent` "string".
|
||||||
|
|
||||||
In the browser environment you dont need to pass the user-agent string to the function, you can just call the funtion and it should automatically get the string from the `window.navigator.userAgent`, but that is not the case in nodejs. The user-agent string must be passed in' nodejs for the function to work. Usually you can find the user agent in: `request.headers["user-agent"]`.
|
typeof `extensions` "array".
|
||||||
|
|
||||||
|
In The Browser environment you dont need to pass the user-agent string to the function, you can just call the funtion and it should automatically get the string from the `window.navigator.userAgent`, but that is not the case in nodejs. The user-agent string must be passed in nodejs for the function to work.
|
||||||
|
Usually you can find the user agent in:
|
||||||
|
`request.headers["user-agent"]`.
|
||||||
|
|
||||||
|
|
||||||
## Constructor
|
## Constructor
|
||||||
When you call `UAParser` with the `new` keyword, `UAParser` will return a new instance with an empty result object, you have to call one of the available methods to get the information from the user-agent string.
|
When you call `UAParser` with the `new` keyword `UAParser` will return a new instance with an empty result object, you have to call one of the available methods to get the information from the user-agent string.
|
||||||
Like so:
|
Like so:
|
||||||
* `new UAParser([user-agent:string][,extensions:object][,headers:object(since@2.0)])`
|
* `new UAParser([uastring][,extensions])`
|
||||||
```js
|
```js
|
||||||
let parser = new UAParser("your user-agent here"); // you need to pass the user-agent for nodejs
|
let parser = new UAParser("user-agent"); // you need to pass the user-agent for nodejs
|
||||||
console.log(parser); // {}
|
console.log(parser); // {}
|
||||||
let parserResults = parser.getResult();
|
let parserResults = parser.getResult();
|
||||||
console.log(parserResults);
|
console.log(parserResults);
|
||||||
/** {
|
/** {
|
||||||
"ua" : "",
|
"ua": "",
|
||||||
"browser" : {},
|
"browser": {},
|
||||||
"engine" : {},
|
"engine": {},
|
||||||
"os" : {},
|
"os": {},
|
||||||
"device" : {},
|
"device": {},
|
||||||
"cpu" : {}
|
"cpu": {}
|
||||||
} */
|
} */
|
||||||
```
|
```
|
||||||
|
|
||||||
When you call UAParser without the `new` keyword, it will automatically call `getResult()` function and return the parsed results.
|
When you call UAParser without the `new` keyword, it will automatically call `getResult()` function and return the parsed results.
|
||||||
* `UAParser([user-agent:string][,extensions:object][,headers:object(since@2.0)])`
|
* `UAParser([uastring][,extensions])`
|
||||||
* returns result object `{ ua: '', browser: {}, cpu: {}, device: {}, engine: {}, os: {} }`
|
* returns result object `{ ua: '', browser: {}, cpu: {}, device: {}, engine: {}, os: {} }`
|
||||||
|
|
||||||
## Methods
|
## Methods
|
||||||
@@ -90,6 +91,7 @@ The methods are self explanatory, here's a small overview on all the available m
|
|||||||
* `getUA()` - returns the user-agent string.
|
* `getUA()` - returns the user-agent string.
|
||||||
* `setUA(user-agent)` - set a custom user-agent to be parsed.
|
* `setUA(user-agent)` - set a custom user-agent to be parsed.
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
* `getResult()`
|
* `getResult()`
|
||||||
@@ -102,19 +104,19 @@ The methods are self explanatory, here's a small overview on all the available m
|
|||||||
# Possible 'browser.name':
|
# Possible 'browser.name':
|
||||||
2345Explorer, 360 Browser, Amaya, Android Browser, Arora, Avant, Avast, AVG,
|
2345Explorer, 360 Browser, Amaya, Android Browser, Arora, Avant, Avast, AVG,
|
||||||
BIDUBrowser, Baidu, Basilisk, Blazer, Bolt, Brave, Bowser, Camino, Chimera,
|
BIDUBrowser, Baidu, Basilisk, Blazer, Bolt, Brave, Bowser, Camino, Chimera,
|
||||||
[Mobile] Chrome [Headless/WebView], Chromium, Cobalt, Comodo Dragon, Dillo,
|
Chrome Headless, Chrome WebView, Chrome, Chromium, Cobalt, Comodo Dragon, Dillo,
|
||||||
Dolphin, Doris, DuckDuckGo, Edge, Electron, Epiphany, Facebook, Falkon, Fennec,
|
Dolphin, Doris, DuckDuckGo, Edge, Electron, Epiphany, Facebook, Falkon, Fennec,
|
||||||
Firebird, [Mobile] Firefox [Focus/Reality], Flock, Flow, GSA, GoBrowser, HeyTap,
|
Firebird, Firefox [Focus/Reality], Flock, Flow, GSA, GoBrowser, Huawei Browser,
|
||||||
Huawei Browser, ICE Browser, IE, IEMobile, IceApe, IceCat, IceDragon, Iceweasel,
|
ICE Browser, IE, IEMobile, IceApe, IceCat, IceDragon, Iceweasel, Instagram,
|
||||||
Instagram, Iridium, Iron, Jasmine, Kakao[Story/Talk], K-Meleon, Kindle, Klar,
|
Iridium, Iron, Jasmine, Kakao[Story/Talk], K-Meleon, Kindle, Klar, Konqueror,
|
||||||
Konqueror, LBBROWSER, Line, LinkedIn, Links, Lunascape, Lynx, MIUI Browser,
|
LBBROWSER, Line, LinkedIn, Links, Lunascape, Lynx, MIUI Browser, Maemo Browser,
|
||||||
Maemo Browser, Maemo, Maxthon, MetaSr Midori, Minimo, Mosaic, Mozilla, NetFront,
|
Maemo, Maxthon, MetaSr Midori, Minimo, Mobile Safari, Mosaic, Mozilla, NetFront,
|
||||||
NetSurf, Netfront, Netscape, NokiaBrowser, Obigo, Oculus Browser, OmniWeb,
|
NetSurf, Netfront, Netscape, NokiaBrowser, Obigo, Oculus Browser, OmniWeb,
|
||||||
Opera Coast, Opera [Mini/Mobi/Tablet], PaleMoon, PhantomJS, Phoenix, Polaris,
|
Opera Coast, Opera [Mini/Mobi/Tablet], PaleMoon, PhantomJS, Phoenix, Polaris,
|
||||||
Puffin, QQ, QQBrowser, QQBrowserLite, Quark, QupZilla, RockMelt, [Mobile] Safari,
|
Puffin, QQ, QQBrowser, QQBrowserLite, Quark, QupZilla, RockMelt, Safari,
|
||||||
Sailfish Browser, Samsung Browser, SeaMonkey, Silk, Skyfire, Sleipnir, Slim,
|
Sailfish Browser, Samsung Browser, SeaMonkey, Silk, Skyfire, Sleipnir, Slim,
|
||||||
SlimBrowser, Swiftfox, Tesla, TikTok, Tizen Browser, UCBrowser, UP.Browser, Viera,
|
SlimBrowser, Swiftfox, Tesla, Tizen Browser, UCBrowser, UP.Browser, Viera,
|
||||||
Vivaldi, Waterfox, WeChat, Weibo, Yandex, baidu, iCab, w3m, Whale Browser, ...
|
Vivaldi, Waterfox, WeChat, Weibo, Yandex, baidu, iCab, w3m, Whale Browser...
|
||||||
|
|
||||||
# 'browser.version' determined dynamically
|
# 'browser.version' determined dynamically
|
||||||
```
|
```
|
||||||
@@ -148,8 +150,8 @@ Siemens, Sony[Ericsson], Sprint, Tesla, Vivo, Vodafone, Xbox, Xiaomi, Zebra, ZTE
|
|||||||
|
|
||||||
```sh
|
```sh
|
||||||
# Possible 'engine.name'
|
# Possible 'engine.name'
|
||||||
Amaya, Blink, EdgeHTML, Flow, Gecko, Goanna, iCab, KHTML, LibWeb, Links, Lynx,
|
Amaya, Blink, EdgeHTML, Flow, Gecko, Goanna, iCab, KHTML, Links, Lynx, NetFront,
|
||||||
NetFront, NetSurf, Presto, Tasman, Trident, w3m, WebKit
|
NetSurf, Presto, Tasman, Trident, w3m, WebKit
|
||||||
|
|
||||||
# 'engine.version' determined dynamically
|
# 'engine.version' determined dynamically
|
||||||
```
|
```
|
||||||
@@ -165,9 +167,8 @@ Fuchsia, Gentoo, GhostBSD, GNU, Haiku, HarmonyOS, HP-UX, Hurd, iOS, Joli, KaiOS,
|
|||||||
Linpus, Linspire,Linux, Mac OS, Maemo, Mageia, Mandriva, Manjaro, MeeGo, Minix,
|
Linpus, Linspire,Linux, Mac OS, Maemo, Mageia, Mandriva, Manjaro, MeeGo, Minix,
|
||||||
Mint, Morph OS, NetBSD, NetRange, NetTV, Nintendo, OpenBSD, OpenVMS, OS/2, Palm,
|
Mint, Morph OS, NetBSD, NetRange, NetTV, Nintendo, OpenBSD, OpenVMS, OS/2, Palm,
|
||||||
PC-BSD, PCLinuxOS, Plan9, PlayStation, QNX, Raspbian, RedHat, RIM Tablet OS,
|
PC-BSD, PCLinuxOS, Plan9, PlayStation, QNX, Raspbian, RedHat, RIM Tablet OS,
|
||||||
RISC OS, Sabayon, Sailfish, SerenityOS, Series40, Slackware, Solaris, SUSE, Symbian,
|
RISC OS, Sabayon, Sailfish, Series40, Slackware, Solaris, SUSE, Symbian, Tizen,
|
||||||
Tizen, Ubuntu, Unix, VectorLinux, Viera, watchOS, WebOS, Windows [Phone/Mobile],
|
Ubuntu, Unix, VectorLinux, Viera, watchOS, WebOS, Windows [Phone/Mobile], Zenwalk, ...
|
||||||
Zenwalk, ...
|
|
||||||
|
|
||||||
# 'os.version' determined dynamically
|
# 'os.version' determined dynamically
|
||||||
```
|
```
|
||||||
@@ -187,214 +188,6 @@ Zenwalk, ...
|
|||||||
* set UA string to be parsed
|
* set UA string to be parsed
|
||||||
* returns current instance
|
* returns current instance
|
||||||
|
|
||||||
#### * `is():boolean` utility `since@2.0`
|
|
||||||
|
|
||||||
```js
|
|
||||||
// Is just a shorthand comparison to check whether the value of specified item equals one of its properties (in a case-insensitive way)
|
|
||||||
// so that instead of write it using `==` operator like this:
|
|
||||||
|
|
||||||
let ua = UAParser();
|
|
||||||
let device = ua.device;
|
|
||||||
let os = ua.os;
|
|
||||||
|
|
||||||
if (device.type == "mobile" && os.name != "iOS") {}
|
|
||||||
if (device.type == "smarttv" || device.vendor == "Samsung") {}
|
|
||||||
|
|
||||||
// we can also write the comparison above into as follow:
|
|
||||||
|
|
||||||
if (device.is("mobile") && !os.is("iOS")) {}
|
|
||||||
if (device.is("SmartTV") || device.is("SaMsUnG")) {}
|
|
||||||
|
|
||||||
/*
|
|
||||||
For device, properties will be checked in this particular order: type, model, vendor
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Another examples:
|
|
||||||
|
|
||||||
let uap = new UAParser('Mozilla/5.0 (Mobile; Windows Phone 8.1; Android 4.0; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 635) like iPhone OS 7_0_3 Mac OS X AppleWebKit/537 (KHTML, like Gecko) Mobile Safari/537');
|
|
||||||
|
|
||||||
uap.getBrowser().name; // "IEMobile"
|
|
||||||
uap.getBrowser().is("IEMobile"); // true
|
|
||||||
uap.getCPU().is("ARM"); // true
|
|
||||||
|
|
||||||
uap.getOS().name; // "Windows Phone"
|
|
||||||
uap.getOS().is("Windows Phone"); // true
|
|
||||||
|
|
||||||
uap.getDevice(); // { vendor: "Nokia", model: "Lumia 635", type: "mobile" }
|
|
||||||
uap.getResult().device; // { vendor: "Nokia", model: "Lumia 635", type: "mobile" }
|
|
||||||
|
|
||||||
let device = uap.getDevice();
|
|
||||||
device.is("mobile"); // true
|
|
||||||
device.is("Lumia 635"); // true
|
|
||||||
device.is("Nokia"); // true
|
|
||||||
device.is("iPhone"); // false
|
|
||||||
uap.getResult().device.is("Nokia"); // true
|
|
||||||
uap.getResult().device.model; // "Lumia 635"
|
|
||||||
|
|
||||||
uap.setUA("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36");
|
|
||||||
|
|
||||||
let browser = uap.getBrowser();
|
|
||||||
browser.is("IEMobile"); // false
|
|
||||||
browser.is("Chrome"); // true
|
|
||||||
|
|
||||||
uap.getResult().browser.is("Edge"); // false
|
|
||||||
uap.getResult().os.name // "Mac OS"
|
|
||||||
uap.getResult().os.is("Mac OS"); // true
|
|
||||||
uap.getResult().os.version; // "10.6.8"
|
|
||||||
|
|
||||||
let engine = uap.getEngine();
|
|
||||||
engine.is("Blink"); // true
|
|
||||||
```
|
|
||||||
|
|
||||||
#### * `toString():string` utility `since@2.0`
|
|
||||||
|
|
||||||
```js
|
|
||||||
// Retrieve full-name values as a string
|
|
||||||
|
|
||||||
/*
|
|
||||||
Values will be concatenated following this pattern:
|
|
||||||
* browser : name + version
|
|
||||||
* cpu : architecture
|
|
||||||
* device : vendor + model
|
|
||||||
* engine : name + version
|
|
||||||
* os : name + version
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Usage examples
|
|
||||||
|
|
||||||
let uap = new UAParser('Mozilla/5.0 (Mobile; Windows Phone 8.1; Android 4.0; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 635) like iPhone OS 7_0_3 Mac OS X AppleWebKit/537 (KHTML, like Gecko) Mobile Safari/537');
|
|
||||||
|
|
||||||
uap.getDevice(); // {
|
|
||||||
// vendor: "Nokia",
|
|
||||||
// model: "Lumia 635",
|
|
||||||
// type: "mobile"
|
|
||||||
// }
|
|
||||||
uap.getDevice().toString(); // "Nokia Lumia 635"
|
|
||||||
|
|
||||||
uap.getResult().os.name; // "Windows Phone"
|
|
||||||
uap.getResult().os.version; // "8.1"
|
|
||||||
uap.getResult().os.toString(); // "Windows Phone 8.1"
|
|
||||||
|
|
||||||
uap.setUA("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36");
|
|
||||||
uap.getBrowser().name; // "Chrome"
|
|
||||||
uap.getBrowser().version; // "28.0.1500.95"
|
|
||||||
uap.getBrowser().major; // "28"
|
|
||||||
uap.getBrowser().toString(); // "Chrome 28.0.1500.95"
|
|
||||||
|
|
||||||
let engine = uap.getEngine();
|
|
||||||
engine.name; // "Blink"
|
|
||||||
engine.version; // "28.0.1500.95"
|
|
||||||
engine.toString(); // "Blink 28.0.1500.95"
|
|
||||||
```
|
|
||||||
|
|
||||||
#### * `withClientHints():Promise<object>|Thenable<object>|object` `since@2.0`
|
|
||||||
|
|
||||||
Recently, Chrome limits the information exposed through user-agent and introduces a new experimental set of data called "client-hints". In browser-environment, obtaining the client-hints data via JavaScript must be done in an asynchronous way. In `UAParser` you can chain the result object from `get*` method with `withClientHints()` to also read the client-hints data from the browser and return the updated data as a `Promise`.
|
|
||||||
|
|
||||||
```js
|
|
||||||
// client-side example
|
|
||||||
(async function () {
|
|
||||||
let ua = new UAParser();
|
|
||||||
|
|
||||||
// get browser data from user-agent only :
|
|
||||||
let browser = ua.getBrowser();
|
|
||||||
console.log('Using User-Agent: ', browser);
|
|
||||||
|
|
||||||
// get browser data from client-hints (with user-agent as fallback) :
|
|
||||||
browser = await ua.getBrowser().withClientHints();
|
|
||||||
console.log('Using Client-Hints: ', browser);
|
|
||||||
|
|
||||||
// alternatively :
|
|
||||||
ua.getBrowser().withClientHints().then(function (browser) {
|
|
||||||
console.log('Using Client-Hints: ', browser);
|
|
||||||
});
|
|
||||||
})();
|
|
||||||
```
|
|
||||||
|
|
||||||
Along with `User-Agent` HTTP header, Chrome also sends this client-hints data by default under `Sec-CH-UA-*` HTTP headers in each request. In server-side development, you can capture this extra information by passing the `req.headers` to `UAParser()` (see examples below). When using `withClientHints()` in nodejs environment and browser without client-hints support (basically anything that's not Chromium-based), it will returns a new object with updated data.
|
|
||||||
|
|
||||||
```js
|
|
||||||
// server-side example
|
|
||||||
|
|
||||||
// Suppose we got a request having these HTTP headers:
|
|
||||||
const request = {
|
|
||||||
headers : {
|
|
||||||
'user-agent' : 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36',
|
|
||||||
|
|
||||||
'sec-ch-ua-mobile' : '?1',
|
|
||||||
'sec-ch-ua-model' : 'Galaxy S3 Marketing',
|
|
||||||
'sec-ch-ua-platform' : 'Android'
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const result1 = UAParser(request.headers); // parse only "user-agent" header
|
|
||||||
const result2 = UAParser(request.headers).withClientHints(); // update with "sec-ch-ua" headers
|
|
||||||
|
|
||||||
console.log(result1.os.name); // "Linux"
|
|
||||||
console.log(result1.device.type); // undefined
|
|
||||||
console.log(result1.device.model); // undefined
|
|
||||||
|
|
||||||
console.log(result2.os.name); // "Android"
|
|
||||||
console.log(result2.device.type); // "mobile"
|
|
||||||
console.log(result2.device.model); // "Galaxy S3 Marketing"
|
|
||||||
|
|
||||||
new UAParser(request.headers)
|
|
||||||
.getBrowser()
|
|
||||||
.withClientHints()
|
|
||||||
.then((browser) => {
|
|
||||||
console.log(browser.toString()); // Chrome 110.0.0.0
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
## Extending Regex
|
|
||||||
|
|
||||||
If you want to detect something that's not currently provided by UAParser.js (eg: `bots`, specific apps, etc), you can pass a list of regexes to extend internal UAParser.js regexes with your own.
|
|
||||||
|
|
||||||
* `UAParser([uastring,] extensions [,headers:object(since@2.0)])`
|
|
||||||
|
|
||||||
```js
|
|
||||||
// Example:
|
|
||||||
const myOwnListOfBrowsers = [
|
|
||||||
[/(mybrowser)\/([\w\.]+)/i], [UAParser.BROWSER.NAME, UAParser.BROWSER.VERSION, ['type', 'bot']]
|
|
||||||
];
|
|
||||||
|
|
||||||
const myUA = 'Mozilla/5.0 MyBrowser/1.3';
|
|
||||||
|
|
||||||
let myParser = new UAParser({ browser: myOwnListOfBrowsers });
|
|
||||||
|
|
||||||
console.log(myParser.setUA(myUA).getBrowser()); // {name: "MyBrowser", version: "1.3", major: "1", type : "bot"}
|
|
||||||
console.log(myParser.getBrowser().is('bot')); // true
|
|
||||||
|
|
||||||
// Another example:
|
|
||||||
const myOwnListOfDevices = [
|
|
||||||
[/(mytab) ([\w ]+)/i], [UAParser.DEVICE.VENDOR, UAParser.DEVICE.MODEL, [UAParser.DEVICE.TYPE, UAParser.DEVICE.TABLET]],
|
|
||||||
[/(myphone)/i], [UAParser.DEVICE.VENDOR, [UAParser.DEVICE.TYPE, UAParser.DEVICE.MOBILE]]
|
|
||||||
];
|
|
||||||
|
|
||||||
const myUA2 = 'Mozilla/5.0 MyTab 14 Pro Max';
|
|
||||||
|
|
||||||
let myParser2 = new UAParser({
|
|
||||||
browser: myOwnListOfBrowsers,
|
|
||||||
device: myOwnListOfDevices
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log(myParser2.setUA(myUA2).getDevice()); // {vendor: "MyTab", model: "14 Pro Max", type: "tablet"}
|
|
||||||
```
|
|
||||||
|
|
||||||
Some basic extensions (although not very complete at the moment) can also be found under `ua-parser-js/extensions` submodule.
|
|
||||||
|
|
||||||
```js
|
|
||||||
import { UAParser } from 'ua-parser-js';
|
|
||||||
import { Emails } from 'ua-parser-js/extensions';
|
|
||||||
|
|
||||||
const browser = new UAParser(Emails)
|
|
||||||
.setUA('Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.13.0')
|
|
||||||
.getBrowser();
|
|
||||||
|
|
||||||
console.log(browser.name); // Thunderbird
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
# Usage
|
# Usage
|
||||||
|
|
||||||
## Using HTML
|
## Using HTML
|
||||||
@@ -406,8 +199,8 @@ console.log(browser.name); // Thunderbird
|
|||||||
<script src="ua-parser.min.js"></script>
|
<script src="ua-parser.min.js"></script>
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
var uap = new UAParser();
|
var parser = new UAParser();
|
||||||
console.log(uap.getResult());
|
console.log(parser.getResult());
|
||||||
/*
|
/*
|
||||||
/// This will print an object structured like this:
|
/// This will print an object structured like this:
|
||||||
{
|
{
|
||||||
@@ -415,7 +208,7 @@ console.log(browser.name); // Thunderbird
|
|||||||
browser: {
|
browser: {
|
||||||
name: "",
|
name: "",
|
||||||
version: "",
|
version: "",
|
||||||
major: ""
|
major: "" //@deprecated
|
||||||
},
|
},
|
||||||
engine: {
|
engine: {
|
||||||
name: "",
|
name: "",
|
||||||
@@ -439,10 +232,10 @@ console.log(browser.name); // Thunderbird
|
|||||||
|
|
||||||
// Now let's try a custom user-agent string as an example
|
// Now let's try a custom user-agent string as an example
|
||||||
var uastring1 = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.2 (KHTML, like Gecko) Ubuntu/11.10 Chromium/15.0.874.106 Chrome/15.0.874.106 Safari/535.2";
|
var uastring1 = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.2 (KHTML, like Gecko) Ubuntu/11.10 Chromium/15.0.874.106 Chrome/15.0.874.106 Safari/535.2";
|
||||||
uap.setUA(uastring1);
|
parser.setUA(uastring1);
|
||||||
var result = uap.getResult();
|
var result = parser.getResult();
|
||||||
// You can also use UAParser constructor directly without having to create an instance:
|
// You can also use UAParser constructor directly without having to create an instance:
|
||||||
// var ua = UAParser(uastring1);
|
// var result = UAParser(uastring1);
|
||||||
|
|
||||||
console.log(result.browser); // {name: "Chromium", version: "15.0.874.106"}
|
console.log(result.browser); // {name: "Chromium", version: "15.0.874.106"}
|
||||||
console.log(result.device); // {model: undefined, type: undefined, vendor: undefined}
|
console.log(result.device); // {model: undefined, type: undefined, vendor: undefined}
|
||||||
@@ -453,14 +246,14 @@ console.log(browser.name); // Thunderbird
|
|||||||
|
|
||||||
// Do some other tests
|
// Do some other tests
|
||||||
var uastring2 = "Mozilla/5.0 (compatible; Konqueror/4.1; OpenBSD) KHTML/4.1.4 (like Gecko)";
|
var uastring2 = "Mozilla/5.0 (compatible; Konqueror/4.1; OpenBSD) KHTML/4.1.4 (like Gecko)";
|
||||||
console.log(uap.setUA(uastring2).getBrowser().name); // "Konqueror"
|
console.log(parser.setUA(uastring2).getBrowser().name); // "Konqueror"
|
||||||
console.log(uap.getOS()); // {name: "OpenBSD", version: undefined}
|
console.log(parser.getOS()); // {name: "OpenBSD", version: undefined}
|
||||||
console.log(uap.getEngine()); // {name: "KHTML", version: "4.1.4"}
|
console.log(parser.getEngine()); // {name: "KHTML", version: "4.1.4"}
|
||||||
|
|
||||||
var uastring3 = 'Mozilla/5.0 (PlayBook; U; RIM Tablet OS 1.0.0; en-US) AppleWebKit/534.11 (KHTML, like Gecko) Version/7.1.0.7 Safari/534.11';
|
var uastring3 = 'Mozilla/5.0 (PlayBook; U; RIM Tablet OS 1.0.0; en-US) AppleWebKit/534.11 (KHTML, like Gecko) Version/7.1.0.7 Safari/534.11';
|
||||||
console.log(uap.setUA(uastring3).getDevice().model); // "PlayBook"
|
console.log(parser.setUA(uastring3).getDevice().model); // "PlayBook"
|
||||||
console.log(uap.getOS()) // {name: "RIM Tablet OS", version: "1.0.0"}
|
console.log(parser.getOS()) // {name: "RIM Tablet OS", version: "1.0.0"}
|
||||||
console.log(uap.getBrowser().name); // "Safari"
|
console.log(parser.getBrowser().name); // "Safari"
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
@@ -479,24 +272,11 @@ $ npm install ua-parser-js
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
var http = require('http');
|
var http = require('http');
|
||||||
var uap = require('ua-parser-js');
|
var parser = require('ua-parser-js');
|
||||||
|
|
||||||
http.createServer(function (req, res) {
|
http.createServer(function (req, res) {
|
||||||
// get user-agent header
|
// get user-agent header
|
||||||
var ua = uap(req.headers['user-agent']);
|
var ua = parser(req.headers['user-agent']);
|
||||||
|
|
||||||
/* // BEGIN since@2.0 - you can also pass client-hints data to UAParser
|
|
||||||
|
|
||||||
// note: only works in secure context (https:// or localhost or file://)
|
|
||||||
|
|
||||||
var getHighEntropyValues = 'Sec-CH-UA-Full-Version-List, Sec-CH-UA-Mobile, Sec-CH-UA-Model, Sec-CH-UA-Platform, Sec-CH-UA-Platform-Version, Sec-CH-UA-Arch, Sec-CH-UA-Bitness';
|
|
||||||
res.setHeader('Accept-CH', getHighEntropyValues);
|
|
||||||
res.setHeader('Critical-CH', getHighEntropyValues);
|
|
||||||
|
|
||||||
var ua = uap(req.headers).withClientHints();
|
|
||||||
|
|
||||||
// END since@2.0 */
|
|
||||||
|
|
||||||
// write the result as response
|
// write the result as response
|
||||||
res.end(JSON.stringify(ua, null, ' '));
|
res.end(JSON.stringify(ua, null, ' '));
|
||||||
})
|
})
|
||||||
@@ -505,19 +285,6 @@ http.createServer(function (req, res) {
|
|||||||
console.log('Server running at http://127.0.0.1:1337/');
|
console.log('Server running at http://127.0.0.1:1337/');
|
||||||
```
|
```
|
||||||
|
|
||||||
## Using ES Modules
|
|
||||||
|
|
||||||
```js
|
|
||||||
import { UAParser } from 'ua-parser-js';
|
|
||||||
|
|
||||||
const { browser, cpu, device } = UAParser('Mozilla/5.0 (X11; U; Linux armv7l; en-GB; rv:1.9.2a1pre) Gecko/20090928 Firefox/3.5 Maemo Browser 1.4.1.22 RX-51 N900');
|
|
||||||
|
|
||||||
console.log(browser.name); // Maemo Browser
|
|
||||||
console.log(cpu.is('arm')); // true
|
|
||||||
console.log(device.is('mobile')); // true
|
|
||||||
console.log(device.model); // N900
|
|
||||||
```
|
|
||||||
|
|
||||||
## Using TypeScript
|
## Using TypeScript
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
@@ -553,6 +320,20 @@ console.log(parseInt($.ua.browser.version.split('.')[0], 10)); // 4
|
|||||||
$('body').addClass('ua-browser-' + $.ua.browser.name + ' ua-devicetype-' + $.ua.device.type);
|
$('body').addClass('ua-browser-' + $.ua.browser.name + ' ua-devicetype-' + $.ua.device.type);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Using Extension
|
||||||
|
|
||||||
|
* `UAParser([uastring,] extensions)`
|
||||||
|
|
||||||
|
```js
|
||||||
|
// Example:
|
||||||
|
var myOwnListOfBrowsers = [
|
||||||
|
[/(mybrowser)\/([\w\.]+)/i], [UAParser.BROWSER.NAME, UAParser.BROWSER.VERSION]
|
||||||
|
];
|
||||||
|
var myParser = new UAParser({ browser: myOwnListOfBrowsers });
|
||||||
|
var myUA = 'Mozilla/5.0 MyBrowser/1.3';
|
||||||
|
console.log(myParser.setUA(myUA).getBrowser()); // {name: "MyBrowser", version: "1.3"}
|
||||||
|
```
|
||||||
|
|
||||||
# Development
|
# Development
|
||||||
|
|
||||||
## Backers & Sponsors
|
## Backers & Sponsors
|
||||||
@@ -582,7 +363,7 @@ Made with [contributors-img](https://contrib.rocks).
|
|||||||
|
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2012-2023 Faisal Salman <<f@faisalman.com>>
|
Copyright (c) 2012-2021 Faisal Salman <<f@faisalman.com>>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -1,101 +0,0 @@
|
|||||||
///////////////////////////////////////////////
|
|
||||||
/* Enums for UAParser.js v2.0.0-alpha.2
|
|
||||||
https://github.com/faisalman/ua-parser-js
|
|
||||||
Author: Faisal Salman <f@faisalman.com>
|
|
||||||
MIT License */
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
|
|
||||||
const BrowserName = Object.freeze({
|
|
||||||
CHROME : 'Chrome',
|
|
||||||
EDGE : 'Edge',
|
|
||||||
SAFARI : 'Safari',
|
|
||||||
FIREFOX : 'Firefox',
|
|
||||||
OPERA : 'Opera',
|
|
||||||
MOBILE_CHROME : 'Mobile Chrome',
|
|
||||||
MOBILE_SAFARI : 'Mobile Safari',
|
|
||||||
MOBILE_FIREFOX : 'Mobile Firefox',
|
|
||||||
ANDROID_BROWSER : 'Android Browser'
|
|
||||||
|
|
||||||
// TODO : test!
|
|
||||||
});
|
|
||||||
|
|
||||||
const CPUArch = Object.freeze({
|
|
||||||
IA32 : 'ia32',
|
|
||||||
AMD64 : 'amd64',
|
|
||||||
IA64 : 'ia64',
|
|
||||||
ARM : 'arm',
|
|
||||||
ARM64 : 'arm64',
|
|
||||||
ARMHF : 'armhf',
|
|
||||||
_68K : '68k',
|
|
||||||
AVR : 'avr',
|
|
||||||
IRIX : 'irix',
|
|
||||||
IRIX64 : 'irix64',
|
|
||||||
MIPS : 'mips',
|
|
||||||
MIPS64 : 'mips64',
|
|
||||||
PPC : 'ppc',
|
|
||||||
SPARC : 'sparc',
|
|
||||||
SPARC64 : 'sparc64'
|
|
||||||
});
|
|
||||||
|
|
||||||
const DeviceType = Object.freeze({
|
|
||||||
MOBILE : 'mobile',
|
|
||||||
TABLET : 'tablet',
|
|
||||||
SMARTTV : 'smarttv',
|
|
||||||
CONSOLE : 'console',
|
|
||||||
WEARABLE: 'wearable',
|
|
||||||
EMBEDDED: 'embedded'
|
|
||||||
});
|
|
||||||
|
|
||||||
const DeviceVendor = Object.freeze({
|
|
||||||
APPLE : 'Apple',
|
|
||||||
SAMSUNG : 'Samsung',
|
|
||||||
HUAWEI : 'Huawei',
|
|
||||||
XIAOMI : 'Xiaomi',
|
|
||||||
OPPO : 'OPPO',
|
|
||||||
VIVO : 'Vivo',
|
|
||||||
REALME : 'Realme',
|
|
||||||
LENOVO : 'Lenovo',
|
|
||||||
LG : 'LG'
|
|
||||||
|
|
||||||
// TODO : test!
|
|
||||||
});
|
|
||||||
|
|
||||||
const EngineName = Object.freeze({
|
|
||||||
AMAYA : 'Amaya',
|
|
||||||
BLINK : 'Blink',
|
|
||||||
EDGEHTML: 'EdgeHTML',
|
|
||||||
FLOW : 'Flow',
|
|
||||||
GECKO : 'Gecko',
|
|
||||||
GOANNA : 'Goanna',
|
|
||||||
ICAB : 'iCab',
|
|
||||||
LIBWEB : 'LibWeb',
|
|
||||||
KHTML : 'KHTML',
|
|
||||||
LINKS : 'Links',
|
|
||||||
LYNX : 'Lynx',
|
|
||||||
NETFRONT: 'NetFront',
|
|
||||||
NETSURF : 'NetSurf',
|
|
||||||
PRESTO : 'Presto',
|
|
||||||
TASMAN : 'Tasman',
|
|
||||||
TRIDENT : 'Trident',
|
|
||||||
W3M : 'w3m',
|
|
||||||
WEBKIT : 'WebKit'
|
|
||||||
});
|
|
||||||
|
|
||||||
const OSName = Object.freeze({
|
|
||||||
WINDOWS : 'Windows',
|
|
||||||
LINUX : 'Linux',
|
|
||||||
MACOS : 'macOS',
|
|
||||||
IOS : 'iOS',
|
|
||||||
ANDROID : 'Android'
|
|
||||||
|
|
||||||
// TODO : test!
|
|
||||||
});
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
BrowserName,
|
|
||||||
CPUArch,
|
|
||||||
DeviceType,
|
|
||||||
DeviceVendor,
|
|
||||||
EngineName,
|
|
||||||
OSName
|
|
||||||
}
|
|
||||||
@@ -1,105 +0,0 @@
|
|||||||
// Generated ESM version of UAParser.js enums
|
|
||||||
// DO NOT EDIT THIS FILE!
|
|
||||||
// Source: /src/enum/ua-parser-enum.js
|
|
||||||
|
|
||||||
///////////////////////////////////////////////
|
|
||||||
/* Enums for UAParser.js v2.0.0-alpha.2
|
|
||||||
https://github.com/faisalman/ua-parser-js
|
|
||||||
Author: Faisal Salman <f@faisalman.com>
|
|
||||||
MIT License */
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
|
|
||||||
const BrowserName = Object.freeze({
|
|
||||||
CHROME : 'Chrome',
|
|
||||||
EDGE : 'Edge',
|
|
||||||
SAFARI : 'Safari',
|
|
||||||
FIREFOX : 'Firefox',
|
|
||||||
OPERA : 'Opera',
|
|
||||||
MOBILE_CHROME : 'Mobile Chrome',
|
|
||||||
MOBILE_SAFARI : 'Mobile Safari',
|
|
||||||
MOBILE_FIREFOX : 'Mobile Firefox',
|
|
||||||
ANDROID_BROWSER : 'Android Browser'
|
|
||||||
|
|
||||||
// TODO : test!
|
|
||||||
});
|
|
||||||
|
|
||||||
const CPUArch = Object.freeze({
|
|
||||||
IA32 : 'ia32',
|
|
||||||
AMD64 : 'amd64',
|
|
||||||
IA64 : 'ia64',
|
|
||||||
ARM : 'arm',
|
|
||||||
ARM64 : 'arm64',
|
|
||||||
ARMHF : 'armhf',
|
|
||||||
_68K : '68k',
|
|
||||||
AVR : 'avr',
|
|
||||||
IRIX : 'irix',
|
|
||||||
IRIX64 : 'irix64',
|
|
||||||
MIPS : 'mips',
|
|
||||||
MIPS64 : 'mips64',
|
|
||||||
PPC : 'ppc',
|
|
||||||
SPARC : 'sparc',
|
|
||||||
SPARC64 : 'sparc64'
|
|
||||||
});
|
|
||||||
|
|
||||||
const DeviceType = Object.freeze({
|
|
||||||
MOBILE : 'mobile',
|
|
||||||
TABLET : 'tablet',
|
|
||||||
SMARTTV : 'smarttv',
|
|
||||||
CONSOLE : 'console',
|
|
||||||
WEARABLE: 'wearable',
|
|
||||||
EMBEDDED: 'embedded'
|
|
||||||
});
|
|
||||||
|
|
||||||
const DeviceVendor = Object.freeze({
|
|
||||||
APPLE : 'Apple',
|
|
||||||
SAMSUNG : 'Samsung',
|
|
||||||
HUAWEI : 'Huawei',
|
|
||||||
XIAOMI : 'Xiaomi',
|
|
||||||
OPPO : 'OPPO',
|
|
||||||
VIVO : 'Vivo',
|
|
||||||
REALME : 'Realme',
|
|
||||||
LENOVO : 'Lenovo',
|
|
||||||
LG : 'LG'
|
|
||||||
|
|
||||||
// TODO : test!
|
|
||||||
});
|
|
||||||
|
|
||||||
const EngineName = Object.freeze({
|
|
||||||
AMAYA : 'Amaya',
|
|
||||||
BLINK : 'Blink',
|
|
||||||
EDGEHTML: 'EdgeHTML',
|
|
||||||
FLOW : 'Flow',
|
|
||||||
GECKO : 'Gecko',
|
|
||||||
GOANNA : 'Goanna',
|
|
||||||
ICAB : 'iCab',
|
|
||||||
LIBWEB : 'LibWeb',
|
|
||||||
KHTML : 'KHTML',
|
|
||||||
LINKS : 'Links',
|
|
||||||
LYNX : 'Lynx',
|
|
||||||
NETFRONT: 'NetFront',
|
|
||||||
NETSURF : 'NetSurf',
|
|
||||||
PRESTO : 'Presto',
|
|
||||||
TASMAN : 'Tasman',
|
|
||||||
TRIDENT : 'Trident',
|
|
||||||
W3M : 'w3m',
|
|
||||||
WEBKIT : 'WebKit'
|
|
||||||
});
|
|
||||||
|
|
||||||
const OSName = Object.freeze({
|
|
||||||
WINDOWS : 'Windows',
|
|
||||||
LINUX : 'Linux',
|
|
||||||
MACOS : 'macOS',
|
|
||||||
IOS : 'iOS',
|
|
||||||
ANDROID : 'Android'
|
|
||||||
|
|
||||||
// TODO : test!
|
|
||||||
});
|
|
||||||
|
|
||||||
export {
|
|
||||||
BrowserName,
|
|
||||||
CPUArch,
|
|
||||||
DeviceType,
|
|
||||||
DeviceVendor,
|
|
||||||
EngineName,
|
|
||||||
OSName
|
|
||||||
}
|
|
||||||
@@ -1,120 +0,0 @@
|
|||||||
///////////////////////////////////////////////
|
|
||||||
/* Extensions for UAParser.js v2.0.0-alpha.2
|
|
||||||
https://github.com/faisalman/ua-parser-js
|
|
||||||
Author: Faisal Salman <f@faisalman.com>
|
|
||||||
MIT License */
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
|
|
||||||
const MODEL = 'model';
|
|
||||||
const NAME = 'name';
|
|
||||||
const TYPE = 'type';
|
|
||||||
const VENDOR = 'vendor';
|
|
||||||
const VERSION = 'version';
|
|
||||||
const MOBILE = 'mobile';
|
|
||||||
const TABLET = 'tablet';
|
|
||||||
|
|
||||||
const Bots = Object.freeze({
|
|
||||||
browser : [
|
|
||||||
// Googlebot / BingBot / MSNBot / FacebookBot
|
|
||||||
[/((?:google|bing|msn|facebook)bot(?:\-[imagevdo]{5})?|bingpreview)\/([\w\.]+)/i], [NAME, VERSION, [TYPE, 'bot']]
|
|
||||||
]
|
|
||||||
});
|
|
||||||
|
|
||||||
const ExtraDevices = Object.freeze({
|
|
||||||
device : [
|
|
||||||
[
|
|
||||||
/(nook)[\w ]+build\/(\w+)/i, // Nook
|
|
||||||
/(dell) (strea[kpr\d ]*[\dko])/i, // Dell Streak
|
|
||||||
/(le[- ]+pan)[- ]+(\w{1,9}) bui/i, // Le Pan Tablets
|
|
||||||
/(trinity)[- ]*(t\d{3}) bui/i, // Trinity Tablets
|
|
||||||
/(gigaset)[- ]+(q\w{1,9}) bui/i, // Gigaset Tablets
|
|
||||||
/(vodafone) ([\w ]+)(?:\)| bui)/i // Vodafone
|
|
||||||
], [VENDOR, MODEL, [TYPE, TABLET]], [
|
|
||||||
|
|
||||||
/(u304aa)/i // AT&T
|
|
||||||
], [MODEL, [VENDOR, 'AT&T'], [TYPE, MOBILE]], [
|
|
||||||
|
|
||||||
/\bsie-(\w*)/i // Siemens
|
|
||||||
], [MODEL, [VENDOR, 'Siemens'], [TYPE, MOBILE]], [
|
|
||||||
|
|
||||||
/\b(rct\w+) b/i // RCA Tablets
|
|
||||||
], [MODEL, [VENDOR, 'RCA'], [TYPE, TABLET]], [
|
|
||||||
|
|
||||||
/\b(venue[\d ]{2,7}) b/i // Dell Venue Tablets
|
|
||||||
], [MODEL, [VENDOR, 'Dell'], [TYPE, TABLET]], [
|
|
||||||
|
|
||||||
/\b(q(?:mv|ta)\w+) b/i // Verizon Tablet
|
|
||||||
], [MODEL, [VENDOR, 'Verizon'], [TYPE, TABLET]], [
|
|
||||||
|
|
||||||
/\b(?:barnes[& ]+noble |bn[rt])([\w\+ ]*) b/i // Barnes & Noble Tablet
|
|
||||||
], [MODEL, [VENDOR, 'Barnes & Noble'], [TYPE, TABLET]], [
|
|
||||||
|
|
||||||
/\b(tm\d{3}\w+) b/i
|
|
||||||
], [MODEL, [VENDOR, 'NuVision'], [TYPE, TABLET]], [
|
|
||||||
|
|
||||||
/\b(k88) b/i // ZTE K Series Tablet
|
|
||||||
], [MODEL, [VENDOR, 'ZTE'], [TYPE, TABLET]], [
|
|
||||||
|
|
||||||
/\b(nx\d{3}j) b/i // ZTE Nubia
|
|
||||||
], [MODEL, [VENDOR, 'ZTE'], [TYPE, MOBILE]], [
|
|
||||||
|
|
||||||
/\b(gen\d{3}) b.+49h/i // Swiss GEN Mobile
|
|
||||||
], [MODEL, [VENDOR, 'Swiss'], [TYPE, MOBILE]], [
|
|
||||||
|
|
||||||
/\b(zur\d{3}) b/i // Swiss ZUR Tablet
|
|
||||||
], [MODEL, [VENDOR, 'Swiss'], [TYPE, TABLET]], [
|
|
||||||
|
|
||||||
/\b((zeki)?tb.*\b) b/i // Zeki Tablets
|
|
||||||
], [MODEL, [VENDOR, 'Zeki'], [TYPE, TABLET]], [
|
|
||||||
|
|
||||||
/\b([yr]\d{2}) b/i,
|
|
||||||
/\b(?:dragon[- ]+touch |dt)(\w{5}) b/i // Dragon Touch Tablet
|
|
||||||
], [MODEL, [VENDOR, 'Dragon Touch'], [TYPE, TABLET]], [
|
|
||||||
|
|
||||||
/\b(ns-?\w{0,9}) b/i // Insignia Tablets
|
|
||||||
], [MODEL, [VENDOR, 'Insignia'], [TYPE, TABLET]], [
|
|
||||||
|
|
||||||
/\b((nxa|next)-?\w{0,9}) b/i // NextBook Tablets
|
|
||||||
], [MODEL, [VENDOR, 'NextBook'], [TYPE, TABLET]], [
|
|
||||||
|
|
||||||
/\b(xtreme\_)?(v(1[045]|2[015]|[3469]0|7[05])) b/i // Voice Xtreme Phones
|
|
||||||
], [[VENDOR, 'Voice'], MODEL, [TYPE, MOBILE]], [
|
|
||||||
|
|
||||||
/\b(lvtel\-)?(v1[12]) b/i // LvTel Phones
|
|
||||||
], [[VENDOR, 'LvTel'], MODEL, [TYPE, MOBILE]], [
|
|
||||||
|
|
||||||
/\b(ph-1) /i // Essential PH-1
|
|
||||||
], [MODEL, [VENDOR, 'Essential'], [TYPE, MOBILE]], [
|
|
||||||
|
|
||||||
/\b(v(100md|700na|7011|917g).*\b) b/i // Envizen Tablets
|
|
||||||
], [MODEL, [VENDOR, 'Envizen'], [TYPE, TABLET]], [
|
|
||||||
|
|
||||||
/\b(trio[-\w\. ]+) b/i // MachSpeed Tablets
|
|
||||||
], [MODEL, [VENDOR, 'MachSpeed'], [TYPE, TABLET]], [
|
|
||||||
|
|
||||||
/\btu_(1491) b/i // Rotor Tablets
|
|
||||||
], [MODEL, [VENDOR, 'Rotor'], [TYPE, TABLET]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
});
|
|
||||||
|
|
||||||
const Emails = Object.freeze({
|
|
||||||
browser : [
|
|
||||||
// Microsoft Outlook / Thunderbird
|
|
||||||
[/(microsoft outlook|thunderbird)[\s\/]([\w\.]+)/i], [NAME, VERSION, [TYPE, 'email']]
|
|
||||||
]
|
|
||||||
});
|
|
||||||
|
|
||||||
const Tools = Object.freeze({
|
|
||||||
browser : [
|
|
||||||
// wget / curl / lynx
|
|
||||||
[/(wget|curl|lynx)\/([\w\.]+)/i], [NAME, VERSION, [TYPE, 'tool']]
|
|
||||||
]
|
|
||||||
});
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
Bots,
|
|
||||||
ExtraDevices,
|
|
||||||
Emails,
|
|
||||||
Tools
|
|
||||||
}
|
|
||||||
@@ -1,124 +0,0 @@
|
|||||||
// Generated ESM version of UAParser.js extensions
|
|
||||||
// DO NOT EDIT THIS FILE!
|
|
||||||
// Source: /src/extension/ua-parser-extension.js
|
|
||||||
|
|
||||||
///////////////////////////////////////////////
|
|
||||||
/* Extensions for UAParser.js v2.0.0-alpha.2
|
|
||||||
https://github.com/faisalman/ua-parser-js
|
|
||||||
Author: Faisal Salman <f@faisalman.com>
|
|
||||||
MIT License */
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
|
|
||||||
const MODEL = 'model';
|
|
||||||
const NAME = 'name';
|
|
||||||
const TYPE = 'type';
|
|
||||||
const VENDOR = 'vendor';
|
|
||||||
const VERSION = 'version';
|
|
||||||
const MOBILE = 'mobile';
|
|
||||||
const TABLET = 'tablet';
|
|
||||||
|
|
||||||
const Bots = Object.freeze({
|
|
||||||
browser : [
|
|
||||||
// Googlebot / BingBot / MSNBot / FacebookBot
|
|
||||||
[/((?:google|bing|msn|facebook)bot(?:\-[imagevdo]{5})?|bingpreview)\/([\w\.]+)/i], [NAME, VERSION, [TYPE, 'bot']]
|
|
||||||
]
|
|
||||||
});
|
|
||||||
|
|
||||||
const ExtraDevices = Object.freeze({
|
|
||||||
device : [
|
|
||||||
[
|
|
||||||
/(nook)[\w ]+build\/(\w+)/i, // Nook
|
|
||||||
/(dell) (strea[kpr\d ]*[\dko])/i, // Dell Streak
|
|
||||||
/(le[- ]+pan)[- ]+(\w{1,9}) bui/i, // Le Pan Tablets
|
|
||||||
/(trinity)[- ]*(t\d{3}) bui/i, // Trinity Tablets
|
|
||||||
/(gigaset)[- ]+(q\w{1,9}) bui/i, // Gigaset Tablets
|
|
||||||
/(vodafone) ([\w ]+)(?:\)| bui)/i // Vodafone
|
|
||||||
], [VENDOR, MODEL, [TYPE, TABLET]], [
|
|
||||||
|
|
||||||
/(u304aa)/i // AT&T
|
|
||||||
], [MODEL, [VENDOR, 'AT&T'], [TYPE, MOBILE]], [
|
|
||||||
|
|
||||||
/\bsie-(\w*)/i // Siemens
|
|
||||||
], [MODEL, [VENDOR, 'Siemens'], [TYPE, MOBILE]], [
|
|
||||||
|
|
||||||
/\b(rct\w+) b/i // RCA Tablets
|
|
||||||
], [MODEL, [VENDOR, 'RCA'], [TYPE, TABLET]], [
|
|
||||||
|
|
||||||
/\b(venue[\d ]{2,7}) b/i // Dell Venue Tablets
|
|
||||||
], [MODEL, [VENDOR, 'Dell'], [TYPE, TABLET]], [
|
|
||||||
|
|
||||||
/\b(q(?:mv|ta)\w+) b/i // Verizon Tablet
|
|
||||||
], [MODEL, [VENDOR, 'Verizon'], [TYPE, TABLET]], [
|
|
||||||
|
|
||||||
/\b(?:barnes[& ]+noble |bn[rt])([\w\+ ]*) b/i // Barnes & Noble Tablet
|
|
||||||
], [MODEL, [VENDOR, 'Barnes & Noble'], [TYPE, TABLET]], [
|
|
||||||
|
|
||||||
/\b(tm\d{3}\w+) b/i
|
|
||||||
], [MODEL, [VENDOR, 'NuVision'], [TYPE, TABLET]], [
|
|
||||||
|
|
||||||
/\b(k88) b/i // ZTE K Series Tablet
|
|
||||||
], [MODEL, [VENDOR, 'ZTE'], [TYPE, TABLET]], [
|
|
||||||
|
|
||||||
/\b(nx\d{3}j) b/i // ZTE Nubia
|
|
||||||
], [MODEL, [VENDOR, 'ZTE'], [TYPE, MOBILE]], [
|
|
||||||
|
|
||||||
/\b(gen\d{3}) b.+49h/i // Swiss GEN Mobile
|
|
||||||
], [MODEL, [VENDOR, 'Swiss'], [TYPE, MOBILE]], [
|
|
||||||
|
|
||||||
/\b(zur\d{3}) b/i // Swiss ZUR Tablet
|
|
||||||
], [MODEL, [VENDOR, 'Swiss'], [TYPE, TABLET]], [
|
|
||||||
|
|
||||||
/\b((zeki)?tb.*\b) b/i // Zeki Tablets
|
|
||||||
], [MODEL, [VENDOR, 'Zeki'], [TYPE, TABLET]], [
|
|
||||||
|
|
||||||
/\b([yr]\d{2}) b/i,
|
|
||||||
/\b(?:dragon[- ]+touch |dt)(\w{5}) b/i // Dragon Touch Tablet
|
|
||||||
], [MODEL, [VENDOR, 'Dragon Touch'], [TYPE, TABLET]], [
|
|
||||||
|
|
||||||
/\b(ns-?\w{0,9}) b/i // Insignia Tablets
|
|
||||||
], [MODEL, [VENDOR, 'Insignia'], [TYPE, TABLET]], [
|
|
||||||
|
|
||||||
/\b((nxa|next)-?\w{0,9}) b/i // NextBook Tablets
|
|
||||||
], [MODEL, [VENDOR, 'NextBook'], [TYPE, TABLET]], [
|
|
||||||
|
|
||||||
/\b(xtreme\_)?(v(1[045]|2[015]|[3469]0|7[05])) b/i // Voice Xtreme Phones
|
|
||||||
], [[VENDOR, 'Voice'], MODEL, [TYPE, MOBILE]], [
|
|
||||||
|
|
||||||
/\b(lvtel\-)?(v1[12]) b/i // LvTel Phones
|
|
||||||
], [[VENDOR, 'LvTel'], MODEL, [TYPE, MOBILE]], [
|
|
||||||
|
|
||||||
/\b(ph-1) /i // Essential PH-1
|
|
||||||
], [MODEL, [VENDOR, 'Essential'], [TYPE, MOBILE]], [
|
|
||||||
|
|
||||||
/\b(v(100md|700na|7011|917g).*\b) b/i // Envizen Tablets
|
|
||||||
], [MODEL, [VENDOR, 'Envizen'], [TYPE, TABLET]], [
|
|
||||||
|
|
||||||
/\b(trio[-\w\. ]+) b/i // MachSpeed Tablets
|
|
||||||
], [MODEL, [VENDOR, 'MachSpeed'], [TYPE, TABLET]], [
|
|
||||||
|
|
||||||
/\btu_(1491) b/i // Rotor Tablets
|
|
||||||
], [MODEL, [VENDOR, 'Rotor'], [TYPE, TABLET]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
});
|
|
||||||
|
|
||||||
const Emails = Object.freeze({
|
|
||||||
browser : [
|
|
||||||
// Microsoft Outlook / Thunderbird
|
|
||||||
[/(microsoft outlook|thunderbird)[\s\/]([\w\.]+)/i], [NAME, VERSION, [TYPE, 'email']]
|
|
||||||
]
|
|
||||||
});
|
|
||||||
|
|
||||||
const Tools = Object.freeze({
|
|
||||||
browser : [
|
|
||||||
// wget / curl / lynx
|
|
||||||
[/(wget|curl|lynx)\/([\w\.]+)/i], [NAME, VERSION, [TYPE, 'tool']]
|
|
||||||
]
|
|
||||||
});
|
|
||||||
|
|
||||||
export {
|
|
||||||
Bots,
|
|
||||||
ExtraDevices,
|
|
||||||
Emails,
|
|
||||||
Tools
|
|
||||||
}
|
|
||||||
636
src/ua-parser.js
636
src/ua-parser.js
@@ -1,6 +1,6 @@
|
|||||||
/////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
/* UAParser.js v2.0.0-alpha.2
|
/* UAParser.js v0.7.34
|
||||||
Copyright © 2012-2023 Faisal Salman <f@faisalman.com>
|
Copyright © 2012-2021 Faisal Salman <f@faisalman.com>
|
||||||
MIT License *//*
|
MIT License *//*
|
||||||
Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data.
|
Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data.
|
||||||
Supports browser & node.js environment.
|
Supports browser & node.js environment.
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
/////////////
|
/////////////
|
||||||
|
|
||||||
|
|
||||||
var LIBVERSION = '2.0.0-alpha.2',
|
var LIBVERSION = '0.7.34',
|
||||||
EMPTY = '',
|
EMPTY = '',
|
||||||
UNKNOWN = '?',
|
UNKNOWN = '?',
|
||||||
FUNC_TYPE = 'function',
|
FUNC_TYPE = 'function',
|
||||||
@@ -37,77 +37,44 @@
|
|||||||
SMARTTV = 'smarttv',
|
SMARTTV = 'smarttv',
|
||||||
WEARABLE = 'wearable',
|
WEARABLE = 'wearable',
|
||||||
EMBEDDED = 'embedded',
|
EMBEDDED = 'embedded',
|
||||||
USER_AGENT = 'user-agent',
|
UA_MAX_LENGTH = 350;
|
||||||
UA_MAX_LENGTH = 350,
|
|
||||||
BRANDS = 'brands',
|
var AMAZON = 'Amazon',
|
||||||
FULLVERLIST = 'fullVersionList',
|
APPLE = 'Apple',
|
||||||
PLATFORM = 'platform',
|
ASUS = 'ASUS',
|
||||||
PLATFORMVER = 'platformVersion',
|
BLACKBERRY = 'BlackBerry',
|
||||||
BITNESS = 'bitness',
|
BROWSER = 'Browser',
|
||||||
CH_HEADER = 'sec-ch-ua',
|
CHROME = 'Chrome',
|
||||||
CH_HEADER_FULL_VER_LIST = CH_HEADER + '-full-version-list',
|
EDGE = 'Edge',
|
||||||
CH_HEADER_ARCH = CH_HEADER + '-arch',
|
FIREFOX = 'Firefox',
|
||||||
CH_HEADER_BITNESS = CH_HEADER + '-bitness',
|
GOOGLE = 'Google',
|
||||||
CH_HEADER_MOBILE = CH_HEADER + '-mobile',
|
HUAWEI = 'Huawei',
|
||||||
CH_HEADER_MODEL = CH_HEADER + '-model',
|
LG = 'LG',
|
||||||
CH_HEADER_PLATFORM = CH_HEADER + '-platform',
|
MICROSOFT = 'Microsoft',
|
||||||
CH_HEADER_PLATFORM_VER = CH_HEADER_PLATFORM + '-version',
|
MOTOROLA = 'Motorola',
|
||||||
CH_ALL_VALUES = ['brands', 'fullVersionList', MOBILE, MODEL, 'platform', 'platformVersion', ARCHITECTURE, 'bitness'],
|
OPERA = 'Opera',
|
||||||
UA_BROWSER = 'browser',
|
SAMSUNG = 'Samsung',
|
||||||
UA_CPU = 'cpu',
|
SHARP = 'Sharp',
|
||||||
UA_DEVICE = 'device',
|
SONY = 'Sony',
|
||||||
UA_ENGINE = 'engine',
|
VIERA = 'Viera',
|
||||||
UA_OS = 'os',
|
XIAOMI = 'Xiaomi',
|
||||||
UA_RESULT = 'result',
|
ZEBRA = 'Zebra',
|
||||||
AMAZON = 'Amazon',
|
|
||||||
APPLE = 'Apple',
|
|
||||||
ASUS = 'ASUS',
|
|
||||||
BLACKBERRY = 'BlackBerry',
|
|
||||||
GOOGLE = 'Google',
|
|
||||||
HUAWEI = 'Huawei',
|
|
||||||
LG = 'LG',
|
|
||||||
MICROSOFT = 'Microsoft',
|
|
||||||
MOTOROLA = 'Motorola',
|
|
||||||
SAMSUNG = 'Samsung',
|
|
||||||
SHARP = 'Sharp',
|
|
||||||
SONY = 'Sony',
|
|
||||||
XIAOMI = 'Xiaomi',
|
|
||||||
ZEBRA = 'Zebra',
|
|
||||||
PREFIX_MOBILE = 'Mobile ',
|
|
||||||
SUFFIX_BROWSER = ' Browser',
|
|
||||||
CHROME = 'Chrome',
|
|
||||||
EDGE = 'Edge',
|
|
||||||
FIREFOX = 'Firefox',
|
|
||||||
OPERA = 'Opera',
|
|
||||||
FACEBOOK = 'Facebook',
|
FACEBOOK = 'Facebook',
|
||||||
WINDOWS = 'Windows';
|
CHROMIUM_OS = 'Chromium OS',
|
||||||
|
MAC_OS = 'Mac OS';
|
||||||
var NAVIGATOR = (typeof window !== UNDEF_TYPE && window.navigator) ?
|
|
||||||
window.navigator :
|
|
||||||
undefined,
|
|
||||||
NAVIGATOR_UADATA = (NAVIGATOR && NAVIGATOR.userAgentData) ?
|
|
||||||
NAVIGATOR.userAgentData :
|
|
||||||
undefined;
|
|
||||||
|
|
||||||
///////////
|
///////////
|
||||||
// Helper
|
// Helper
|
||||||
//////////
|
//////////
|
||||||
|
|
||||||
var assignFromEntries = function (arr) {
|
var extend = function (regexes, extensions) {
|
||||||
for (var i in arr) {
|
|
||||||
var propName = arr[i];
|
|
||||||
if (typeof propName == OBJ_TYPE && propName.length == 2) {
|
|
||||||
this[propName[0]] = propName[1];
|
|
||||||
} else {
|
|
||||||
this[propName] = undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
},
|
|
||||||
extend = function (regexes, extensions) {
|
|
||||||
var mergedRegexes = {};
|
var mergedRegexes = {};
|
||||||
for (var i in regexes) {
|
for (var i in regexes) {
|
||||||
mergedRegexes[i] = extensions[i] && extensions[i].length % 2 === 0 ? extensions[i].concat(regexes[i]) : regexes[i];
|
if (extensions[i] && extensions[i].length % 2 === 0) {
|
||||||
|
mergedRegexes[i] = extensions[i].concat(regexes[i]);
|
||||||
|
} else {
|
||||||
|
mergedRegexes[i] = regexes[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return mergedRegexes;
|
return mergedRegexes;
|
||||||
},
|
},
|
||||||
@@ -119,44 +86,17 @@
|
|||||||
return enums;
|
return enums;
|
||||||
},
|
},
|
||||||
has = function (str1, str2) {
|
has = function (str1, str2) {
|
||||||
if (typeof str1 === OBJ_TYPE && str1.length > 0) {
|
|
||||||
for (var i in str1) {
|
|
||||||
if (lowerize(str1[i]) == lowerize(str2)) return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return typeof str1 === STR_TYPE ? lowerize(str2).indexOf(lowerize(str1)) !== -1 : false;
|
return typeof str1 === STR_TYPE ? lowerize(str2).indexOf(lowerize(str1)) !== -1 : false;
|
||||||
},
|
},
|
||||||
isExtensions = function (obj) {
|
|
||||||
for (var prop in obj) {
|
|
||||||
return /^(browser|cpu|device|engine|os)$/.test(prop);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
itemListToArray = function (header) {
|
|
||||||
if (!header) return undefined;
|
|
||||||
var arr = [];
|
|
||||||
var tokens = strip(/\\?\"/g, header).split(', ');
|
|
||||||
for (var i = 0; i < tokens.length; i++) {
|
|
||||||
var token = tokens[i].split(';v=');
|
|
||||||
arr[i] = { brand : token[0], version : token[1] };
|
|
||||||
}
|
|
||||||
return arr;
|
|
||||||
},
|
|
||||||
lowerize = function (str) {
|
lowerize = function (str) {
|
||||||
return typeof(str) === STR_TYPE ? str.toLowerCase() : str;
|
return str.toLowerCase();
|
||||||
},
|
},
|
||||||
majorize = function (version) {
|
majorize = function (version) {
|
||||||
return typeof(version) === STR_TYPE ? strip(/[^\d\.]/g, version).split('.')[0] : undefined;
|
return typeof(version) === STR_TYPE ? version.replace(/[^\d\.]/g, EMPTY).split('.')[0] : undefined;
|
||||||
},
|
|
||||||
strip = function (pattern, str) {
|
|
||||||
return str.replace(pattern, EMPTY);
|
|
||||||
},
|
|
||||||
stripQuotes = function (val) {
|
|
||||||
return typeof val === STR_TYPE ? strip(/\"/g, val) : val;
|
|
||||||
},
|
},
|
||||||
trim = function (str, len) {
|
trim = function (str, len) {
|
||||||
if (typeof(str) === STR_TYPE) {
|
if (typeof(str) === STR_TYPE) {
|
||||||
str = strip(/^\s\s*/, str);
|
str = str.replace(/^\s\s*/, EMPTY);
|
||||||
return typeof(len) === UNDEF_TYPE ? str : str.substring(0, UA_MAX_LENGTH);
|
return typeof(len) === UNDEF_TYPE ? str : str.substring(0, UA_MAX_LENGTH);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -167,8 +107,6 @@
|
|||||||
|
|
||||||
var rgxMapper = function (ua, arrays) {
|
var rgxMapper = function (ua, arrays) {
|
||||||
|
|
||||||
if(!ua || !arrays) return;
|
|
||||||
|
|
||||||
var i = 0, j, k, p, q, matches, match;
|
var i = 0, j, k, p, q, matches, match;
|
||||||
|
|
||||||
// loop through all regexes maps
|
// loop through all regexes maps
|
||||||
@@ -270,13 +208,12 @@
|
|||||||
// Regex map
|
// Regex map
|
||||||
/////////////
|
/////////////
|
||||||
|
|
||||||
var defaultRegexes = {
|
var regexes = {
|
||||||
|
|
||||||
browser : [[
|
browser : [[
|
||||||
|
|
||||||
// Most common regardless engine
|
|
||||||
/\b(?:crmo|crios)\/([\w\.]+)/i // Chrome for Android/iOS
|
/\b(?:crmo|crios)\/([\w\.]+)/i // Chrome for Android/iOS
|
||||||
], [VERSION, [NAME, PREFIX_MOBILE + 'Chrome']], [
|
], [VERSION, [NAME, 'Chrome']], [
|
||||||
/edg(?:e|ios|a)?\/([\w\.]+)/i // Microsoft Edge
|
/edg(?:e|ios|a)?\/([\w\.]+)/i // Microsoft Edge
|
||||||
], [VERSION, [NAME, 'Edge']], [
|
], [VERSION, [NAME, 'Edge']], [
|
||||||
|
|
||||||
@@ -300,12 +237,11 @@
|
|||||||
|
|
||||||
// Webkit/KHTML based // Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS/Bowser/QupZilla/Falkon
|
// Webkit/KHTML based // Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS/Bowser/QupZilla/Falkon
|
||||||
/(flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi|iridium|phantomjs|bowser|quark|qupzilla|falkon|rekonq|puffin|brave|whale(?!.+naver)|qqbrowserlite|qq|duckduckgo)\/([-\w\.]+)/i,
|
/(flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi|iridium|phantomjs|bowser|quark|qupzilla|falkon|rekonq|puffin|brave|whale(?!.+naver)|qqbrowserlite|qq|duckduckgo)\/([-\w\.]+)/i,
|
||||||
// Rekonq/Puffin/Brave/Whale/QQBrowserLite/QQ//Vivaldi/DuckDuckGo
|
// Rekonq/Puffin/Brave/Whale/QQBrowserLite/QQ, aka ShouQ
|
||||||
/(heytap|ovi)browser\/([\d\.]+)/i, // HeyTap/Ovi
|
|
||||||
/(weibo)__([\d\.]+)/i // Weibo
|
/(weibo)__([\d\.]+)/i // Weibo
|
||||||
], [NAME, VERSION], [
|
], [NAME, VERSION], [
|
||||||
/(?:\buc? ?browser|(?:juc.+)ucweb)[\/ ]?([\w\.]+)/i // UCBrowser
|
/(?:\buc? ?browser|(?:juc.+)ucweb)[\/ ]?([\w\.]+)/i // UCBrowser
|
||||||
], [VERSION, [NAME, 'UCBrowser']], [
|
], [VERSION, [NAME, 'UC'+BROWSER]], [
|
||||||
/microm.+\bqbcore\/([\w\.]+)/i, // WeChat Desktop for Windows Built-in Browser
|
/microm.+\bqbcore\/([\w\.]+)/i, // WeChat Desktop for Windows Built-in Browser
|
||||||
/\bqbcore\/([\w\.]+).+microm/i
|
/\bqbcore\/([\w\.]+).+microm/i
|
||||||
], [VERSION, [NAME, 'WeChat(Win) Desktop']], [
|
], [VERSION, [NAME, 'WeChat(Win) Desktop']], [
|
||||||
@@ -315,10 +251,10 @@
|
|||||||
], [VERSION, [NAME, 'Konqueror']], [
|
], [VERSION, [NAME, 'Konqueror']], [
|
||||||
/trident.+rv[: ]([\w\.]{1,9})\b.+like gecko/i // IE11
|
/trident.+rv[: ]([\w\.]{1,9})\b.+like gecko/i // IE11
|
||||||
], [VERSION, [NAME, 'IE']], [
|
], [VERSION, [NAME, 'IE']], [
|
||||||
/ya(?:search)?browser\/([\w\.]+)/i // Yandex
|
/yabrowser\/([\w\.]+)/i // Yandex
|
||||||
], [VERSION, [NAME, 'Yandex']], [
|
], [VERSION, [NAME, 'Yandex']], [
|
||||||
/(avast|avg)\/([\w\.]+)/i // Avast/AVG Secure Browser
|
/(avast|avg)\/([\w\.]+)/i // Avast/AVG Secure Browser
|
||||||
], [[NAME, /(.+)/, '$1 Secure' + SUFFIX_BROWSER], VERSION], [
|
], [[NAME, /(.+)/, '$1 Secure '+BROWSER], VERSION], [
|
||||||
/\bfocus\/([\w\.]+)/i // Firefox Focus
|
/\bfocus\/([\w\.]+)/i // Firefox Focus
|
||||||
], [VERSION, [NAME, FIREFOX+' Focus']], [
|
], [VERSION, [NAME, FIREFOX+' Focus']], [
|
||||||
/\bopt\/([\w\.]+)/i // Opera Touch
|
/\bopt\/([\w\.]+)/i // Opera Touch
|
||||||
@@ -330,13 +266,13 @@
|
|||||||
/coast\/([\w\.]+)/i // Opera Coast
|
/coast\/([\w\.]+)/i // Opera Coast
|
||||||
], [VERSION, [NAME, OPERA+' Coast']], [
|
], [VERSION, [NAME, OPERA+' Coast']], [
|
||||||
/miuibrowser\/([\w\.]+)/i // MIUI Browser
|
/miuibrowser\/([\w\.]+)/i // MIUI Browser
|
||||||
], [VERSION, [NAME, 'MIUI' + SUFFIX_BROWSER]], [
|
], [VERSION, [NAME, 'MIUI '+BROWSER]], [
|
||||||
/fxios\/([\w\.-]+)/i // Firefox for iOS
|
/fxios\/([-\w\.]+)/i // Firefox for iOS
|
||||||
], [VERSION, [NAME, PREFIX_MOBILE + FIREFOX]], [
|
], [VERSION, [NAME, FIREFOX]], [
|
||||||
/\bqihu|(qi?ho?o?|360)browser/i // 360
|
/\bqihu|(qi?ho?o?|360)browser/i // 360
|
||||||
], [[NAME, '360' + SUFFIX_BROWSER]], [
|
], [[NAME, '360 '+BROWSER]], [
|
||||||
/(oculus|samsung|sailfish|huawei)browser\/([\w\.]+)/i
|
/(oculus|samsung|sailfish|huawei)browser\/([\w\.]+)/i
|
||||||
], [[NAME, /(.+)/, '$1' + SUFFIX_BROWSER], VERSION], [ // Oculus/Samsung/Sailfish/Huawei Browser
|
], [[NAME, /(.+)/, '$1 '+BROWSER], VERSION], [ // Oculus/Samsung/Sailfish/Huawei Browser
|
||||||
/(comodo_dragon)\/([\w\.]+)/i // Comodo Dragon
|
/(comodo_dragon)\/([\w\.]+)/i // Comodo Dragon
|
||||||
], [[NAME, /_/g, ' '], VERSION], [
|
], [[NAME, /_/g, ' '], VERSION], [
|
||||||
/(electron)\/([\w\.]+) safari/i, // Electron-based App
|
/(electron)\/([\w\.]+) safari/i, // Electron-based App
|
||||||
@@ -359,8 +295,6 @@
|
|||||||
], [NAME, VERSION], [
|
], [NAME, VERSION], [
|
||||||
/\bgsa\/([\w\.]+) .*safari\//i // Google Search Appliance on iOS
|
/\bgsa\/([\w\.]+) .*safari\//i // Google Search Appliance on iOS
|
||||||
], [VERSION, [NAME, 'GSA']], [
|
], [VERSION, [NAME, 'GSA']], [
|
||||||
/musical_ly(?:.+app_?version\/|_)([\w\.]+)/i // TikTok
|
|
||||||
], [VERSION, [NAME, 'TikTok']], [
|
|
||||||
|
|
||||||
/headlesschrome(?:\/([\w\.]+)| )/i // Chrome Headless
|
/headlesschrome(?:\/([\w\.]+)| )/i // Chrome Headless
|
||||||
], [VERSION, [NAME, CHROME+' Headless']], [
|
], [VERSION, [NAME, CHROME+' Headless']], [
|
||||||
@@ -369,19 +303,14 @@
|
|||||||
], [[NAME, CHROME+' WebView'], VERSION], [
|
], [[NAME, CHROME+' WebView'], VERSION], [
|
||||||
|
|
||||||
/droid.+ version\/([\w\.]+)\b.+(?:mobile safari|safari)/i // Android Browser
|
/droid.+ version\/([\w\.]+)\b.+(?:mobile safari|safari)/i // Android Browser
|
||||||
], [VERSION, [NAME, 'Android' + SUFFIX_BROWSER]], [
|
], [VERSION, [NAME, 'Android '+BROWSER]], [
|
||||||
|
|
||||||
/chrome\/([\w\.]+) mobile/i // Chrome Mobile
|
|
||||||
], [VERSION, [NAME, PREFIX_MOBILE + 'Chrome']], [
|
|
||||||
|
|
||||||
/(chrome|omniweb|arora|[tizenoka]{5} ?browser)\/v?([\w\.]+)/i // Chrome/OmniWeb/Arora/Tizen/Nokia
|
/(chrome|omniweb|arora|[tizenoka]{5} ?browser)\/v?([\w\.]+)/i // Chrome/OmniWeb/Arora/Tizen/Nokia
|
||||||
], [NAME, VERSION], [
|
], [NAME, VERSION], [
|
||||||
|
|
||||||
/version\/([\w\.\,]+) .*mobile(?:\/\w+ | ?)safari/i // Safari Mobile
|
/version\/([\w\.\,]+) .*mobile\/\w+ (safari)/i // Mobile Safari
|
||||||
], [VERSION, [NAME, PREFIX_MOBILE + 'Safari']], [
|
], [VERSION, [NAME, 'Mobile Safari']], [
|
||||||
/iphone .*mobile(?:\/\w+ | ?)safari/i
|
/version\/([\w(\.|\,)]+) .*(mobile ?safari|safari)/i // Safari & Safari Mobile
|
||||||
], [[NAME, PREFIX_MOBILE + 'Safari']], [
|
|
||||||
/version\/([\w\.\,]+) .*(safari)/i // Safari
|
|
||||||
], [VERSION, NAME], [
|
], [VERSION, NAME], [
|
||||||
/webkit.+?(mobile ?safari|safari)(\/[\w\.]+)/i // Safari < 3.0
|
/webkit.+?(mobile ?safari|safari)(\/[\w\.]+)/i // Safari < 3.0
|
||||||
], [NAME, [VERSION, strMapper, oldSafariMap]], [
|
], [NAME, [VERSION, strMapper, oldSafariMap]], [
|
||||||
@@ -390,8 +319,6 @@
|
|||||||
], [NAME, VERSION], [
|
], [NAME, VERSION], [
|
||||||
|
|
||||||
// Gecko based
|
// Gecko based
|
||||||
/(?:mobile|tablet);.*(firefox)\/([\w\.-]+)/i // Firefox Mobile
|
|
||||||
], [[NAME, PREFIX_MOBILE + FIREFOX], VERSION], [
|
|
||||||
/(navigator|netscape\d?)\/([-\w\.]+)/i // Netscape
|
/(navigator|netscape\d?)\/([-\w\.]+)/i // Netscape
|
||||||
], [[NAME, 'Netscape'], VERSION], [
|
], [[NAME, 'Netscape'], VERSION], [
|
||||||
/mobile vr; rv:([\w\.]+)\).+firefox/i // Firefox Reality
|
/mobile vr; rv:([\w\.]+)\).+firefox/i // Firefox Reality
|
||||||
@@ -413,15 +340,17 @@
|
|||||||
], [NAME, VERSION], [
|
], [NAME, VERSION], [
|
||||||
|
|
||||||
/(cobalt)\/([\w\.]+)/i // Cobalt
|
/(cobalt)\/([\w\.]+)/i // Cobalt
|
||||||
], [NAME, [VERSION, /[^\d\.]+./, EMPTY]]
|
], [NAME, [VERSION, /master.|lts./, ""]]
|
||||||
],
|
],
|
||||||
|
|
||||||
cpu : [[
|
cpu : [[
|
||||||
|
|
||||||
/\b(?:(amd|x|x86[-_]?|wow|win)64)\b/i // AMD64 (x64)
|
/(?:(amd|x(?:(?:86|64)[-_])?|wow|win)64)[;\)]/i // AMD64 (x64)
|
||||||
], [[ARCHITECTURE, 'amd64']], [
|
], [[ARCHITECTURE, 'amd64']], [
|
||||||
|
|
||||||
/(ia32(?=;))/i, // IA32 (quicktime)
|
/(ia32(?=;))/i // IA32 (quicktime)
|
||||||
|
], [[ARCHITECTURE, lowerize]], [
|
||||||
|
|
||||||
/((?:i[346]|x)86)[;\)]/i // IA32 (x86)
|
/((?:i[346]|x)86)[;\)]/i // IA32 (x86)
|
||||||
], [[ARCHITECTURE, 'ia32']], [
|
], [[ARCHITECTURE, 'ia32']], [
|
||||||
|
|
||||||
@@ -461,7 +390,7 @@
|
|||||||
], [MODEL, [VENDOR, SAMSUNG], [TYPE, MOBILE]], [
|
], [MODEL, [VENDOR, SAMSUNG], [TYPE, MOBILE]], [
|
||||||
|
|
||||||
// Apple
|
// Apple
|
||||||
/(?:\/|\()(ip(?:hone|od)[\w, ]*)(?:\/|;)/i // iPod/iPhone
|
/\((ip(?:hone|od)[\w ]*);/i // iPod/iPhone
|
||||||
], [MODEL, [VENDOR, APPLE], [TYPE, MOBILE]], [
|
], [MODEL, [VENDOR, APPLE], [TYPE, MOBILE]], [
|
||||||
/\((ipad);[-\w\),; ]+apple/i, // iPad
|
/\((ipad);[-\w\),; ]+apple/i, // iPad
|
||||||
/applecoremedia\/[\w\.]+ \((ipad)/i,
|
/applecoremedia\/[\w\.]+ \((ipad)/i,
|
||||||
@@ -551,7 +480,7 @@
|
|||||||
|
|
||||||
// Amazon
|
// Amazon
|
||||||
/(alexa)webm/i,
|
/(alexa)webm/i,
|
||||||
/(kf[a-z]{2}wi|aeo[c-r]{2})( bui|\))/i, // Kindle Fire without Silk / Echo Show
|
/(kf[a-z]{2}wi)( bui|\))/i, // Kindle Fire without Silk
|
||||||
/(kf[a-z]+)( bui|\)).+silk\//i // Kindle Fire HD
|
/(kf[a-z]+)( bui|\)).+silk\//i // Kindle Fire HD
|
||||||
], [MODEL, [VENDOR, AMAZON], [TYPE, TABLET]], [
|
], [MODEL, [VENDOR, AMAZON], [TYPE, TABLET]], [
|
||||||
/((?:sd|kf)[0349hijorstuw]+)( bui|\)).+silk\//i // Fire Phone
|
/((?:sd|kf)[0349hijorstuw]+)( bui|\)).+silk\//i // Fire Phone
|
||||||
@@ -603,20 +532,69 @@
|
|||||||
/(kobo)\s(ereader|touch)/i, // Kobo
|
/(kobo)\s(ereader|touch)/i, // Kobo
|
||||||
/(archos) (gamepad2?)/i, // Archos
|
/(archos) (gamepad2?)/i, // Archos
|
||||||
/(hp).+(touchpad(?!.+tablet)|tablet)/i, // HP TouchPad
|
/(hp).+(touchpad(?!.+tablet)|tablet)/i, // HP TouchPad
|
||||||
/(kindle)\/([\w\.]+)/i // Kindle
|
/(kindle)\/([\w\.]+)/i, // Kindle
|
||||||
|
/(nook)[\w ]+build\/(\w+)/i, // Nook
|
||||||
|
/(dell) (strea[kpr\d ]*[\dko])/i, // Dell Streak
|
||||||
|
/(le[- ]+pan)[- ]+(\w{1,9}) bui/i, // Le Pan Tablets
|
||||||
|
/(trinity)[- ]*(t\d{3}) bui/i, // Trinity Tablets
|
||||||
|
/(gigaset)[- ]+(q\w{1,9}) bui/i, // Gigaset Tablets
|
||||||
|
/(vodafone) ([\w ]+)(?:\)| bui)/i // Vodafone
|
||||||
], [VENDOR, MODEL, [TYPE, TABLET]], [
|
], [VENDOR, MODEL, [TYPE, TABLET]], [
|
||||||
|
|
||||||
/(surface duo)/i // Surface Duo
|
/(surface duo)/i // Surface Duo
|
||||||
], [MODEL, [VENDOR, MICROSOFT], [TYPE, TABLET]], [
|
], [MODEL, [VENDOR, MICROSOFT], [TYPE, TABLET]], [
|
||||||
/droid [\d\.]+; (fp\du?)(?: b|\))/i // Fairphone
|
/droid [\d\.]+; (fp\du?)(?: b|\))/i // Fairphone
|
||||||
], [MODEL, [VENDOR, 'Fairphone'], [TYPE, MOBILE]], [
|
], [MODEL, [VENDOR, 'Fairphone'], [TYPE, MOBILE]], [
|
||||||
|
/(u304aa)/i // AT&T
|
||||||
|
], [MODEL, [VENDOR, 'AT&T'], [TYPE, MOBILE]], [
|
||||||
|
/\bsie-(\w*)/i // Siemens
|
||||||
|
], [MODEL, [VENDOR, 'Siemens'], [TYPE, MOBILE]], [
|
||||||
|
/\b(rct\w+) b/i // RCA Tablets
|
||||||
|
], [MODEL, [VENDOR, 'RCA'], [TYPE, TABLET]], [
|
||||||
|
/\b(venue[\d ]{2,7}) b/i // Dell Venue Tablets
|
||||||
|
], [MODEL, [VENDOR, 'Dell'], [TYPE, TABLET]], [
|
||||||
|
/\b(q(?:mv|ta)\w+) b/i // Verizon Tablet
|
||||||
|
], [MODEL, [VENDOR, 'Verizon'], [TYPE, TABLET]], [
|
||||||
|
/\b(?:barnes[& ]+noble |bn[rt])([\w\+ ]*) b/i // Barnes & Noble Tablet
|
||||||
|
], [MODEL, [VENDOR, 'Barnes & Noble'], [TYPE, TABLET]], [
|
||||||
|
/\b(tm\d{3}\w+) b/i
|
||||||
|
], [MODEL, [VENDOR, 'NuVision'], [TYPE, TABLET]], [
|
||||||
|
/\b(k88) b/i // ZTE K Series Tablet
|
||||||
|
], [MODEL, [VENDOR, 'ZTE'], [TYPE, TABLET]], [
|
||||||
|
/\b(nx\d{3}j) b/i // ZTE Nubia
|
||||||
|
], [MODEL, [VENDOR, 'ZTE'], [TYPE, MOBILE]], [
|
||||||
|
/\b(gen\d{3}) b.+49h/i // Swiss GEN Mobile
|
||||||
|
], [MODEL, [VENDOR, 'Swiss'], [TYPE, MOBILE]], [
|
||||||
|
/\b(zur\d{3}) b/i // Swiss ZUR Tablet
|
||||||
|
], [MODEL, [VENDOR, 'Swiss'], [TYPE, TABLET]], [
|
||||||
|
/\b((zeki)?tb.*\b) b/i // Zeki Tablets
|
||||||
|
], [MODEL, [VENDOR, 'Zeki'], [TYPE, TABLET]], [
|
||||||
|
/\b([yr]\d{2}) b/i,
|
||||||
|
/\b(dragon[- ]+touch |dt)(\w{5}) b/i // Dragon Touch Tablet
|
||||||
|
], [[VENDOR, 'Dragon Touch'], MODEL, [TYPE, TABLET]], [
|
||||||
|
/\b(ns-?\w{0,9}) b/i // Insignia Tablets
|
||||||
|
], [MODEL, [VENDOR, 'Insignia'], [TYPE, TABLET]], [
|
||||||
|
/\b((nxa|next)-?\w{0,9}) b/i // NextBook Tablets
|
||||||
|
], [MODEL, [VENDOR, 'NextBook'], [TYPE, TABLET]], [
|
||||||
|
/\b(xtreme\_)?(v(1[045]|2[015]|[3469]0|7[05])) b/i // Voice Xtreme Phones
|
||||||
|
], [[VENDOR, 'Voice'], MODEL, [TYPE, MOBILE]], [
|
||||||
|
/\b(lvtel\-)?(v1[12]) b/i // LvTel Phones
|
||||||
|
], [[VENDOR, 'LvTel'], MODEL, [TYPE, MOBILE]], [
|
||||||
|
/\b(ph-1) /i // Essential PH-1
|
||||||
|
], [MODEL, [VENDOR, 'Essential'], [TYPE, MOBILE]], [
|
||||||
|
/\b(v(100md|700na|7011|917g).*\b) b/i // Envizen Tablets
|
||||||
|
], [MODEL, [VENDOR, 'Envizen'], [TYPE, TABLET]], [
|
||||||
|
/\b(trio[-\w\. ]+) b/i // MachSpeed Tablets
|
||||||
|
], [MODEL, [VENDOR, 'MachSpeed'], [TYPE, TABLET]], [
|
||||||
|
/\btu_(1491) b/i // Rotor Tablets
|
||||||
|
], [MODEL, [VENDOR, 'Rotor'], [TYPE, TABLET]], [
|
||||||
/(shield[\w ]+) b/i // Nvidia Shield Tablets
|
/(shield[\w ]+) b/i // Nvidia Shield Tablets
|
||||||
], [MODEL, [VENDOR, 'Nvidia'], [TYPE, TABLET]], [
|
], [MODEL, [VENDOR, 'Nvidia'], [TYPE, TABLET]], [
|
||||||
/(sprint) (\w+)/i // Sprint Phones
|
/(sprint) (\w+)/i // Sprint Phones
|
||||||
], [VENDOR, MODEL, [TYPE, MOBILE]], [
|
], [VENDOR, MODEL, [TYPE, MOBILE]], [
|
||||||
/(kin\.[onetw]{3})/i // Microsoft Kin
|
/(kin\.[onetw]{3})/i // Microsoft Kin
|
||||||
], [[MODEL, /\./g, ' '], [VENDOR, MICROSOFT], [TYPE, MOBILE]], [
|
], [[MODEL, /\./g, ' '], [VENDOR, MICROSOFT], [TYPE, MOBILE]], [
|
||||||
/droid.+; ([c6]+|et5[16]|mc[239][23]x?|vc8[03]x?)\)/i // Zebra
|
/droid.+; (cc6666?|et5[16]|mc[239][23]x?|vc8[03]x?)\)/i // Zebra
|
||||||
], [MODEL, [VENDOR, ZEBRA], [TYPE, TABLET]], [
|
], [MODEL, [VENDOR, ZEBRA], [TYPE, TABLET]], [
|
||||||
/droid.+; (ec30|ps20|tc[2-8]\d[kx])\)/i
|
/droid.+; (ec30|ps20|tc[2-8]\d[kx])\)/i
|
||||||
], [MODEL, [VENDOR, ZEBRA], [TYPE, MOBILE]], [
|
], [MODEL, [VENDOR, ZEBRA], [TYPE, MOBILE]], [
|
||||||
@@ -640,7 +618,7 @@
|
|||||||
/\(dtv[\);].+(aquos)/i,
|
/\(dtv[\);].+(aquos)/i,
|
||||||
/(aquos-tv[\w ]+)\)/i // Sharp
|
/(aquos-tv[\w ]+)\)/i // Sharp
|
||||||
], [MODEL, [VENDOR, SHARP], [TYPE, SMARTTV]],[
|
], [MODEL, [VENDOR, SHARP], [TYPE, SMARTTV]],[
|
||||||
/(bravia[\w ]+)( bui|\))/i // Sony
|
/(bravia[\w ]+)( bui|\))/i // Sony
|
||||||
], [MODEL, [VENDOR, SONY], [TYPE, SMARTTV]], [
|
], [MODEL, [VENDOR, SONY], [TYPE, SMARTTV]], [
|
||||||
/(mitv-\w{5}) bui/i // Xiaomi
|
/(mitv-\w{5}) bui/i // Xiaomi
|
||||||
], [MODEL, [VENDOR, XIAOMI], [TYPE, SMARTTV]], [
|
], [MODEL, [VENDOR, XIAOMI], [TYPE, SMARTTV]], [
|
||||||
@@ -657,11 +635,11 @@
|
|||||||
///////////////////
|
///////////////////
|
||||||
|
|
||||||
/(ouya)/i, // Ouya
|
/(ouya)/i, // Ouya
|
||||||
/(nintendo) (\w+)/i // Nintendo
|
/(nintendo) ([wids3utch]+)/i // Nintendo
|
||||||
], [VENDOR, MODEL, [TYPE, CONSOLE]], [
|
], [VENDOR, MODEL, [TYPE, CONSOLE]], [
|
||||||
/droid.+; (shield) bui/i // Nvidia
|
/droid.+; (shield) bui/i // Nvidia
|
||||||
], [MODEL, [VENDOR, 'Nvidia'], [TYPE, CONSOLE]], [
|
], [MODEL, [VENDOR, 'Nvidia'], [TYPE, CONSOLE]], [
|
||||||
/(playstation \w+)/i // Playstation
|
/(playstation [345portablevi]+)/i // Playstation
|
||||||
], [MODEL, [VENDOR, SONY], [TYPE, CONSOLE]], [
|
], [MODEL, [VENDOR, SONY], [TYPE, CONSOLE]], [
|
||||||
/\b(xbox(?: one)?(?!; xbox))[\); ]/i // Microsoft Xbox
|
/\b(xbox(?: one)?(?!; xbox))[\); ]/i // Microsoft Xbox
|
||||||
], [MODEL, [VENDOR, MICROSOFT], [TYPE, CONSOLE]], [
|
], [MODEL, [VENDOR, MICROSOFT], [TYPE, CONSOLE]], [
|
||||||
@@ -687,8 +665,6 @@
|
|||||||
|
|
||||||
/(tesla)(?: qtcarbrowser|\/[-\w\.]+)/i // Tesla
|
/(tesla)(?: qtcarbrowser|\/[-\w\.]+)/i // Tesla
|
||||||
], [VENDOR, [TYPE, EMBEDDED]], [
|
], [VENDOR, [TYPE, EMBEDDED]], [
|
||||||
/(aeobc)\b/i // Echo Dot
|
|
||||||
], [MODEL, [VENDOR, AMAZON], [TYPE, EMBEDDED]], [
|
|
||||||
|
|
||||||
////////////////////
|
////////////////////
|
||||||
// MIXED (GENERIC)
|
// MIXED (GENERIC)
|
||||||
@@ -718,8 +694,7 @@
|
|||||||
/(webkit|trident|netfront|netsurf|amaya|lynx|w3m|goanna)\/([\w\.]+)/i, // WebKit/Trident/NetFront/NetSurf/Amaya/Lynx/w3m/Goanna
|
/(webkit|trident|netfront|netsurf|amaya|lynx|w3m|goanna)\/([\w\.]+)/i, // WebKit/Trident/NetFront/NetSurf/Amaya/Lynx/w3m/Goanna
|
||||||
/ekioh(flow)\/([\w\.]+)/i, // Flow
|
/ekioh(flow)\/([\w\.]+)/i, // Flow
|
||||||
/(khtml|tasman|links)[\/ ]\(?([\w\.]+)/i, // KHTML/Tasman/Links
|
/(khtml|tasman|links)[\/ ]\(?([\w\.]+)/i, // KHTML/Tasman/Links
|
||||||
/(icab)[\/ ]([23]\.[\d\.]+)/i, // iCab
|
/(icab)[\/ ]([23]\.[\d\.]+)/i // iCab
|
||||||
/\b(libweb)/i
|
|
||||||
], [NAME, VERSION], [
|
], [NAME, VERSION], [
|
||||||
|
|
||||||
/rv\:([\w\.]{1,9})\b.+(gecko)/i // Gecko
|
/rv\:([\w\.]{1,9})\b.+(gecko)/i // Gecko
|
||||||
@@ -736,16 +711,15 @@
|
|||||||
/(windows)[\/ ]?([ntce\d\. ]+\w)(?!.+xbox)/i
|
/(windows)[\/ ]?([ntce\d\. ]+\w)(?!.+xbox)/i
|
||||||
], [NAME, [VERSION, strMapper, windowsVersionMap]], [
|
], [NAME, [VERSION, strMapper, windowsVersionMap]], [
|
||||||
/(win(?=3|9|n)|win 9x )([nt\d\.]+)/i
|
/(win(?=3|9|n)|win 9x )([nt\d\.]+)/i
|
||||||
], [[NAME, WINDOWS], [VERSION, strMapper, windowsVersionMap]], [
|
], [[NAME, 'Windows'], [VERSION, strMapper, windowsVersionMap]], [
|
||||||
|
|
||||||
// iOS/macOS
|
// iOS/macOS
|
||||||
/ip[honead]{2,4}\b(?:.*os ([\w]+) like mac|; opera)/i, // iOS
|
/ip[honead]{2,4}\b(?:.*os ([\w]+) like mac|; opera)/i, // iOS
|
||||||
/ios;fbsv\/([\d\.]+)/i,
|
|
||||||
/cfnetwork\/.+darwin/i
|
/cfnetwork\/.+darwin/i
|
||||||
], [[VERSION, /_/g, '.'], [NAME, 'iOS']], [
|
], [[VERSION, /_/g, '.'], [NAME, 'iOS']], [
|
||||||
/(mac os x) ?([\w\. ]*)/i,
|
/(mac os x) ?([\w\. ]*)/i,
|
||||||
/(macintosh|mac_powerpc\b)(?!.+haiku)/i // Mac OS
|
/(macintosh|mac_powerpc\b)(?!.+haiku)/i // Mac OS
|
||||||
], [[NAME, 'macOS'], [VERSION, /_/g, '.']], [
|
], [[NAME, MAC_OS], [VERSION, /_/g, '.']], [
|
||||||
|
|
||||||
// Mobile OSes
|
// Mobile OSes
|
||||||
/droid ([\w\.]+)\b.+(android[- ]x86|harmonyos)/i // Android-x86/HarmonyOS
|
/droid ([\w\.]+)\b.+(android[- ]x86|harmonyos)/i // Android-x86/HarmonyOS
|
||||||
@@ -771,7 +745,7 @@
|
|||||||
/crkey\/([\d\.]+)/i // Google Chromecast
|
/crkey\/([\d\.]+)/i // Google Chromecast
|
||||||
], [VERSION, [NAME, CHROME+'cast']], [
|
], [VERSION, [NAME, CHROME+'cast']], [
|
||||||
/(cros) [\w]+(?:\)| ([\w\.]+)\b)/i // Chromium OS
|
/(cros) [\w]+(?:\)| ([\w\.]+)\b)/i // Chromium OS
|
||||||
], [[NAME, "Chrome OS"], VERSION],[
|
], [[NAME, CHROMIUM_OS], VERSION],[
|
||||||
|
|
||||||
// Smart TVs
|
// Smart TVs
|
||||||
/panasonic;(viera)/i, // Panasonic Viera
|
/panasonic;(viera)/i, // Panasonic Viera
|
||||||
@@ -779,7 +753,7 @@
|
|||||||
/(nettv)\/(\d+\.[\w\.]+)/i, // NetTV
|
/(nettv)\/(\d+\.[\w\.]+)/i, // NetTV
|
||||||
|
|
||||||
// Console
|
// Console
|
||||||
/(nintendo|playstation) (\w+)/i, // Nintendo/Playstation
|
/(nintendo|playstation) ([wids345portablevuch]+)/i, // Nintendo/Playstation
|
||||||
/(xbox); +xbox ([^\);]+)/i, // Microsoft Xbox (360, One, X, S, Series X, Series S)
|
/(xbox); +xbox ([^\);]+)/i, // Microsoft Xbox (360, One, X, S, Series X, Series S)
|
||||||
|
|
||||||
// Other
|
// Other
|
||||||
@@ -797,321 +771,105 @@
|
|||||||
], [[NAME, 'Solaris'], VERSION], [
|
], [[NAME, 'Solaris'], VERSION], [
|
||||||
/((?:open)?solaris)[-\/ ]?([\w\.]*)/i, // Solaris
|
/((?:open)?solaris)[-\/ ]?([\w\.]*)/i, // Solaris
|
||||||
/(aix) ((\d)(?=\.|\)| )[\w\.])*/i, // AIX
|
/(aix) ((\d)(?=\.|\)| )[\w\.])*/i, // AIX
|
||||||
/\b(beos|os\/2|amigaos|morphos|openvms|fuchsia|hp-ux|serenityos)/i, // BeOS/OS2/AmigaOS/MorphOS/OpenVMS/Fuchsia/HP-UX/SerenityOS
|
/\b(beos|os\/2|amigaos|morphos|openvms|fuchsia|hp-ux)/i, // BeOS/OS2/AmigaOS/MorphOS/OpenVMS/Fuchsia/HP-UX
|
||||||
/(unix) ?([\w\.]*)/i // UNIX
|
/(unix) ?([\w\.]*)/i // UNIX
|
||||||
], [NAME, VERSION]
|
], [NAME, VERSION]
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
/////////////////
|
|
||||||
// Factories
|
|
||||||
////////////////
|
|
||||||
|
|
||||||
var defaultProps = (function () {
|
|
||||||
var props = { init : {}, isIgnore : {}, isIgnoreRgx : {}, toString : {}};
|
|
||||||
assignFromEntries.call(props.init, [
|
|
||||||
[UA_BROWSER, [NAME, VERSION, MAJOR]],
|
|
||||||
[UA_CPU, [ARCHITECTURE]],
|
|
||||||
[UA_DEVICE, [TYPE, MODEL, VENDOR]],
|
|
||||||
[UA_ENGINE, [NAME, VERSION]],
|
|
||||||
[UA_OS, [NAME, VERSION]]
|
|
||||||
]);
|
|
||||||
assignFromEntries.call(props.isIgnore, [
|
|
||||||
[UA_BROWSER, [VERSION, MAJOR]],
|
|
||||||
[UA_ENGINE, [VERSION]],
|
|
||||||
[UA_OS, [VERSION]]
|
|
||||||
]);
|
|
||||||
assignFromEntries.call(props.isIgnoreRgx, [
|
|
||||||
[UA_BROWSER, / ?browser$/i],
|
|
||||||
[UA_OS, / ?os$/i]
|
|
||||||
]);
|
|
||||||
assignFromEntries.call(props.toString, [
|
|
||||||
[UA_BROWSER, [NAME, VERSION]],
|
|
||||||
[UA_CPU, [ARCHITECTURE]],
|
|
||||||
[UA_DEVICE, [VENDOR, MODEL]],
|
|
||||||
[UA_ENGINE, [NAME, VERSION]],
|
|
||||||
[UA_OS, [NAME, VERSION]]
|
|
||||||
]);
|
|
||||||
return props;
|
|
||||||
})();
|
|
||||||
|
|
||||||
var createUAParserData = function (itemType, ua, rgxMap, uaCH) {
|
|
||||||
|
|
||||||
var init_props = defaultProps.init[itemType],
|
|
||||||
is_ignoreProps = defaultProps.isIgnore[itemType] || 0,
|
|
||||||
is_ignoreRgx = defaultProps.isIgnoreRgx[itemType] || 0,
|
|
||||||
toString_props = defaultProps.toString[itemType] || 0;
|
|
||||||
|
|
||||||
function UAParserData () {
|
|
||||||
assignFromEntries.call(this, init_props);
|
|
||||||
}
|
|
||||||
UAParserData.prototype.withClientHints = function () {
|
|
||||||
|
|
||||||
// nodejs / non-client-hints browsers
|
|
||||||
if (!NAVIGATOR_UADATA) {
|
|
||||||
return new UAParserItem(itemType, ua, rgxMap, uaCH).parseCH().get();
|
|
||||||
}
|
|
||||||
|
|
||||||
// browsers based on chromium 85+
|
|
||||||
return NAVIGATOR_UADATA
|
|
||||||
.getHighEntropyValues(CH_ALL_VALUES)
|
|
||||||
.then(function (res) {
|
|
||||||
var JS_UACH = new UAParserDataCH(res, false);
|
|
||||||
return new UAParserItem(itemType, ua, rgxMap, JS_UACH).parseCH().get();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
if (itemType != UA_RESULT) {
|
|
||||||
UAParserData.prototype.is = function (strToCheck) {
|
|
||||||
var is = false;
|
|
||||||
for (var i in this) {
|
|
||||||
if (this.hasOwnProperty(i) && !has(is_ignoreProps, i) && lowerize(is_ignoreRgx ? strip(is_ignoreRgx, this[i]) : this[i]) == lowerize(is_ignoreRgx ? strip(is_ignoreRgx, strToCheck) : strToCheck)) {
|
|
||||||
is = true;
|
|
||||||
if (strToCheck != UNDEF_TYPE) break;
|
|
||||||
} else if (strToCheck == UNDEF_TYPE && is) {
|
|
||||||
is = !is;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return is;
|
|
||||||
};
|
|
||||||
UAParserData.prototype.toString = function () {
|
|
||||||
var str = EMPTY;
|
|
||||||
for (var i in toString_props) {
|
|
||||||
if (typeof(this[toString_props[i]]) !== UNDEF_TYPE) {
|
|
||||||
str += (str ? ' ' : EMPTY) + this[toString_props[i]];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return str || UNDEF_TYPE;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!NAVIGATOR_UADATA) {
|
|
||||||
UAParserData.prototype.then = function (cb) {
|
|
||||||
var that = this;
|
|
||||||
var UAParserDataResolve = function () {
|
|
||||||
for (var prop in that) {
|
|
||||||
if (that.hasOwnProperty(prop)) {
|
|
||||||
this[prop] = that[prop];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
UAParserDataResolve.prototype = {
|
|
||||||
is : UAParserData.prototype.is,
|
|
||||||
toString : UAParserData.prototype.toString
|
|
||||||
};
|
|
||||||
var resolveData = new UAParserDataResolve();
|
|
||||||
cb(resolveData);
|
|
||||||
return resolveData;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return new UAParserData();
|
|
||||||
};
|
|
||||||
|
|
||||||
/////////////////
|
/////////////////
|
||||||
// Constructor
|
// Constructor
|
||||||
////////////////
|
////////////////
|
||||||
|
|
||||||
function UAParserDataCH (uach, isHTTP_UACH) {
|
var UAParser = function (ua, extensions) {
|
||||||
uach = uach || {};
|
|
||||||
assignFromEntries.call(this, CH_ALL_VALUES);
|
|
||||||
if (isHTTP_UACH) {
|
|
||||||
assignFromEntries.call(this, [
|
|
||||||
[BRANDS, itemListToArray(uach[CH_HEADER])],
|
|
||||||
[FULLVERLIST, itemListToArray(uach[CH_HEADER_FULL_VER_LIST])],
|
|
||||||
[BRANDS, itemListToArray(uach[CH_HEADER])],
|
|
||||||
[MOBILE, /\?1/.test(uach[CH_HEADER_MOBILE])],
|
|
||||||
[MODEL, stripQuotes(uach[CH_HEADER_MODEL])],
|
|
||||||
[PLATFORM, stripQuotes(uach[CH_HEADER_PLATFORM])],
|
|
||||||
[PLATFORMVER, stripQuotes(uach[CH_HEADER_PLATFORM_VER])],
|
|
||||||
[ARCHITECTURE, stripQuotes(uach[CH_HEADER_ARCH])],
|
|
||||||
[BITNESS, stripQuotes(uach[CH_HEADER_BITNESS])]
|
|
||||||
]);
|
|
||||||
} else {
|
|
||||||
for (var prop in uach) {
|
|
||||||
if(this.hasOwnProperty(prop) && typeof uach[prop] !== UNDEF_TYPE) this[prop] = uach[prop];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
function UAParserItem (itemType, ua, rgxMap, uaCH) {
|
|
||||||
assignFromEntries.call(this, [
|
|
||||||
['itemType', itemType],
|
|
||||||
['ua', ua],
|
|
||||||
['uaCH', uaCH],
|
|
||||||
['rgxMap', rgxMap],
|
|
||||||
['data', createUAParserData(itemType, ua, rgxMap, uaCH)]
|
|
||||||
]);
|
|
||||||
this.parse();
|
|
||||||
var isSelfNav = NAVIGATOR && NAVIGATOR.userAgent == ua;
|
|
||||||
switch(this.itemType) {
|
|
||||||
case UA_BROWSER:
|
|
||||||
// Brave-specific detection
|
|
||||||
if (isSelfNav && NAVIGATOR.brave && typeof NAVIGATOR.brave.isBrave == FUNC_TYPE) {
|
|
||||||
this.set(NAME, 'Brave');
|
|
||||||
}
|
|
||||||
this.set(MAJOR, majorize(this.get(VERSION)));
|
|
||||||
break;
|
|
||||||
case UA_DEVICE:
|
|
||||||
if (isSelfNav && !this.get(TYPE) && NAVIGATOR_UADATA && NAVIGATOR_UADATA[MOBILE]) {
|
|
||||||
this.set(TYPE, MOBILE);
|
|
||||||
}
|
|
||||||
// iPadOS-specific detection: identified as Mac, but has some iOS-only properties
|
|
||||||
if (isSelfNav && this.get(MODEL) == 'Macintosh' && NAVIGATOR && typeof NAVIGATOR.standalone !== UNDEF_TYPE && NAVIGATOR.maxTouchPoints && NAVIGATOR.maxTouchPoints > 2) {
|
|
||||||
this.set(MODEL, 'iPad')
|
|
||||||
.set(TYPE, TABLET);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case UA_OS:
|
|
||||||
if (isSelfNav && !this.get(NAME) && NAVIGATOR_UADATA && NAVIGATOR_UADATA[PLATFORM]) {
|
|
||||||
this.set(NAME, NAVIGATOR_UADATA[PLATFORM]);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case UA_RESULT:
|
|
||||||
var createUAParserItem = function (itemType) {
|
|
||||||
return new UAParserItem(itemType, ua, rgxMap[itemType], uaCH).get();
|
|
||||||
};
|
|
||||||
this.set('ua', ua)
|
|
||||||
.set(UA_BROWSER, createUAParserItem(UA_BROWSER))
|
|
||||||
.set(UA_CPU, createUAParserItem(UA_CPU))
|
|
||||||
.set(UA_DEVICE, createUAParserItem(UA_DEVICE))
|
|
||||||
.set(UA_ENGINE, createUAParserItem(UA_ENGINE))
|
|
||||||
.set(UA_OS, createUAParserItem(UA_OS))
|
|
||||||
.get();
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
UAParserItem.prototype.get = function (prop) {
|
|
||||||
if (!prop) return this.data;
|
|
||||||
return this.data.hasOwnProperty(prop) ? this.data[prop] : undefined;
|
|
||||||
};
|
|
||||||
UAParserItem.prototype.parse = function () {
|
|
||||||
if (this.itemType != UA_RESULT) {
|
|
||||||
rgxMapper.call(this.data, this.ua, this.rgxMap);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
UAParserItem.prototype.parseCH = function () {
|
|
||||||
var ua = this.ua,
|
|
||||||
uaCH = this.uaCH,
|
|
||||||
rgxMap = this.rgxMap;
|
|
||||||
|
|
||||||
switch (this.itemType) {
|
|
||||||
case UA_BROWSER:
|
|
||||||
var brands = uaCH[FULLVERLIST] || uaCH[BRANDS];
|
|
||||||
if (brands) {
|
|
||||||
for (var i in brands) {
|
|
||||||
var brandName = brands[i].brand,
|
|
||||||
brandVersion = brands[i].version;
|
|
||||||
if (!/not.a.brand/i.test(brandName) && (i < 1 || /chromi/i.test(this.get(NAME)))) {
|
|
||||||
this.set(NAME, strip(GOOGLE+' ', brandName))
|
|
||||||
.set(VERSION, brandVersion)
|
|
||||||
.set(MAJOR, majorize(brandVersion));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case UA_CPU:
|
|
||||||
var archName = uaCH[ARCHITECTURE];
|
|
||||||
if (archName) {
|
|
||||||
if (archName && uaCH[BITNESS] == '64') archName += '64';
|
|
||||||
rgxMapper.call(this.data, archName + ';', rgxMap);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case UA_DEVICE:
|
|
||||||
if (uaCH[MOBILE]) {
|
|
||||||
this.set(TYPE, MOBILE);
|
|
||||||
}
|
|
||||||
if (uaCH[MODEL]) {
|
|
||||||
this.set(MODEL, uaCH[MODEL]);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case UA_OS:
|
|
||||||
var osName = uaCH[PLATFORM];
|
|
||||||
if(osName) {
|
|
||||||
var osVersion = uaCH[PLATFORMVER];
|
|
||||||
if (osName == WINDOWS) osVersion = (parseInt(majorize(osVersion), 10) >= 13 ? '11' : '10');
|
|
||||||
this.set(NAME, osName)
|
|
||||||
.set(VERSION, osVersion);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case UA_RESULT:
|
|
||||||
var createUAParserItemWithCH = function (itemType) {
|
|
||||||
return new UAParserItem(itemType, ua, rgxMap[itemType], uaCH).parseCH().get();
|
|
||||||
};
|
|
||||||
this.set('ua', ua)
|
|
||||||
.set(UA_BROWSER, createUAParserItemWithCH(UA_BROWSER))
|
|
||||||
.set(UA_CPU, createUAParserItemWithCH(UA_CPU))
|
|
||||||
.set(UA_DEVICE, createUAParserItemWithCH(UA_DEVICE))
|
|
||||||
.set(UA_ENGINE, createUAParserItemWithCH(UA_ENGINE))
|
|
||||||
.set(UA_OS, createUAParserItemWithCH(UA_OS));
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
UAParserItem.prototype.set = function (prop, val) {
|
|
||||||
this.data[prop] = val;
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
function UAParser (ua, extensions, headers) {
|
|
||||||
|
|
||||||
if (typeof ua === OBJ_TYPE) {
|
if (typeof ua === OBJ_TYPE) {
|
||||||
if (isExtensions(ua)) {
|
extensions = ua;
|
||||||
if (typeof extensions === OBJ_TYPE) {
|
|
||||||
headers = extensions; // case UAParser(extensions, headers)
|
|
||||||
}
|
|
||||||
extensions = ua; // case UAParser(extensions)
|
|
||||||
} else {
|
|
||||||
headers = ua; // case UAParser(headers)
|
|
||||||
extensions = undefined;
|
|
||||||
}
|
|
||||||
ua = undefined;
|
ua = undefined;
|
||||||
} else if (typeof ua === STR_TYPE && !isExtensions(extensions)) {
|
|
||||||
headers = extensions; // case UAParser(ua, headers)
|
|
||||||
extensions = undefined;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(this instanceof UAParser)) {
|
if (!(this instanceof UAParser)) {
|
||||||
return new UAParser(ua, extensions, headers).getResult();
|
return new UAParser(ua, extensions).getResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
var userAgent = ua ||
|
var _navigator = (typeof window !== UNDEF_TYPE && window.navigator) ? window.navigator : undefined;
|
||||||
((NAVIGATOR && NAVIGATOR.userAgent) ?
|
var _ua = ua || ((_navigator && _navigator.userAgent) ? _navigator.userAgent : EMPTY);
|
||||||
NAVIGATOR.userAgent :
|
var _uach = (_navigator && _navigator.userAgentData) ? _navigator.userAgentData : undefined;
|
||||||
(headers && headers[USER_AGENT] ?
|
var _rgxmap = extensions ? extend(regexes, extensions) : regexes;
|
||||||
headers[USER_AGENT] :
|
|
||||||
EMPTY)),
|
|
||||||
|
|
||||||
HTTP_UACH = new UAParserDataCH(headers, true),
|
|
||||||
|
|
||||||
regexMap = extensions ?
|
this.getBrowser = function () {
|
||||||
extend(defaultRegexes, extensions) :
|
var _browser = {};
|
||||||
defaultRegexes,
|
_browser[NAME] = undefined;
|
||||||
|
_browser[VERSION] = undefined;
|
||||||
createUAParserItemFunc = function (itemType) {
|
rgxMapper.call(_browser, _ua, _rgxmap.browser);
|
||||||
return function () {
|
_browser[MAJOR] = majorize(_browser[VERSION]);
|
||||||
return new UAParserItem(itemType, userAgent, itemType == UA_RESULT ? regexMap : regexMap[itemType], HTTP_UACH).get();
|
// Brave-specific detection
|
||||||
};
|
if (_navigator && _navigator.brave && typeof _navigator.brave.isBrave == FUNC_TYPE) {
|
||||||
|
_browser[NAME] = 'Brave';
|
||||||
|
}
|
||||||
|
return _browser;
|
||||||
|
};
|
||||||
|
this.getCPU = function () {
|
||||||
|
var _cpu = {};
|
||||||
|
_cpu[ARCHITECTURE] = undefined;
|
||||||
|
rgxMapper.call(_cpu, _ua, _rgxmap.cpu);
|
||||||
|
return _cpu;
|
||||||
|
};
|
||||||
|
this.getDevice = function () {
|
||||||
|
var _device = {};
|
||||||
|
_device[VENDOR] = undefined;
|
||||||
|
_device[MODEL] = undefined;
|
||||||
|
_device[TYPE] = undefined;
|
||||||
|
rgxMapper.call(_device, _ua, _rgxmap.device);
|
||||||
|
if (!_device[TYPE] && _uach && _uach.mobile) {
|
||||||
|
_device[TYPE] = MOBILE;
|
||||||
|
}
|
||||||
|
// iPadOS-specific detection: identified as Mac, but has some iOS-only properties
|
||||||
|
if (_device[MODEL] == 'Macintosh' && _navigator && typeof _navigator.standalone !== UNDEF_TYPE && _navigator.maxTouchPoints && _navigator.maxTouchPoints > 2) {
|
||||||
|
_device[MODEL] = 'iPad';
|
||||||
|
_device[TYPE] = TABLET;
|
||||||
|
}
|
||||||
|
return _device;
|
||||||
|
};
|
||||||
|
this.getEngine = function () {
|
||||||
|
var _engine = {};
|
||||||
|
_engine[NAME] = undefined;
|
||||||
|
_engine[VERSION] = undefined;
|
||||||
|
rgxMapper.call(_engine, _ua, _rgxmap.engine);
|
||||||
|
return _engine;
|
||||||
|
};
|
||||||
|
this.getOS = function () {
|
||||||
|
var _os = {};
|
||||||
|
_os[NAME] = undefined;
|
||||||
|
_os[VERSION] = undefined;
|
||||||
|
rgxMapper.call(_os, _ua, _rgxmap.os);
|
||||||
|
if (!_os[NAME] && _uach && _uach.platform != 'Unknown') {
|
||||||
|
_os[NAME] = _uach.platform
|
||||||
|
.replace(/chrome os/i, CHROMIUM_OS)
|
||||||
|
.replace(/macos/i, MAC_OS); // backward compatibility
|
||||||
|
}
|
||||||
|
return _os;
|
||||||
|
};
|
||||||
|
this.getResult = function () {
|
||||||
|
return {
|
||||||
|
ua : this.getUA(),
|
||||||
|
browser : this.getBrowser(),
|
||||||
|
engine : this.getEngine(),
|
||||||
|
os : this.getOS(),
|
||||||
|
device : this.getDevice(),
|
||||||
|
cpu : this.getCPU()
|
||||||
};
|
};
|
||||||
|
};
|
||||||
// public methods
|
this.getUA = function () {
|
||||||
assignFromEntries.call(this, [
|
return _ua;
|
||||||
['getBrowser', createUAParserItemFunc(UA_BROWSER)],
|
};
|
||||||
['getCPU', createUAParserItemFunc(UA_CPU)],
|
this.setUA = function (ua) {
|
||||||
['getDevice', createUAParserItemFunc(UA_DEVICE)],
|
_ua = (typeof ua === STR_TYPE && ua.length > UA_MAX_LENGTH) ? trim(ua, UA_MAX_LENGTH) : ua;
|
||||||
['getEngine', createUAParserItemFunc(UA_ENGINE)],
|
return this;
|
||||||
['getOS', createUAParserItemFunc(UA_OS)],
|
};
|
||||||
['getResult', createUAParserItemFunc(UA_RESULT)],
|
this.setUA(_ua);
|
||||||
['getUA', function () { return userAgent; }],
|
|
||||||
['setUA', function (ua) {
|
|
||||||
userAgent = (typeof ua === STR_TYPE && ua.length > UA_MAX_LENGTH) ? trim(ua, UA_MAX_LENGTH) : ua;
|
|
||||||
return this;
|
|
||||||
}]
|
|
||||||
]).setUA(userAgent);
|
|
||||||
return this;
|
return this;
|
||||||
}
|
};
|
||||||
|
|
||||||
UAParser.VERSION = LIBVERSION;
|
UAParser.VERSION = LIBVERSION;
|
||||||
UAParser.BROWSER = enumerize([NAME, VERSION, MAJOR]);
|
UAParser.BROWSER = enumerize([NAME, VERSION, MAJOR]);
|
||||||
|
|||||||
1126
src/ua-parser.mjs
1126
src/ua-parser.mjs
File diff suppressed because it is too large
Load Diff
@@ -234,7 +234,7 @@
|
|||||||
"ua" : "Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_1_1 like Mac OS X; en) AppleWebKit/534.46.0 (KHTML, like Gecko) CriOS/19.0.1084.60 Mobile/9B206 Safari/7534.48.3",
|
"ua" : "Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_1_1 like Mac OS X; en) AppleWebKit/534.46.0 (KHTML, like Gecko) CriOS/19.0.1084.60 Mobile/9B206 Safari/7534.48.3",
|
||||||
"expect" :
|
"expect" :
|
||||||
{
|
{
|
||||||
"name" : "Mobile Chrome",
|
"name" : "Chrome",
|
||||||
"version" : "19.0.1084.60",
|
"version" : "19.0.1084.60",
|
||||||
"major" : "19"
|
"major" : "19"
|
||||||
}
|
}
|
||||||
@@ -254,7 +254,7 @@
|
|||||||
"ua" : "Mozilla/5.0 (Linux; U; Android-4.0.3; en-us; Galaxy Nexus Build/IML74K) AppleWebKit/535.7 (KHTML, like Gecko) CrMo/16.0.912.75 Mobile Safari/535.7",
|
"ua" : "Mozilla/5.0 (Linux; U; Android-4.0.3; en-us; Galaxy Nexus Build/IML74K) AppleWebKit/535.7 (KHTML, like Gecko) CrMo/16.0.912.75 Mobile Safari/535.7",
|
||||||
"expect" :
|
"expect" :
|
||||||
{
|
{
|
||||||
"name" : "Mobile Chrome",
|
"name" : "Chrome",
|
||||||
"version" : "16.0.912.75",
|
"version" : "16.0.912.75",
|
||||||
"major" : "16"
|
"major" : "16"
|
||||||
}
|
}
|
||||||
@@ -508,16 +508,6 @@
|
|||||||
"major" : "1"
|
"major" : "1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"desc" : "HeyTap",
|
|
||||||
"ua" : "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.61 Safari/537.36 HeyTapBrowser/40.8.10.1",
|
|
||||||
"expect" :
|
|
||||||
{
|
|
||||||
"name" : "HeyTap",
|
|
||||||
"version" : "40.8.10.1",
|
|
||||||
"major" : "40"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"desc" : "HuaweiBrowser",
|
"desc" : "HuaweiBrowser",
|
||||||
"ua" : "Mozilla/5.0 (Linux; Android 6.0.1; LYA-AL00;HMSCore/4.0.0 GMS/10.4 ) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.64 HuaweiBrowser/10.0.3.102 Mobile Safari/537.36",
|
"ua" : "Mozilla/5.0 (Linux; Android 6.0.1; LYA-AL00;HMSCore/4.0.0 GMS/10.4 ) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.64 HuaweiBrowser/10.0.3.102 Mobile Safari/537.36",
|
||||||
@@ -768,16 +758,6 @@
|
|||||||
"major" : "4"
|
"major" : "4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"desc" : "Mobile Safari",
|
|
||||||
"ua" : "Mozilla/5.0 (iPhone; CPU iPhone OS 16_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Safari/604.1",
|
|
||||||
"expect" :
|
|
||||||
{
|
|
||||||
"name" : "Mobile Safari",
|
|
||||||
"version" : "undefined",
|
|
||||||
"major" : "undefined"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"desc" : "Mosaic",
|
"desc" : "Mosaic",
|
||||||
"ua" : "NCSA_Mosaic/2.6 (X11; SunOS 4.1.3 sun4m)",
|
"ua" : "NCSA_Mosaic/2.6 (X11; SunOS 4.1.3 sun4m)",
|
||||||
@@ -1318,16 +1298,6 @@
|
|||||||
"major" : "1"
|
"major" : "1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"desc" : "Yandex",
|
|
||||||
"ua" : "Mozilla/5.0 (Linux; arm_64; Android 11; M2101K7AG) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.125 YaApp_Android/22.70 YaSearchBrowser/22.70 BroPP/1.0 SA/3 Mobile Safari/537.36",
|
|
||||||
"expect" :
|
|
||||||
{
|
|
||||||
"name" : "Yandex",
|
|
||||||
"version" : "22.70",
|
|
||||||
"major" : "22"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"desc" : "Puffin",
|
"desc" : "Puffin",
|
||||||
"ua" : "Mozilla/5.0 (Linux; Android 6.0.1; Lenovo P2a42 Build/MMB29M; en-us) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Mobile Safari/537.36 Puffin/6.0.8.15804AP",
|
"ua" : "Mozilla/5.0 (Linux; Android 6.0.1; Lenovo P2a42 Build/MMB29M; en-us) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Mobile Safari/537.36 Puffin/6.0.8.15804AP",
|
||||||
@@ -1423,7 +1393,7 @@
|
|||||||
"ua" : "Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) FxiOS/1.1 Mobile/13B143 Safari/601.1.46",
|
"ua" : "Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) FxiOS/1.1 Mobile/13B143 Safari/601.1.46",
|
||||||
"expect" :
|
"expect" :
|
||||||
{
|
{
|
||||||
"name" : "Mobile Firefox",
|
"name" : "Firefox",
|
||||||
"version" : "1.1",
|
"version" : "1.1",
|
||||||
"major" : "1"
|
"major" : "1"
|
||||||
}
|
}
|
||||||
@@ -1433,7 +1403,7 @@
|
|||||||
"ua" : "Mozilla/5.0 (iPad; CPU iPhone OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) FxiOS/1.0 Mobile/12F69 Safari/600.1.4",
|
"ua" : "Mozilla/5.0 (iPad; CPU iPhone OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) FxiOS/1.0 Mobile/12F69 Safari/600.1.4",
|
||||||
"expect" :
|
"expect" :
|
||||||
{
|
{
|
||||||
"name" : "Mobile Firefox",
|
"name" : "Firefox",
|
||||||
"version" : "1.0",
|
"version" : "1.0",
|
||||||
"major" : "1"
|
"major" : "1"
|
||||||
}
|
}
|
||||||
@@ -1712,62 +1682,5 @@
|
|||||||
"version": "10.25.0",
|
"version": "10.25.0",
|
||||||
"major" : "10"
|
"major" : "10"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc" : "TikTok",
|
|
||||||
"ua" : "Mozilla/5.0 (Linux; Android 11; 21061119AG Build/RP1A.200720.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/92.0.4515.131 Mobile Safari/537.36 trill_2022109040 JsSdk/1.0 NetType/MOBILE Channel/googleplay AppName/musical_ly app_version/21.9.4 ByteLocale/ru-RU ByteFullLocale/ru-RU Region/KG BytedanceWebview/d8a21c6",
|
|
||||||
"expect" : {
|
|
||||||
"name" : "TikTok",
|
|
||||||
"version": "21.9.4",
|
|
||||||
"major" : "21"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc" : "TikTok",
|
|
||||||
"ua" : "Mozilla/5.0 (iPhone; CPU iPhone OS 14_8 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 musical_ly_21.1.0 JsSdk/2.0 NetType/4G Channel/App Store ByteLocale/ru Region/RU ByteFullLocale/ru-RU isDarkMode/1 WKWebView/1 BytedanceWebview/d8a21c6",
|
|
||||||
"expect" : {
|
|
||||||
"name" : "TikTok",
|
|
||||||
"version": "21.1.0",
|
|
||||||
"major" : "21"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc" : "TikTok",
|
|
||||||
"ua" : "Mozilla/5.0 (Linux; Android 10; STK-LX1 Build/HONORSTK-LX1; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/110.0.5481.153 Mobile Safari/537.36 musical_ly_2022803040 JsSdk/1.0 NetType/WIFI Channel/huaweiadsglobal_int AppName/musical_ly app_version/28.3.4 ByteLocale/en ByteFullLocale/en Region/IQ Spark/1.2.7-alpha.8 AppVersion/28.3.4 PIA/1.5.11 BytedanceWebview/d8a21c6",
|
|
||||||
"expect" : {
|
|
||||||
"name" : "TikTok",
|
|
||||||
"version": "28.3.4",
|
|
||||||
"major" : "28"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc" : "Chrome Mobile",
|
|
||||||
"ua" : "Mozilla/5.0 (Linux; Android 7.1.2; Nexus 5X Build/N2G47W) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.83 Mobile Safari/537.36",
|
|
||||||
"expect" :
|
|
||||||
{
|
|
||||||
"name" : "Mobile Chrome",
|
|
||||||
"version" : "58.0.3029.83",
|
|
||||||
"major" : "58"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc" : "Firefox Mobile",
|
|
||||||
"ua" : "Mozilla/5.0 (Linux; Android 7.1.2; Nexus 5X Build/N2G47W) AppleWebKit/537.36 (KHTML, like Gecko) FxiOS/7.5b3349 Mobile/14F89 Safari/603.2.4",
|
|
||||||
"expect" :
|
|
||||||
{
|
|
||||||
"name" : "Mobile Firefox",
|
|
||||||
"version" : "7.5b3349",
|
|
||||||
"major" : "7"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc" : "Firefox Mobile",
|
|
||||||
"ua" : "Mozilla/5.0 (Android 5.0; Mobile; rv:41.0) Gecko/41.0 Firefox/41.0",
|
|
||||||
"expect" :
|
|
||||||
{
|
|
||||||
"name" : "Mobile Firefox",
|
|
||||||
"version" : "41.0",
|
|
||||||
"major" : "41"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -206,13 +206,5 @@
|
|||||||
{
|
{
|
||||||
"architecture" : "irix64"
|
"architecture" : "irix64"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc" : "68k",
|
|
||||||
"ua" : "'Mozilla/1.1 (Macintosh; U; 68K)'",
|
|
||||||
"expect" :
|
|
||||||
{
|
|
||||||
"architecture" : "68k"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -205,6 +205,15 @@
|
|||||||
"type": "mobile"
|
"type": "mobile"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"desc": "Essential PH-1",
|
||||||
|
"ua": "Mozilla/5.0 (Linux; Android 9; PH-1 Build/PPR1.180905.036) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.86 Mobile Safari/537.36",
|
||||||
|
"expect": {
|
||||||
|
"vendor": "Essential",
|
||||||
|
"model": "PH-1",
|
||||||
|
"type": "mobile"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"desc": "Fairphone 1U",
|
"desc": "Fairphone 1U",
|
||||||
"ua": "Mozilla/5.0 (Linux; U; Android 4.2.2; FP1U Build/JDQ39) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30",
|
"ua": "Mozilla/5.0 (Linux; U; Android 4.2.2; FP1U Build/JDQ39) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30",
|
||||||
@@ -1629,33 +1638,6 @@
|
|||||||
"type": "tablet"
|
"type": "tablet"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"desc": "Echo Show 5",
|
|
||||||
"ua": "Mozilla/5.0 (Linux; Android 5.1; AEORK Build/LVY48F; xx-xx) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/70.0.3538.110 Mobile Safari/537.36",
|
|
||||||
"expect": {
|
|
||||||
"vendor": "Amazon",
|
|
||||||
"model": "AEORK",
|
|
||||||
"type": "tablet"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc": "Echo Show 8",
|
|
||||||
"ua": "Mozilla/5.0 (Linux; Android 7.1; AEOCH) AppleWebKit/537.36 (KHTML, like Gecko) Silk/77.2.21 like Chrome/77.0.3865.92 Mobile Safari/537.36",
|
|
||||||
"expect": {
|
|
||||||
"vendor": "Amazon",
|
|
||||||
"model": "AEOCH",
|
|
||||||
"type": "tablet"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc": "Echo Dot",
|
|
||||||
"ua": "Dalvik/2.1.0 (Linux; U; Android 5.1.1; AEOBC Build/LVY48F)",
|
|
||||||
"expect": {
|
|
||||||
"vendor": "Amazon",
|
|
||||||
"model": "AEOBC",
|
|
||||||
"type": "embedded"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"desc": "Samsung Galaxy A21s",
|
"desc": "Samsung Galaxy A21s",
|
||||||
"ua": "Mozilla/5.0 (Linux; Android 10; SAMSUNG SM-A217F) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/11.0 Chrome/75.0.3770.143 Mobile Safari/537.36",
|
"ua": "Mozilla/5.0 (Linux; Android 10; SAMSUNG SM-A217F) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/11.0 Chrome/75.0.3770.143 Mobile Safari/537.36",
|
||||||
@@ -2718,6 +2700,294 @@
|
|||||||
"type": "tablet"
|
"type": "tablet"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"desc": "RCA Voyager III Tablet",
|
||||||
|
"ua": "Mozilla/5.0 (Linux; Android 6.0.1; RCT6973W43 Build/MMB29M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
|
||||||
|
"expect": {
|
||||||
|
"vendor": "RCA",
|
||||||
|
"model": "RCT6973W43",
|
||||||
|
"type": "tablet"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "RCA Voyager II Tablet",
|
||||||
|
"ua": "Mozilla/5.0 (Linux; Android 5.0; RCT6773W22B Build/LRX21M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
|
||||||
|
"expect": {
|
||||||
|
"vendor": "RCA",
|
||||||
|
"model": "RCT6773W22B",
|
||||||
|
"type": "tablet"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "Verizon Quanta Tablet",
|
||||||
|
"ua": "Mozilla/5.0 (Linux; Android 4.4.2; QMV7B Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
|
||||||
|
"expect": {
|
||||||
|
"vendor": "Verizon",
|
||||||
|
"model": "QMV7B",
|
||||||
|
"type": "tablet"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "Verizon Ellipsis 8 Tablet",
|
||||||
|
"ua": "Mozilla/5.0 (Linux; Android 5.1.1; QTAQZ3 Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
|
||||||
|
"expect": {
|
||||||
|
"vendor": "Verizon",
|
||||||
|
"model": "QTAQZ3",
|
||||||
|
"type": "tablet"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "Verizon Ellipsis 8HD Tablet",
|
||||||
|
"ua": "Mozilla/5.0 (Linux; Android 6.0.1; QTASUN1 Build/MMB29M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.81 Safari/537.36",
|
||||||
|
"expect": {
|
||||||
|
"vendor": "Verizon",
|
||||||
|
"model": "QTASUN1",
|
||||||
|
"type": "tablet"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "Dell Venue 8 Tablet",
|
||||||
|
"ua": "Mozilla/5.0 (Linux; Android 4.4.2; Venue 8 3830 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
|
||||||
|
"expect": {
|
||||||
|
"vendor": "Dell",
|
||||||
|
"model": "Venue 8 3830",
|
||||||
|
"type": "tablet"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "Dell Venue 7 Tablet",
|
||||||
|
"ua": "Mozilla/5.0 (Linux; Android 4.4.2; Venue 7 3730 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
|
||||||
|
"expect": {
|
||||||
|
"vendor": "Dell",
|
||||||
|
"model": "Venue 7 3730",
|
||||||
|
"type": "tablet"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "Barnes & Noble Nook HD+ Tablet",
|
||||||
|
"ua": "Mozilla/5.0 (Linux; U; Android 4.1.2; en-us; Barnes & Noble Nook HD+ Build/JZO54K; CyanogenMod-10) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30",
|
||||||
|
"expect": {
|
||||||
|
"vendor": "Barnes & Noble",
|
||||||
|
"model": "Nook HD+",
|
||||||
|
"type": "tablet"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "Barnes & Noble V400 Tablet",
|
||||||
|
"ua": "Mozilla/5.0 (Linux; Android 4.0.4; BNTV400 Build/IMM76L) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.111 Safari/537.36",
|
||||||
|
"expect": {
|
||||||
|
"vendor": "Barnes & Noble",
|
||||||
|
"model": "V400",
|
||||||
|
"type": "tablet"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "NuVision TM101A540N Tablet",
|
||||||
|
"ua": "Mozilla/5.0 (Linux; Android 5.1; TM101A540N Build/LMY47I; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/50.0.2661.86 Safari/537.36",
|
||||||
|
"expect": {
|
||||||
|
"vendor": "NuVision",
|
||||||
|
"model": "TM101A540N",
|
||||||
|
"type": "tablet"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "ZTE-Z431",
|
||||||
|
"ua": "ZTE-Z431/1.4.0 NetFront/4.2 QTV5.1 Profile/MIDP-2.1 Configuration/CLDC-1.1",
|
||||||
|
"expect": {
|
||||||
|
"vendor": "ZTE",
|
||||||
|
"model": "Z431",
|
||||||
|
"type": "mobile"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "ZTE",
|
||||||
|
"ua": "Mozilla/5.0 (Linux; U; Android 4.1.2; en-us; ZTE-Z740G Build/JZO54K) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30",
|
||||||
|
"expect": {
|
||||||
|
"vendor": "ZTE",
|
||||||
|
"model": "Z740G",
|
||||||
|
"type": "mobile"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "ZTE K Series Tablet",
|
||||||
|
"ua": "Mozilla/5.0 (Linux; Android 6.0.1; K88 Build/MMB29M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
|
||||||
|
"expect": {
|
||||||
|
"vendor": "ZTE",
|
||||||
|
"model": "K88",
|
||||||
|
"type": "tablet"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "ZTE Nubia Red Magic 3",
|
||||||
|
"ua": "Mozilla/5.0 (Linux; Android 9; NX629J Build/PKQ1.190321.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/45016 Mobile Safari/537.36 MMWEBID/4064 MicroMessenger/7.0.10.1580(0x27000A34) Process/tools NetType/WIFI Language/zh_CN ABI/arm64",
|
||||||
|
"expect": {
|
||||||
|
"vendor": "ZTE",
|
||||||
|
"model": "NX629J",
|
||||||
|
"type": "mobile"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "ZTE Blade A5",
|
||||||
|
"ua": "Mozilla/5.0 (Linux; Android 9; ZTE Blade A5 2019) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.116 Mobile Safari/537.36",
|
||||||
|
"expect": {
|
||||||
|
"vendor": "ZTE",
|
||||||
|
"model": "Blade A5 2019",
|
||||||
|
"type": "mobile"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "ZTE BLADE V0730",
|
||||||
|
"ua": "Mozilla/5.0 (Linux; Android 6.0; ZTE BLADE V0730) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.116 Mobile Safari/537.36",
|
||||||
|
"expect": {
|
||||||
|
"vendor": "ZTE",
|
||||||
|
"model": "BLADE V0730",
|
||||||
|
"type": "mobile"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "ZTE B2017G",
|
||||||
|
"ua": "Mozilla/5.0 (Linux; Android 7.1.1; ZTE B2017G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.93 Mobile Safari/537.36",
|
||||||
|
"expect": {
|
||||||
|
"vendor": "ZTE",
|
||||||
|
"model": "B2017G",
|
||||||
|
"type": "mobile"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "Swizz GEN610",
|
||||||
|
"ua": "Mozilla/5.0 (Linux; Android 4.4.2; GEN610 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.83 Mobile Safari/537.36",
|
||||||
|
"expect": {
|
||||||
|
"vendor": "Swiss",
|
||||||
|
"model": "GEN610",
|
||||||
|
"type": "mobile"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "Swizz ZUR700",
|
||||||
|
"ua": "Mozilla/5.0 (Linux; Android 4.4.2; ZUR700 Build/KVT49L) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.96 Safari/537.36",
|
||||||
|
"expect": {
|
||||||
|
"vendor": "Swiss",
|
||||||
|
"model": "ZUR700",
|
||||||
|
"type": "tablet"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "Zeki TB782b Tablet",
|
||||||
|
"ua": "Mozilla/5.0 (Linux; U; Android 4.0.4; en-US; TB782B Build/IMM76D) AppleWebKit/534.31 (KHTML, like Gecko) UCBrowser/9.0.2.299 U3/0.8.0 Mobile Safari/534.31",
|
||||||
|
"expect": {
|
||||||
|
"vendor": "Zeki",
|
||||||
|
"model": "TB782B",
|
||||||
|
"type": "tablet"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "Dragon Touch Tablet",
|
||||||
|
"ua": "Mozilla/5.0 (Linux; Android 4.0.4; DT9138B Build/IMM76D) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.72 Mobile Safari/537.36",
|
||||||
|
"expect": {
|
||||||
|
"vendor": "Dragon Touch",
|
||||||
|
"model": "9138B",
|
||||||
|
"type": "tablet"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "Insignia Tablet",
|
||||||
|
"ua": "Mozilla/5.0 (Linux; U; Android 6.0.1; NS-P08A7100 Build/MMB29M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/56.0.2924.87 Safari/537.36",
|
||||||
|
"expect": {
|
||||||
|
"vendor": "Insignia",
|
||||||
|
"model": "NS-P08A7100",
|
||||||
|
"type": "tablet"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "Voice Xtreme V75",
|
||||||
|
"ua": "Mozilla/5.0 (Linux; U; Android 4.2.1; en-us; V75 Build/JOP40D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30",
|
||||||
|
"expect": {
|
||||||
|
"vendor": "Voice",
|
||||||
|
"model": "V75",
|
||||||
|
"type": "mobile"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "LvTel V11",
|
||||||
|
"ua": "Mozilla/5.0 (Linux; Android 5.1.1; V11 Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/39.0.0.0 Safari/537.36",
|
||||||
|
"expect": {
|
||||||
|
"vendor": "LvTel",
|
||||||
|
"model": "V11",
|
||||||
|
"type": "mobile"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "Envizen Tablet V100MD",
|
||||||
|
"ua": "Mozilla/5.0 (Linux; U; Android 4.1.1; en-us; V100MD Build/V100MD.20130816) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30",
|
||||||
|
"expect": {
|
||||||
|
"vendor": "Envizen",
|
||||||
|
"model": "V100MD",
|
||||||
|
"type": "tablet"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "Rotor Tablet",
|
||||||
|
"ua": "mozilla/5.0 (linux; android 5.0.1; tu_1491 build/lrx22c) applewebkit/537.36 (khtml, like gecko) chrome/43.0.2357.93 safari/537.36",
|
||||||
|
"expect": {
|
||||||
|
"vendor": "Rotor",
|
||||||
|
"model": "1491",
|
||||||
|
"type": "tablet"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "MachSpeed Tablets",
|
||||||
|
"ua": "Mozilla/5.0 (Linux; Android 4.4.2; Trio 7.85 vQ Build/Trio_7.85_vQ) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Safari/537.36",
|
||||||
|
"expect": {
|
||||||
|
"vendor": "MachSpeed",
|
||||||
|
"model": "Trio 7.85 vQ",
|
||||||
|
"type": "tablet"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "Trinity Tablets",
|
||||||
|
"ua": "Mozilla/5.0 (Linux; Android 5.0.1; Trinity T101 Build/LRX22C) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.83 Safari/537.36",
|
||||||
|
"expect": {
|
||||||
|
"vendor": "Trinity",
|
||||||
|
"model": "T101",
|
||||||
|
"type": "tablet"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "NextBook Next7",
|
||||||
|
"ua": "Mozilla/5.0 (Linux; U; Android 4.0.4; en-us; Next7P12 Build/IMM76I) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30",
|
||||||
|
"expect": {
|
||||||
|
"vendor": "NextBook",
|
||||||
|
"model": "Next7P12",
|
||||||
|
"type": "tablet"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "NextBook Tablets",
|
||||||
|
"ua": "Mozilla/5.0 (Linux; Android 5.0; NXA8QC116 Build/LRX21V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
|
||||||
|
"expect": {
|
||||||
|
"vendor": "NextBook",
|
||||||
|
"model": "NXA8QC116",
|
||||||
|
"type": "tablet"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "Le Pan Tablets",
|
||||||
|
"ua": "Mozilla/5.0 (Linux; Android 4.2.2; Le Pan TC802A Build/JDQ39) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
|
||||||
|
"expect": {
|
||||||
|
"vendor": "Le Pan",
|
||||||
|
"model": "TC802A",
|
||||||
|
"type": "tablet"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "Le Pan Tablets",
|
||||||
|
"ua": "Mozilla/5.0 (Linux; Android 4.2.2; Le Pan TC802A Build/JDQ39) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
|
||||||
|
"expect": {
|
||||||
|
"vendor": "Le Pan",
|
||||||
|
"model": "TC802A",
|
||||||
|
"type": "tablet"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"desc": "Amazon Alexa Echo Show",
|
"desc": "Amazon Alexa Echo Show",
|
||||||
"ua": "AlexaWebMediaPlayer/1.0.200641.0 (Linux;Android 5.1.1)",
|
"ua": "AlexaWebMediaPlayer/1.0.200641.0 (Linux;Android 5.1.1)",
|
||||||
@@ -2781,6 +3051,15 @@
|
|||||||
"type": "smarttv"
|
"type": "smarttv"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"desc": "Gigaset Tablet",
|
||||||
|
"ua": "Mozilla/5.0 (Linux; Android 4.2.2; Gigaset QV830 Build/JDQ39) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
|
||||||
|
"expect": {
|
||||||
|
"vendor": "Gigaset",
|
||||||
|
"model": "QV830",
|
||||||
|
"type": "tablet"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"desc": "Amazon Fire 7",
|
"desc": "Amazon Fire 7",
|
||||||
"ua": "Mozilla/5.0 (Linux; Android 5.1.1; KFAUWI) AppleWebKit/537.36 (KHTML, like Gecko) Silk/80.5.3 like Chrome/80.0.3987.162 Safari/537.36",
|
"ua": "Mozilla/5.0 (Linux; Android 5.1.1; KFAUWI) AppleWebKit/537.36 (KHTML, like Gecko) Silk/80.5.3 like Chrome/80.0.3987.162 Safari/537.36",
|
||||||
@@ -2791,20 +3070,45 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"desc": "FaceBook Mobile App",
|
"desc": "AT&T Radiant Core U304AA",
|
||||||
"ua": "[FBAN/FBIOS;FBAV/283.0.0.44.117;FBBV/238386386;FBDV/iPhone12,1;FBMD/iPhone;FBSN/iOS;FBSV/13.6.1;FBSS/2;FBID/phone;FBLC/en_US;FBOP/5;FBRV/240127608]",
|
"ua": "Dalvik/2.1.0 (Linux; U; Android 9; U304AA Build/P00610)",
|
||||||
"expect": {
|
"expect": {
|
||||||
"vendor": "Apple",
|
"vendor": "AT&T",
|
||||||
"model": "iPhone12,1",
|
"model": "U304AA",
|
||||||
"type": "mobile"
|
"type": "mobile"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"desc": "Issue #519",
|
"desc": "Vodafone Smart Tab 4G",
|
||||||
"ua": "ios/iPhone/14.2/SOME_CUSTOM_APP_VERSION",
|
"ua": "Mozilla/5.0 (Linux; Android 4.4.4; Vodafone Smart Tab 4G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36",
|
||||||
|
"expect": {
|
||||||
|
"vendor": "Vodafone",
|
||||||
|
"model": "Smart Tab 4G",
|
||||||
|
"type": "tablet"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "Vodafone Smart ultra 6",
|
||||||
|
"ua": "Mozilla/5.0 (Linux; Android 5.0.2; Vodafone Smart ultra 6 Build/LRX22G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.133 Mobile Safari/537.36",
|
||||||
|
"expect": {
|
||||||
|
"vendor": "Vodafone",
|
||||||
|
"model": "Smart ultra 6",
|
||||||
|
"type": "tablet"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "4ife 4K Smart TV Box",
|
||||||
|
"ua": "Mozilla/5.0 (Linux; Android 4.4.2; 4ife 4K Smart TV Box Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Safari/537.36 Vinebre",
|
||||||
|
"expect": {
|
||||||
|
"vendor": "undefined",
|
||||||
|
"model": "undefined",
|
||||||
|
"type": "smarttv"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "FaceBook Mobile App",
|
||||||
|
"ua": "[FBAN/FBIOS;FBAV/283.0.0.44.117;FBBV/238386386;FBDV/iPhone12,1;FBMD/iPhone;FBSN/iOS;FBSV/13.6.1;FBSS/2;FBID/phone;FBLC/en_US;FBOP/5;FBRV/240127608]",
|
||||||
"expect": {
|
"expect": {
|
||||||
"vendor": "Apple",
|
|
||||||
"model": "iPhone",
|
|
||||||
"type": "mobile"
|
"type": "mobile"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -53,15 +53,6 @@
|
|||||||
"version" : "4.5.4"
|
"version" : "4.5.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"desc" : "LibWeb",
|
|
||||||
"ua" : "Mozilla/4.0 (SerenityOS; x86) LibWeb+LibJS (Not KHTML, nor Gecko) LibWeb",
|
|
||||||
"expect" :
|
|
||||||
{
|
|
||||||
"name" : "LibWeb",
|
|
||||||
"version" : "undefined"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"desc" : "NetFront",
|
"desc" : "NetFront",
|
||||||
"ua" : "Mozilla/4.0 (PDA; Windows CE/1.0.1) NetFront/3.0",
|
"ua" : "Mozilla/4.0 (PDA; Windows CE/1.0.1) NetFront/3.0",
|
||||||
|
|||||||
@@ -670,7 +670,7 @@
|
|||||||
"ua" : "Mozilla/5.0 (X11; CrOS x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.0.0 Safari/537.36",
|
"ua" : "Mozilla/5.0 (X11; CrOS x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.0.0 Safari/537.36",
|
||||||
"expect" :
|
"expect" :
|
||||||
{
|
{
|
||||||
"name" : "Chrome OS",
|
"name" : "Chromium OS",
|
||||||
"version" : "undefined"
|
"version" : "undefined"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -679,7 +679,7 @@
|
|||||||
"ua" : "Mozilla/5.0 (X11; CrOS x86_64 10575.58.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36",
|
"ua" : "Mozilla/5.0 (X11; CrOS x86_64 10575.58.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36",
|
||||||
"expect" :
|
"expect" :
|
||||||
{
|
{
|
||||||
"name" : "Chrome OS",
|
"name" : "Chromium OS",
|
||||||
"version" : "10575.58.0"
|
"version" : "10575.58.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -764,15 +764,6 @@
|
|||||||
"version" : "undefined"
|
"version" : "undefined"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"desc": "iOS with FaceBook Mobile App",
|
|
||||||
"ua": "[FBAN/FBIOS;FBAV/283.0.0.44.117;FBBV/238386386;FBDV/iPhone12,1;FBMD/iPhone;FBSN/iOS;FBSV/13.6.1;FBSS/2;FBID/phone;FBLC/en_US;FBOP/5;FBRV/240127608]",
|
|
||||||
"expect":
|
|
||||||
{
|
|
||||||
"name" : "iOS",
|
|
||||||
"version" : "13.6.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"desc" : "watchOS",
|
"desc" : "watchOS",
|
||||||
"ua" : "server-bag [Watch OS,8.4,19S546,Watch3,4]",
|
"ua" : "server-bag [Watch OS,8.4,19S546,Watch3,4]",
|
||||||
@@ -805,7 +796,7 @@
|
|||||||
"ua" : "Mozilla/4.0 (compatible; MSIE 5.0b1; Mac_PowerPC)",
|
"ua" : "Mozilla/4.0 (compatible; MSIE 5.0b1; Mac_PowerPC)",
|
||||||
"expect" :
|
"expect" :
|
||||||
{
|
{
|
||||||
"name" : "macOS",
|
"name" : "Mac OS",
|
||||||
"version" : "undefined"
|
"version" : "undefined"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -814,7 +805,7 @@
|
|||||||
"ua" : "Mozilla/5.0 (Macintosh; Intel Mac OS X x.y; rv:10.0) Gecko/20100101 Firefox/10.0",
|
"ua" : "Mozilla/5.0 (Macintosh; Intel Mac OS X x.y; rv:10.0) Gecko/20100101 Firefox/10.0",
|
||||||
"expect" :
|
"expect" :
|
||||||
{
|
{
|
||||||
"name" : "macOS",
|
"name" : "Mac OS",
|
||||||
"version" : "x.y"
|
"version" : "x.y"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -823,7 +814,7 @@
|
|||||||
"ua" : "Mozilla/5.0 (Macintosh; PPC Mac OS X x.y; rv:10.0) Gecko/20100101 Firefox/10.0",
|
"ua" : "Mozilla/5.0 (Macintosh; PPC Mac OS X x.y; rv:10.0) Gecko/20100101 Firefox/10.0",
|
||||||
"expect" :
|
"expect" :
|
||||||
{
|
{
|
||||||
"name" : "macOS",
|
"name" : "Mac OS",
|
||||||
"version" : "x.y"
|
"version" : "x.y"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -832,7 +823,7 @@
|
|||||||
"ua" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36",
|
"ua" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36",
|
||||||
"expect" :
|
"expect" :
|
||||||
{
|
{
|
||||||
"name" : "macOS",
|
"name" : "Mac OS",
|
||||||
"version" : "10.6.8"
|
"version" : "10.6.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -1204,14 +1195,5 @@
|
|||||||
"name" : "Linspire",
|
"name" : "Linspire",
|
||||||
"version" : "1.5.0.4"
|
"version" : "1.5.0.4"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc" : "SerenityOS",
|
|
||||||
"ua" : "Mozilla/4.0 (SerenityOS; x86) LibWeb+LibJS (Not KHTML, nor Gecko) LibWeb",
|
|
||||||
"expect" :
|
|
||||||
{
|
|
||||||
"name" : "SerenityOS",
|
|
||||||
"version" : "undefined"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
import { UAParser } from 'ua-parser-js';
|
|
||||||
import { CPUArch, DeviceType, EngineName } from 'ua-parser-js/enums';
|
|
||||||
import * as assert from 'assert';
|
|
||||||
|
|
||||||
describe('Returns', () => {
|
|
||||||
it('getResult() should returns object', () => {
|
|
||||||
assert.deepEqual(new UAParser('').getResult(),
|
|
||||||
{
|
|
||||||
ua : '',
|
|
||||||
//ua_ch : { architecture: undefined, bitness: undefined, brands: undefined, fullVersionList: undefined, mobile: false, model: undefined, platform: undefined, platformVersion: undefined },
|
|
||||||
browser: { name: undefined, version: undefined, major: undefined },
|
|
||||||
cpu: { architecture: undefined },
|
|
||||||
device: { vendor: undefined, model: undefined, type: undefined },
|
|
||||||
engine: { name: undefined, version: undefined},
|
|
||||||
os: { name: undefined, version: undefined }
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Enums', () => {
|
|
||||||
it('Can use enum', () => {
|
|
||||||
const { cpu, device, engine } = UAParser('Mozilla/5.0 (X11; U; Linux armv7l; en-GB; rv:1.9.2a1pre) Gecko/20090928 Firefox/3.5 Maemo Browser 1.4.1.22 RX-51 N900');
|
|
||||||
assert.strictEqual(cpu.is(CPUArch.ARM), true);
|
|
||||||
assert.strictEqual(device.is(DeviceType.MOBILE), true);
|
|
||||||
assert.strictEqual(engine.is(EngineName.GECKO), true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
const assert = require('assert');
|
|
||||||
const safeRegex = require('safe-regex');
|
|
||||||
const UAParser = require('ua-parser-js');
|
|
||||||
const { Bots, Emails, Tools } = require('ua-parser-js/extensions');
|
|
||||||
|
|
||||||
describe('Bots', () => {
|
|
||||||
it('Can detect bots', () => {
|
|
||||||
const googleBot = 'Googlebot-Video/1.0';
|
|
||||||
const msnBot = 'msnbot-media/1.1 (+http://search.msn.com/msnbot.htm)';
|
|
||||||
const bingPreview = 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534+ (KHTML, like Gecko) BingPreview/1.0b';
|
|
||||||
const opera = 'Opera/8.5 (Macintosh; PPC Mac OS X; U; en)';
|
|
||||||
const wget = 'Wget/1.21.1';
|
|
||||||
const facebookBot = 'Mozilla/5.0 (compatible; FacebookBot/1.0; +https://developers.facebook.com/docs/sharing/webmasters/facebookbot/)';
|
|
||||||
const outlook = 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; Microsoft Outlook 16.0.9126; Microsoft Outlook 16.0.9126; ms-office; MSOffice 16)';
|
|
||||||
const thunderbird = 'Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.13.0';
|
|
||||||
|
|
||||||
const botParser = new UAParser(Bots);
|
|
||||||
assert.deepEqual(botParser.setUA(googleBot).getBrowser(), {name: "Googlebot-Video", version: "1.0", major: "1", type: "bot"});
|
|
||||||
assert.deepEqual(botParser.setUA(msnBot).getBrowser(), {name: "msnbot-media", version: "1.1", major: "1", type: "bot"});
|
|
||||||
assert.deepEqual(botParser.setUA(bingPreview).getBrowser(), {name: "BingPreview", version: "1.0b", major: "1", type: "bot"});
|
|
||||||
assert.deepEqual(botParser.setUA(opera).getBrowser(), {name: "Opera", version: "8.5", major: "8"});
|
|
||||||
|
|
||||||
// try merging Bots & Tools
|
|
||||||
const botsAndTools = { browser : [...Bots.browser, ...Tools.browser]};
|
|
||||||
const botolParser = new UAParser(botsAndTools);
|
|
||||||
assert.deepEqual(botolParser.setUA(wget).getBrowser(), {name: "Wget", version: "1.21.1", major: "1", type:"tool"});
|
|
||||||
assert.deepEqual(botolParser.setUA(facebookBot).getBrowser(), {name: "FacebookBot", version: "1.0", major: "1", type:"bot"});
|
|
||||||
|
|
||||||
const emailParser = new UAParser(Emails);
|
|
||||||
assert.deepEqual(emailParser.setUA(outlook).getBrowser(), {name: "Microsoft Outlook", version: "16.0.9126", major: "16", type: "email"});
|
|
||||||
assert.deepEqual(emailParser.setUA(thunderbird).getBrowser(), {name: "Thunderbird", version: "78.13.0", major: "78", type: "email"});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// TODO : move test spec to JSON file
|
|
||||||
// TODO : check for safe-regex
|
|
||||||
@@ -1,342 +0,0 @@
|
|||||||
[{
|
|
||||||
"desc": "Essential PH-1",
|
|
||||||
"ua": "Mozilla/5.0 (Linux; Android 9; PH-1 Build/PPR1.180905.036) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.86 Mobile Safari/537.36",
|
|
||||||
"expect": {
|
|
||||||
"vendor": "Essential",
|
|
||||||
"model": "PH-1",
|
|
||||||
"type": "mobile"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc": "Gigaset Tablet",
|
|
||||||
"ua": "Mozilla/5.0 (Linux; Android 4.2.2; Gigaset QV830 Build/JDQ39) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
|
|
||||||
"expect": {
|
|
||||||
"vendor": "Gigaset",
|
|
||||||
"model": "QV830",
|
|
||||||
"type": "tablet"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc": "RCA Voyager III Tablet",
|
|
||||||
"ua": "Mozilla/5.0 (Linux; Android 6.0.1; RCT6973W43 Build/MMB29M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
|
|
||||||
"expect": {
|
|
||||||
"vendor": "RCA",
|
|
||||||
"model": "RCT6973W43",
|
|
||||||
"type": "tablet"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc": "RCA Voyager II Tablet",
|
|
||||||
"ua": "Mozilla/5.0 (Linux; Android 5.0; RCT6773W22B Build/LRX21M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
|
|
||||||
"expect": {
|
|
||||||
"vendor": "RCA",
|
|
||||||
"model": "RCT6773W22B",
|
|
||||||
"type": "tablet"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc": "Verizon Quanta Tablet",
|
|
||||||
"ua": "Mozilla/5.0 (Linux; Android 4.4.2; QMV7B Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
|
|
||||||
"expect": {
|
|
||||||
"vendor": "Verizon",
|
|
||||||
"model": "QMV7B",
|
|
||||||
"type": "tablet"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc": "Verizon Ellipsis 8 Tablet",
|
|
||||||
"ua": "Mozilla/5.0 (Linux; Android 5.1.1; QTAQZ3 Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
|
|
||||||
"expect": {
|
|
||||||
"vendor": "Verizon",
|
|
||||||
"model": "QTAQZ3",
|
|
||||||
"type": "tablet"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc": "Verizon Ellipsis 8HD Tablet",
|
|
||||||
"ua": "Mozilla/5.0 (Linux; Android 6.0.1; QTASUN1 Build/MMB29M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.81 Safari/537.36",
|
|
||||||
"expect": {
|
|
||||||
"vendor": "Verizon",
|
|
||||||
"model": "QTASUN1",
|
|
||||||
"type": "tablet"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc": "Dell Venue 8 Tablet",
|
|
||||||
"ua": "Mozilla/5.0 (Linux; Android 4.4.2; Venue 8 3830 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
|
|
||||||
"expect": {
|
|
||||||
"vendor": "Dell",
|
|
||||||
"model": "Venue 8 3830",
|
|
||||||
"type": "tablet"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc": "Dell Venue 7 Tablet",
|
|
||||||
"ua": "Mozilla/5.0 (Linux; Android 4.4.2; Venue 7 3730 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
|
|
||||||
"expect": {
|
|
||||||
"vendor": "Dell",
|
|
||||||
"model": "Venue 7 3730",
|
|
||||||
"type": "tablet"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc": "Barnes & Noble Nook HD+ Tablet",
|
|
||||||
"ua": "Mozilla/5.0 (Linux; U; Android 4.1.2; en-us; Barnes & Noble Nook HD+ Build/JZO54K; CyanogenMod-10) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30",
|
|
||||||
"expect": {
|
|
||||||
"vendor": "Barnes & Noble",
|
|
||||||
"model": "Nook HD+",
|
|
||||||
"type": "tablet"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc": "Barnes & Noble V400 Tablet",
|
|
||||||
"ua": "Mozilla/5.0 (Linux; Android 4.0.4; BNTV400 Build/IMM76L) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.111 Safari/537.36",
|
|
||||||
"expect": {
|
|
||||||
"vendor": "Barnes & Noble",
|
|
||||||
"model": "V400",
|
|
||||||
"type": "tablet"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc": "NuVision TM101A540N Tablet",
|
|
||||||
"ua": "Mozilla/5.0 (Linux; Android 5.1; TM101A540N Build/LMY47I; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/50.0.2661.86 Safari/537.36",
|
|
||||||
"expect": {
|
|
||||||
"vendor": "NuVision",
|
|
||||||
"model": "TM101A540N",
|
|
||||||
"type": "tablet"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc": "ZTE-Z431",
|
|
||||||
"ua": "ZTE-Z431/1.4.0 NetFront/4.2 QTV5.1 Profile/MIDP-2.1 Configuration/CLDC-1.1",
|
|
||||||
"expect": {
|
|
||||||
"vendor": "ZTE",
|
|
||||||
"model": "Z431",
|
|
||||||
"type": "mobile"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc": "ZTE",
|
|
||||||
"ua": "Mozilla/5.0 (Linux; U; Android 4.1.2; en-us; ZTE-Z740G Build/JZO54K) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30",
|
|
||||||
"expect": {
|
|
||||||
"vendor": "ZTE",
|
|
||||||
"model": "Z740G",
|
|
||||||
"type": "mobile"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc": "ZTE K Series Tablet",
|
|
||||||
"ua": "Mozilla/5.0 (Linux; Android 6.0.1; K88 Build/MMB29M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
|
|
||||||
"expect": {
|
|
||||||
"vendor": "ZTE",
|
|
||||||
"model": "K88",
|
|
||||||
"type": "tablet"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc": "ZTE Nubia Red Magic 3",
|
|
||||||
"ua": "Mozilla/5.0 (Linux; Android 9; NX629J Build/PKQ1.190321.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/45016 Mobile Safari/537.36 MMWEBID/4064 MicroMessenger/7.0.10.1580(0x27000A34) Process/tools NetType/WIFI Language/zh_CN ABI/arm64",
|
|
||||||
"expect": {
|
|
||||||
"vendor": "ZTE",
|
|
||||||
"model": "NX629J",
|
|
||||||
"type": "mobile"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc": "ZTE Blade A5",
|
|
||||||
"ua": "Mozilla/5.0 (Linux; Android 9; ZTE Blade A5 2019) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.116 Mobile Safari/537.36",
|
|
||||||
"expect": {
|
|
||||||
"vendor": "ZTE",
|
|
||||||
"model": "Blade A5 2019",
|
|
||||||
"type": "mobile"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc": "ZTE BLADE V0730",
|
|
||||||
"ua": "Mozilla/5.0 (Linux; Android 6.0; ZTE BLADE V0730) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.116 Mobile Safari/537.36",
|
|
||||||
"expect": {
|
|
||||||
"vendor": "ZTE",
|
|
||||||
"model": "BLADE V0730",
|
|
||||||
"type": "mobile"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc": "ZTE B2017G",
|
|
||||||
"ua": "Mozilla/5.0 (Linux; Android 7.1.1; ZTE B2017G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.93 Mobile Safari/537.36",
|
|
||||||
"expect": {
|
|
||||||
"vendor": "ZTE",
|
|
||||||
"model": "B2017G",
|
|
||||||
"type": "mobile"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc": "Swizz GEN610",
|
|
||||||
"ua": "Mozilla/5.0 (Linux; Android 4.4.2; GEN610 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.83 Mobile Safari/537.36",
|
|
||||||
"expect": {
|
|
||||||
"vendor": "Swiss",
|
|
||||||
"model": "GEN610",
|
|
||||||
"type": "mobile"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc": "Swizz ZUR700",
|
|
||||||
"ua": "Mozilla/5.0 (Linux; Android 4.4.2; ZUR700 Build/KVT49L) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.96 Safari/537.36",
|
|
||||||
"expect": {
|
|
||||||
"vendor": "Swiss",
|
|
||||||
"model": "ZUR700",
|
|
||||||
"type": "tablet"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc": "Zeki TB782b Tablet",
|
|
||||||
"ua": "Mozilla/5.0 (Linux; U; Android 4.0.4; en-US; TB782B Build/IMM76D) AppleWebKit/534.31 (KHTML, like Gecko) UCBrowser/9.0.2.299 U3/0.8.0 Mobile Safari/534.31",
|
|
||||||
"expect": {
|
|
||||||
"vendor": "Zeki",
|
|
||||||
"model": "TB782B",
|
|
||||||
"type": "tablet"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc": "Dragon Touch Tablet",
|
|
||||||
"ua": "Mozilla/5.0 (Linux; Android 4.0.4; DT9138B Build/IMM76D) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.72 Mobile Safari/537.36",
|
|
||||||
"expect": {
|
|
||||||
"vendor": "Dragon Touch",
|
|
||||||
"model": "9138B",
|
|
||||||
"type": "tablet"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc": "Insignia Tablet",
|
|
||||||
"ua": "Mozilla/5.0 (Linux; U; Android 6.0.1; NS-P08A7100 Build/MMB29M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/56.0.2924.87 Safari/537.36",
|
|
||||||
"expect": {
|
|
||||||
"vendor": "Insignia",
|
|
||||||
"model": "NS-P08A7100",
|
|
||||||
"type": "tablet"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc": "Voice Xtreme V75",
|
|
||||||
"ua": "Mozilla/5.0 (Linux; U; Android 4.2.1; en-us; V75 Build/JOP40D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30",
|
|
||||||
"expect": {
|
|
||||||
"vendor": "Voice",
|
|
||||||
"model": "V75",
|
|
||||||
"type": "mobile"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc": "LvTel V11",
|
|
||||||
"ua": "Mozilla/5.0 (Linux; Android 5.1.1; V11 Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/39.0.0.0 Safari/537.36",
|
|
||||||
"expect": {
|
|
||||||
"vendor": "LvTel",
|
|
||||||
"model": "V11",
|
|
||||||
"type": "mobile"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc": "Envizen Tablet V100MD",
|
|
||||||
"ua": "Mozilla/5.0 (Linux; U; Android 4.1.1; en-us; V100MD Build/V100MD.20130816) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30",
|
|
||||||
"expect": {
|
|
||||||
"vendor": "Envizen",
|
|
||||||
"model": "V100MD",
|
|
||||||
"type": "tablet"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc": "Rotor Tablet",
|
|
||||||
"ua": "mozilla/5.0 (linux; android 5.0.1; tu_1491 build/lrx22c) applewebkit/537.36 (khtml, like gecko) chrome/43.0.2357.93 safari/537.36",
|
|
||||||
"expect": {
|
|
||||||
"vendor": "Rotor",
|
|
||||||
"model": "1491",
|
|
||||||
"type": "tablet"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc": "MachSpeed Tablets",
|
|
||||||
"ua": "Mozilla/5.0 (Linux; Android 4.4.2; Trio 7.85 vQ Build/Trio_7.85_vQ) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Safari/537.36",
|
|
||||||
"expect": {
|
|
||||||
"vendor": "MachSpeed",
|
|
||||||
"model": "Trio 7.85 vQ",
|
|
||||||
"type": "tablet"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc": "Trinity Tablets",
|
|
||||||
"ua": "Mozilla/5.0 (Linux; Android 5.0.1; Trinity T101 Build/LRX22C) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.83 Safari/537.36",
|
|
||||||
"expect": {
|
|
||||||
"vendor": "Trinity",
|
|
||||||
"model": "T101",
|
|
||||||
"type": "tablet"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc": "NextBook Next7",
|
|
||||||
"ua": "Mozilla/5.0 (Linux; U; Android 4.0.4; en-us; Next7P12 Build/IMM76I) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30",
|
|
||||||
"expect": {
|
|
||||||
"vendor": "NextBook",
|
|
||||||
"model": "Next7P12",
|
|
||||||
"type": "tablet"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc": "NextBook Tablets",
|
|
||||||
"ua": "Mozilla/5.0 (Linux; Android 5.0; NXA8QC116 Build/LRX21V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
|
|
||||||
"expect": {
|
|
||||||
"vendor": "NextBook",
|
|
||||||
"model": "NXA8QC116",
|
|
||||||
"type": "tablet"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc": "Le Pan Tablets",
|
|
||||||
"ua": "Mozilla/5.0 (Linux; Android 4.2.2; Le Pan TC802A Build/JDQ39) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
|
|
||||||
"expect": {
|
|
||||||
"vendor": "Le Pan",
|
|
||||||
"model": "TC802A",
|
|
||||||
"type": "tablet"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc": "Le Pan Tablets",
|
|
||||||
"ua": "Mozilla/5.0 (Linux; Android 4.2.2; Le Pan TC802A Build/JDQ39) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
|
|
||||||
"expect": {
|
|
||||||
"vendor": "Le Pan",
|
|
||||||
"model": "TC802A",
|
|
||||||
"type": "tablet"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc": "AT&T Radiant Core U304AA",
|
|
||||||
"ua": "Dalvik/2.1.0 (Linux; U; Android 9; U304AA Build/P00610)",
|
|
||||||
"expect": {
|
|
||||||
"vendor": "AT&T",
|
|
||||||
"model": "U304AA",
|
|
||||||
"type": "mobile"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc": "Vodafone Smart Tab 4G",
|
|
||||||
"ua": "Mozilla/5.0 (Linux; Android 4.4.4; Vodafone Smart Tab 4G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36",
|
|
||||||
"expect": {
|
|
||||||
"vendor": "Vodafone",
|
|
||||||
"model": "Smart Tab 4G",
|
|
||||||
"type": "tablet"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc": "Vodafone Smart ultra 6",
|
|
||||||
"ua": "Mozilla/5.0 (Linux; Android 5.0.2; Vodafone Smart ultra 6 Build/LRX22G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.133 Mobile Safari/537.36",
|
|
||||||
"expect": {
|
|
||||||
"vendor": "Vodafone",
|
|
||||||
"model": "Smart ultra 6",
|
|
||||||
"type": "tablet"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"desc": "4ife 4K Smart TV Box",
|
|
||||||
"ua": "Mozilla/5.0 (Linux; Android 4.4.2; 4ife 4K Smart TV Box Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Safari/537.36 Vinebre",
|
|
||||||
"expect": {
|
|
||||||
"vendor": "undefined",
|
|
||||||
"model": "undefined",
|
|
||||||
"type": "smarttv"
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
418
test/test.js
418
test/test.js
@@ -45,7 +45,7 @@ var methods = [
|
|||||||
|
|
||||||
describe('UAParser()', function () {
|
describe('UAParser()', function () {
|
||||||
var ua = 'Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6';
|
var ua = 'Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6';
|
||||||
assert.deepEqual(UAParser(ua), new UAParser().setUA(ua).getResult());
|
assert.deepStrictEqual(UAParser(ua), new UAParser().setUA(ua).getResult());
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('UAParser() constructor does not throw with undefined ua argument', function () {
|
describe('UAParser() constructor does not throw with undefined ua argument', function () {
|
||||||
@@ -79,10 +79,9 @@ for (var i in methods) {
|
|||||||
|
|
||||||
describe('Returns', function () {
|
describe('Returns', function () {
|
||||||
it('getResult() should returns JSON', function(done) {
|
it('getResult() should returns JSON', function(done) {
|
||||||
assert.deepEqual(new UAParser('').getResult(),
|
assert.deepStrictEqual(new UAParser('').getResult(),
|
||||||
{
|
{
|
||||||
ua : '',
|
ua : '',
|
||||||
//ua_ch : { architecture: undefined, bitness: undefined, brands: undefined, fullVersionList: undefined, mobile: false, model: undefined, platform: undefined, platformVersion: undefined },
|
|
||||||
browser: { name: undefined, version: undefined, major: undefined },
|
browser: { name: undefined, version: undefined, major: undefined },
|
||||||
cpu: { architecture: undefined },
|
cpu: { architecture: undefined },
|
||||||
device: { vendor: undefined, model: undefined, type: undefined },
|
device: { vendor: undefined, model: undefined, type: undefined },
|
||||||
@@ -107,25 +106,6 @@ describe('Extending Regex', function () {
|
|||||||
parser2.setUA(uaString);
|
parser2.setUA(uaString);
|
||||||
assert.strictEqual(parser2.getBrowser().name, 'MyOwnBrowser');
|
assert.strictEqual(parser2.getBrowser().name, 'MyOwnBrowser');
|
||||||
assert.strictEqual(parser1.getBrowser().version, '1.3');
|
assert.strictEqual(parser1.getBrowser().version, '1.3');
|
||||||
|
|
||||||
let myOwnListOfBrowsers = [
|
|
||||||
[/(mybrowser)\/([\w\.]+)/i], [UAParser.BROWSER.NAME, UAParser.BROWSER.VERSION, ['type', 'bot']]
|
|
||||||
];
|
|
||||||
let myParser = new UAParser({ browser: myOwnListOfBrowsers });
|
|
||||||
let myUA = 'Mozilla/5.0 MyBrowser/1.3';
|
|
||||||
assert.deepEqual(myParser.setUA(myUA).getBrowser(), {name: "MyBrowser", version: "1.3", major: "1", type : "bot"});
|
|
||||||
assert.strictEqual(myParser.getBrowser().is('bot'), true);
|
|
||||||
|
|
||||||
let myOwnListOfDevices = [
|
|
||||||
[/(mytab) ([\w ]+)/i], [UAParser.DEVICE.VENDOR, UAParser.DEVICE.MODEL, [UAParser.DEVICE.TYPE, UAParser.DEVICE.TABLET]],
|
|
||||||
[/(myphone)/i], [UAParser.DEVICE.VENDOR, [UAParser.DEVICE.TYPE, UAParser.DEVICE.MOBILE]]
|
|
||||||
];
|
|
||||||
let myParser2 = new UAParser({
|
|
||||||
browser: myOwnListOfBrowsers,
|
|
||||||
device: myOwnListOfDevices
|
|
||||||
});
|
|
||||||
let myUA2 = 'Mozilla/5.0 MyTab 14 Pro Max';
|
|
||||||
assert.deepEqual(myParser2.setUA(myUA2).getDevice(), {vendor: "MyTab", model: "14 Pro Max", type: "tablet"});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('User-agent length', function () {
|
describe('User-agent length', function () {
|
||||||
@@ -186,397 +166,3 @@ describe('Testing regexes', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
describe('is() utility method', function () {
|
|
||||||
let uap = new UAParser('Mozilla/5.0 (Mobile; Windows Phone 8.1; Android 4.0; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 635) like iPhone OS 7_0_3 Mac OS X AppleWebKit/537 (KHTML, like Gecko) Mobile Safari/537');
|
|
||||||
|
|
||||||
it('Should match full name', function () {
|
|
||||||
assert.strictEqual(uap.getBrowser().name, "IEMobile");
|
|
||||||
assert.strictEqual(uap.getBrowser().is("IEMobile"), true);
|
|
||||||
assert.strictEqual(uap.getBrowser().is("IE"), false);
|
|
||||||
assert.strictEqual(uap.getBrowser().is("11.0"), false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Should ignore "Browser" suffix', function () {
|
|
||||||
assert.strictEqual(uap.getBrowser().is("IEMobile Browser"), true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Should ignore case', function () {
|
|
||||||
assert.strictEqual(uap.getEngine().name, "Trident");
|
|
||||||
assert.strictEqual(uap.getEngine().is("tRiDeNt"), true);
|
|
||||||
assert.strictEqual(uap.getEngine().is("7.0"), false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Should get exact name', function () {
|
|
||||||
assert.strictEqual(uap.getOS().name, "Windows Phone");
|
|
||||||
assert.strictEqual(uap.getOS().is("Windows Phone"), true);
|
|
||||||
assert.strictEqual(uap.getOS().is("Windows Phone OS"), true);
|
|
||||||
assert.strictEqual(uap.getOS().is("Windows Mobile"), false);
|
|
||||||
assert.strictEqual(uap.getOS().is("Android"), false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Should check all device properties', function () {
|
|
||||||
assert.deepEqual(uap.getDevice(), {
|
|
||||||
vendor : "Nokia",
|
|
||||||
model : "Lumia 635",
|
|
||||||
type : "mobile"
|
|
||||||
});
|
|
||||||
assert.strictEqual(uap.getDevice().is("Nokia"), true);
|
|
||||||
assert.strictEqual(uap.getDevice().is("Lumia 635"), true);
|
|
||||||
assert.strictEqual(uap.getDevice().is("mobile"), true);
|
|
||||||
|
|
||||||
assert.strictEqual(uap.getResult().device.is("Nokia"), true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Should get result after reassignment', function () {
|
|
||||||
uap.setUA("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36");
|
|
||||||
assert.strictEqual(uap.getOS().name, "macOS");
|
|
||||||
assert.strictEqual(uap.getOS().is("Mac OS"), true);
|
|
||||||
assert.strictEqual(uap.getOS().is("macOS"), true);
|
|
||||||
assert.strictEqual(uap.getOS().is("mac OS"), true);
|
|
||||||
|
|
||||||
assert.strictEqual(uap.getOS().is("M ac"), false);
|
|
||||||
assert.strictEqual(uap.getOS().is("M a c "), false);
|
|
||||||
assert.strictEqual(uap.getOS().is("Mac OS OS"), false);
|
|
||||||
assert.strictEqual(uap.getOS().is("Mac OS X"), false);
|
|
||||||
|
|
||||||
assert.strictEqual(uap.getBrowser().is("Chrome"), true);
|
|
||||||
assert.strictEqual(uap.getEngine().is("Blink"), true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Should refrain from "undefined" until all properties are checked', function () {
|
|
||||||
assert.strictEqual(uap.getDevice().is("undefined"), false);
|
|
||||||
assert.strictEqual(uap.getDevice().is("Apple"), true);
|
|
||||||
|
|
||||||
uap.setUA("");
|
|
||||||
assert.strictEqual(uap.getDevice().model, undefined);
|
|
||||||
assert.strictEqual(uap.getDevice().is("undefined"), false);
|
|
||||||
assert.strictEqual(uap.getDevice().is(undefined), true);
|
|
||||||
});
|
|
||||||
|
|
||||||
//it('Should accept arch equivalent name', function () {
|
|
||||||
it('Should accept exact arch name', function () {
|
|
||||||
uap.setUA("Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:19.0) Gecko/20100101 Firefox/19.0");
|
|
||||||
assert.strictEqual(uap.getCPU().architecture, "ia32");
|
|
||||||
assert.strictEqual(uap.getCPU().is("ia32"), true);
|
|
||||||
assert.strictEqual(uap.getCPU().is("x86"), false);
|
|
||||||
|
|
||||||
uap.setUA("Opera/9.80 (X11; Linux x86_64; U; Linux Mint; en) Presto/2.2.15 Version/10.10");
|
|
||||||
assert.strictEqual(uap.getCPU().architecture, "amd64");
|
|
||||||
assert.strictEqual(uap.getCPU().is("amd64"), true);
|
|
||||||
assert.strictEqual(uap.getCPU().is("x86-64"), false);
|
|
||||||
assert.strictEqual(uap.getCPU().is("x64"), false);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('toString() utility method', function () {
|
|
||||||
it('Should return full name', function () {
|
|
||||||
let uap = new UAParser('Mozilla/5.0 (Mobile; Windows Phone 8.1; Android 4.0; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 635) like iPhone OS 7_0_3 Mac OS X AppleWebKit/537 (KHTML, like Gecko) Mobile Safari/537');
|
|
||||||
assert.strictEqual(uap.getBrowser().name, "IEMobile");
|
|
||||||
assert.strictEqual(uap.getBrowser().version, "11.0");
|
|
||||||
assert.strictEqual(uap.getBrowser().major, "11");
|
|
||||||
assert.strictEqual(uap.getBrowser().toString(), "IEMobile 11.0");
|
|
||||||
|
|
||||||
assert.strictEqual(uap.getCPU().architecture, "arm");
|
|
||||||
assert.strictEqual(uap.getCPU().toString(), "arm");
|
|
||||||
|
|
||||||
assert.strictEqual(uap.getDevice().vendor, "Nokia");
|
|
||||||
assert.strictEqual(uap.getDevice().model, "Lumia 635");
|
|
||||||
assert.strictEqual(uap.getDevice().type, "mobile");
|
|
||||||
assert.strictEqual(uap.getDevice().toString(), "Nokia Lumia 635");
|
|
||||||
|
|
||||||
assert.strictEqual(uap.getEngine().name, "Trident");
|
|
||||||
assert.strictEqual(uap.getEngine().version, "7.0");
|
|
||||||
assert.strictEqual(uap.getEngine().toString(), "Trident 7.0");
|
|
||||||
|
|
||||||
assert.strictEqual(uap.getOS().name, "Windows Phone");
|
|
||||||
assert.strictEqual(uap.getOS().version, "8.1");
|
|
||||||
assert.strictEqual(uap.getOS().toString(), "Windows Phone 8.1");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Read user-agent data from req.headers', function () {
|
|
||||||
const ua = 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Win64; x64; Trident/6.0)';
|
|
||||||
const ext = {
|
|
||||||
engine : [
|
|
||||||
[/(msie)/i], [[UAParser.ENGINE.NAME, 'Custom Browser 1']],
|
|
||||||
[/(edge)/i], [[UAParser.ENGINE.NAME, 'Custom Browser 2']]
|
|
||||||
]
|
|
||||||
};
|
|
||||||
const req = {
|
|
||||||
headers : {
|
|
||||||
'user-agent' : 'Mozilla/5.0 (Windows NT 6.4; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.143 Safari/537.36 Edge/12.0'
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
it('Can be called with UAParser(ua)', function () {
|
|
||||||
let engine = UAParser(ua).engine;
|
|
||||||
assert.strictEqual(engine.name, "Trident");
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Can be called with UAParser(ua, extensions)', function () {
|
|
||||||
let engine = UAParser(ua, ext).engine;
|
|
||||||
assert.strictEqual(engine.name, "Custom Browser 1");
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Can be called with UAParser(ua, extensions, headers)', function () {
|
|
||||||
let engine = UAParser(ua, ext, req.headers).engine;
|
|
||||||
assert.strictEqual(engine.name, "Custom Browser 1");
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Can be called with UAParser(ua, headers)', function () {
|
|
||||||
let engine = UAParser(ua, req.headers).engine;
|
|
||||||
assert.strictEqual(engine.name, "Trident");
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Can be called with UAParser(extensions, headers)', function () {
|
|
||||||
let engine = UAParser(ext, req.headers).engine;
|
|
||||||
assert.strictEqual(engine.name, "Custom Browser 2");
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Can be called with UAParser(headers)', function () {
|
|
||||||
let engine = UAParser(req.headers).engine;
|
|
||||||
assert.strictEqual(engine.name, "EdgeHTML");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Map UA-CH headers', function () {
|
|
||||||
|
|
||||||
const headers = {
|
|
||||||
'sec-ch-ua' : '"Chromium";v="93", "Google Chrome";v="93", " Not;A Brand";v="99"',
|
|
||||||
'sec-ch-ua-full-version-list' : '"Chromium";v="93.0.1.2", "Google Chrome";v="93.0.1.2", " Not;A Brand";v="99.0.1.2"',
|
|
||||||
'sec-ch-ua-arch' : 'ARM',
|
|
||||||
'sec-ch-ua-bitness' : '64',
|
|
||||||
'sec-ch-ua-mobile' : '?1',
|
|
||||||
'sec-ch-ua-model' : 'Pixel 99',
|
|
||||||
'sec-ch-ua-platform' : 'Windows',
|
|
||||||
'sec-ch-ua-platform-version' : '13',
|
|
||||||
'user-agent' : 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36'
|
|
||||||
};
|
|
||||||
|
|
||||||
let uap = UAParser(headers).withClientHints();
|
|
||||||
let browser = new UAParser(headers).getBrowser().withClientHints();
|
|
||||||
let cpu = new UAParser(headers).getCPU().withClientHints();
|
|
||||||
let device = new UAParser(headers).getDevice().withClientHints();
|
|
||||||
let engine = new UAParser(headers).getEngine().withClientHints();
|
|
||||||
let os = new UAParser(headers).getOS().withClientHints();
|
|
||||||
|
|
||||||
/* let ua_ch = {
|
|
||||||
"architecture": "ARM",
|
|
||||||
"bitness": "64",
|
|
||||||
"brands": [
|
|
||||||
{
|
|
||||||
"brand": "Chromium",
|
|
||||||
"version": "93"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"brand": "Google Chrome",
|
|
||||||
"version": "93"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"brand": " Not;A Brand",
|
|
||||||
"version": "99"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"fullVersionList": [
|
|
||||||
{
|
|
||||||
"brand": "Chromium",
|
|
||||||
"version": "93.0.1.2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"brand": "Google Chrome",
|
|
||||||
"version": "93.0.1.2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"brand": " Not;A Brand",
|
|
||||||
"version": "99.0.1.2"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"mobile": true,
|
|
||||||
"model": "Pixel 99",
|
|
||||||
"platform": "Windows",
|
|
||||||
"platformVersion": "13"
|
|
||||||
};*/
|
|
||||||
|
|
||||||
it('Can read from client-hints headers using `withClientHints()`', function () {
|
|
||||||
|
|
||||||
//assert.deepEqual(uap.ua_ch, ua_ch);
|
|
||||||
assert.strictEqual(uap.ua, "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36");
|
|
||||||
assert.strictEqual(uap.browser.name, "Chrome");
|
|
||||||
assert.strictEqual(uap.browser.version, "93.0.1.2");
|
|
||||||
assert.strictEqual(uap.browser.major, "93");
|
|
||||||
assert.strictEqual(browser.name, "Chrome");
|
|
||||||
assert.strictEqual(browser.version, "93.0.1.2");
|
|
||||||
assert.strictEqual(browser.major, "93");
|
|
||||||
assert.strictEqual(uap.cpu.architecture, "arm64");
|
|
||||||
assert.strictEqual(cpu.architecture, "arm64");
|
|
||||||
assert.strictEqual(uap.device.type, "mobile");
|
|
||||||
assert.strictEqual(uap.device.model, "Pixel 99");
|
|
||||||
assert.strictEqual(uap.device.vendor, undefined);
|
|
||||||
assert.strictEqual(device.type, "mobile");
|
|
||||||
assert.strictEqual(device.model, "Pixel 99");
|
|
||||||
assert.strictEqual(device.vendor, undefined);
|
|
||||||
assert.strictEqual(uap.engine.name, 'Blink');
|
|
||||||
assert.strictEqual(uap.engine.version, '110.0.0.0');
|
|
||||||
assert.strictEqual(engine.name, 'Blink');
|
|
||||||
assert.strictEqual(engine.version, '110.0.0.0');
|
|
||||||
assert.strictEqual(uap.os.name, "Windows");
|
|
||||||
assert.strictEqual(uap.os.version, "11");
|
|
||||||
assert.strictEqual(os.name, "Windows");
|
|
||||||
assert.strictEqual(os.version, "11");
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Only read from user-agent header when called without `withClientHints()`', function () {
|
|
||||||
|
|
||||||
uap = UAParser(headers);
|
|
||||||
browser = new UAParser(headers).getBrowser();
|
|
||||||
cpu = new UAParser(headers).getCPU();
|
|
||||||
device = new UAParser(headers).getDevice();
|
|
||||||
engine = new UAParser(headers).getEngine();
|
|
||||||
os = new UAParser(headers).getOS();
|
|
||||||
|
|
||||||
//assert.deepEqual(uap.ua_ch, ua_ch);
|
|
||||||
assert.strictEqual(uap.browser.name, "Chrome");
|
|
||||||
assert.strictEqual(uap.browser.version, "110.0.0.0");
|
|
||||||
assert.strictEqual(uap.browser.major, "110");
|
|
||||||
assert.strictEqual(uap.cpu.architecture, "amd64");
|
|
||||||
assert.strictEqual(uap.device.type, undefined);
|
|
||||||
assert.strictEqual(uap.device.model, undefined);
|
|
||||||
assert.strictEqual(uap.device.vendor, undefined);
|
|
||||||
assert.strictEqual(uap.engine.name, 'Blink');
|
|
||||||
assert.strictEqual(uap.engine.version, '110.0.0.0');
|
|
||||||
assert.strictEqual(uap.os.name, "Linux");
|
|
||||||
assert.strictEqual(uap.os.version, "x86_64");
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Fallback to user-agent header when using `withClientHints()` but found no client hints-related headers', function () {
|
|
||||||
|
|
||||||
const headers2 = {
|
|
||||||
'sec-ch-ua-mobile' : '?1',
|
|
||||||
'user-agent' : 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36'
|
|
||||||
};
|
|
||||||
|
|
||||||
uap = UAParser(headers2).withClientHints();
|
|
||||||
|
|
||||||
/* ua_ch = {
|
|
||||||
"architecture": undefined,
|
|
||||||
"bitness": undefined,
|
|
||||||
"brands": undefined,
|
|
||||||
"fullVersionList": undefined,
|
|
||||||
"mobile": true,
|
|
||||||
"model": undefined,
|
|
||||||
"platform": undefined,
|
|
||||||
"platformVersion": undefined
|
|
||||||
};
|
|
||||||
|
|
||||||
assert.deepEqual(uap.ua_ch, ua_ch);*/
|
|
||||||
assert.strictEqual(uap.browser.name, "Chrome");
|
|
||||||
assert.strictEqual(uap.browser.version, "110.0.0.0");
|
|
||||||
assert.strictEqual(uap.browser.major, "110");
|
|
||||||
assert.strictEqual(uap.cpu.architecture, "amd64");
|
|
||||||
assert.strictEqual(uap.device.type, "mobile");
|
|
||||||
assert.strictEqual(uap.device.model, undefined);
|
|
||||||
assert.strictEqual(uap.device.vendor, undefined);
|
|
||||||
assert.strictEqual(uap.engine.name, 'Blink');
|
|
||||||
assert.strictEqual(uap.engine.version, '110.0.0.0');
|
|
||||||
assert.strictEqual(uap.os.name, "Linux");
|
|
||||||
assert.strictEqual(uap.os.version, "x86_64");
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Can detect Apple silicon from client hints data', function () {
|
|
||||||
|
|
||||||
// https://github.com/faisalman/ua-parser-js/issues/489#issuecomment-1479213579
|
|
||||||
const httpHeadersFromAppleSilicon = {
|
|
||||||
'sec-ch-ua-arch' : 'arm',
|
|
||||||
'sec-ch-ua-platform' : 'macOS',
|
|
||||||
'sec-ch-ua-mobile' : '?0',
|
|
||||||
'sec-ch-ua' : '"Google Chrome";v="111", "Not(A:Brand";v="8", "Chromium";v="111"',
|
|
||||||
'user-agent' : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:97.0) Gecko/20100101 Firefox/97.0'
|
|
||||||
};
|
|
||||||
|
|
||||||
UAParser(httpHeadersFromAppleSilicon).withClientHints().then(function (ua) {
|
|
||||||
|
|
||||||
// Only works in Chrome
|
|
||||||
/*
|
|
||||||
if (ua.os.is("macOS") &&
|
|
||||||
ua.cpu.is("arm") &&
|
|
||||||
!ua.device.is("mobile") &&
|
|
||||||
!ua.device.is("tablet")) {
|
|
||||||
// possibly an Apple silicon device
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
assert.strictEqual(ua.os.is("macOS"), true);
|
|
||||||
assert.strictEqual(ua.cpu.is("arm"), true);
|
|
||||||
assert.strictEqual(ua.device.is("mobile"), false);
|
|
||||||
assert.strictEqual(ua.device.is("tablet"), false);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Map UA-CH JS', () => {
|
|
||||||
|
|
||||||
it('does not throw when using withClientHints() in non-supported environment', () => {
|
|
||||||
assert.doesNotThrow(() => {
|
|
||||||
new UAParser().getResult().withClientHints();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
window = { navigator : { userAgent : '' , userAgentData : new NavigatorUAData() } };
|
|
||||||
function NavigatorUAData () {
|
|
||||||
this.mobile = false;
|
|
||||||
this.platform = '';
|
|
||||||
this.brands = [{ brand : 'A Chromium-based Browser', version : '1' }];
|
|
||||||
this.getHighEntropyValues = (values) => {
|
|
||||||
return new Promise((resolve) => {
|
|
||||||
const result = {
|
|
||||||
brands : [{ brand : 'A Chromium-based Browser', version : '1' }],
|
|
||||||
fullVersionList : [{ brand : 'A Chromium-based Browser', version : '1.2.3' }],
|
|
||||||
architecture : 'x86',
|
|
||||||
bitness : '64',
|
|
||||||
mobile : true,
|
|
||||||
model : 'Galaxy S3',
|
|
||||||
platform : 'Android',
|
|
||||||
platformVersion : '1000'
|
|
||||||
};
|
|
||||||
resolve(result);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
delete require.cache[require.resolve('./../src/ua-parser')];
|
|
||||||
const UAParserWithWindow = require('./../src/ua-parser');
|
|
||||||
|
|
||||||
it('Can read client hints from browser', async () => {
|
|
||||||
|
|
||||||
let uap = new UAParserWithWindow()
|
|
||||||
|
|
||||||
let os = await uap.getOS().withClientHints();
|
|
||||||
|
|
||||||
assert.strictEqual(os.name, 'Android');
|
|
||||||
assert.strictEqual(os.is('Android'), true);
|
|
||||||
assert.strictEqual(os.toString(), 'Android 1000');
|
|
||||||
|
|
||||||
let result = await uap.getResult().withClientHints();
|
|
||||||
|
|
||||||
assert.strictEqual(result.browser.name, 'A Chromium-based Browser');
|
|
||||||
assert.strictEqual(result.browser.version, '1.2.3');
|
|
||||||
assert.strictEqual(result.cpu.architecture, 'amd64');
|
|
||||||
assert.strictEqual(result.os.name, 'Android');
|
|
||||||
|
|
||||||
await uap.getDevice().withClientHints().then((device) => {
|
|
||||||
assert.strictEqual(device.type, 'mobile');
|
|
||||||
assert.strictEqual(device.vendor, undefined);
|
|
||||||
assert.strictEqual(device.model, 'Galaxy S3');
|
|
||||||
});
|
|
||||||
|
|
||||||
let result_without_ch = uap.getResult();
|
|
||||||
|
|
||||||
assert.strictEqual(result_without_ch.browser.name, undefined);
|
|
||||||
|
|
||||||
uap.setUA("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36");
|
|
||||||
assert.strictEqual(uap.getOS().name, "macOS");
|
|
||||||
|
|
||||||
// TODO : create full tests
|
|
||||||
});
|
|
||||||
});
|
|
||||||
Reference in New Issue
Block a user