mirror of
https://github.com/faisalman/ua-parser-js.git
synced 2025-11-15 14:42:16 +03:00
Compare commits
96 Commits
2.0.0-alph
...
2.0.0-beta
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
99d59f7e4c | ||
|
|
768b622603 | ||
|
|
5328642e18 | ||
|
|
bdcd927304 | ||
|
|
db3423a76c | ||
|
|
173325faa1 | ||
|
|
5190905df8 | ||
|
|
0a46ac396a | ||
|
|
f7810dbfcf | ||
|
|
0543b87c02 | ||
|
|
39590f112d | ||
|
|
1a22c6951f | ||
|
|
8991d34e56 | ||
|
|
1a2ef00509 | ||
|
|
12c2c2e48a | ||
|
|
85bf7076d3 | ||
|
|
1fa3d02594 | ||
|
|
4cd867a36e | ||
|
|
6b6fcc68f5 | ||
|
|
760e85bbe7 | ||
|
|
5a8ce35054 | ||
|
|
150d3c6b4a | ||
|
|
e87c794fd9 | ||
|
|
d0db40c290 | ||
|
|
8dce4cc514 | ||
|
|
a43d659577 | ||
|
|
b29a9a7ffb | ||
|
|
6f02da06e0 | ||
|
|
4d950db145 | ||
|
|
b5b5475ab4 | ||
|
|
7c22bc587f | ||
|
|
d6d8ac7cb4 | ||
|
|
54c633aac5 | ||
|
|
9c5d6ee70e | ||
|
|
b5c62b0c82 | ||
|
|
0c49d75074 | ||
|
|
09904a0a47 | ||
|
|
3622b614a7 | ||
|
|
e4f2463849 | ||
|
|
fdbeabbaed | ||
|
|
2046fe5209 | ||
|
|
5173a5442f | ||
|
|
106d882fba | ||
|
|
7abc8b9ecc | ||
|
|
7ad3e3b451 | ||
|
|
26f7e7d59e | ||
|
|
f8f71c65d4 | ||
|
|
17f0c1e1cd | ||
|
|
9cc274fb6f | ||
|
|
f56073bb3e | ||
|
|
5c10e2b107 | ||
|
|
46ff3df974 | ||
|
|
cfc01470b5 | ||
|
|
d565f65280 | ||
|
|
69ed6cec77 | ||
|
|
b51ae9eb38 | ||
|
|
125f0d9f16 | ||
|
|
e614108911 | ||
|
|
77e0aa1ac6 | ||
|
|
119515edd2 | ||
|
|
c8c6d121e0 | ||
|
|
e6a085f710 | ||
|
|
37c61736c3 | ||
|
|
177a496c34 | ||
|
|
ac282df13e | ||
|
|
5a0d9cc3d0 | ||
|
|
f6fbf170e3 | ||
|
|
a9247154e0 | ||
|
|
f57f8fa1a7 | ||
|
|
8fea17f296 | ||
|
|
a4b4e8a2c2 | ||
|
|
954ce35755 | ||
|
|
ea4f145e64 | ||
|
|
91d2d2c0e8 | ||
|
|
b5546ee39f | ||
|
|
b3f4321bb6 | ||
|
|
aa76da90d9 | ||
|
|
817c5835ef | ||
|
|
6ea6936632 | ||
|
|
9b182526fa | ||
|
|
f17d2d7664 | ||
|
|
9652169da0 | ||
|
|
bf1d7267f6 | ||
|
|
5226361348 | ||
|
|
385e0aaee5 | ||
|
|
a661ab61d5 | ||
|
|
647e115a1e | ||
|
|
05a98aceda | ||
|
|
807dcdbded | ||
|
|
1522691426 | ||
|
|
f538018f8e | ||
|
|
3f105fe93b | ||
|
|
129657673b | ||
|
|
3dd4b60ee9 | ||
|
|
73a936001a | ||
|
|
2046b77ede |
5
.github/ISSUE_TEMPLATE/bug_report.md
vendored
5
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -7,6 +7,11 @@ assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Library version**
|
||||
Which version of the library that you use, eg: v0.7.35 or v2.0.0-alpha.3
|
||||
|
||||
For the issue related with detection result, you can use the demo section in https://uaparser.js.org to confirm
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
|
||||
10
.github/ISSUE_TEMPLATE/custom.md
vendored
10
.github/ISSUE_TEMPLATE/custom.md
vendored
@@ -1,10 +0,0 @@
|
||||
---
|
||||
name: Custom issue template
|
||||
about: Describe this issue template's purpose here.
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
|
||||
1
.github/PULL_REQUEST_TEMPLATE/pull_request_template.md
vendored
Normal file
1
.github/PULL_REQUEST_TEMPLATE/pull_request_template.md
vendored
Normal file
@@ -0,0 +1 @@
|
||||
- [ ] I have read and accept the [Contributor License Agreement (CLA)](https://gist.github.com/faisalman/2ed16621ebb544157eba85a7f7381417) Document and I hereby sign the CLA
|
||||
@@ -2,30 +2,66 @@
|
||||
|
||||
# Version 2.0
|
||||
- What's breaking:
|
||||
- Dual-licensed under AGPLv3 or PRO License
|
||||
- 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()`
|
||||
- Add support for feature detection: `withFeatureCheck()`
|
||||
- Some new methods in result object:
|
||||
- Support for client hints: `withClientHints()`
|
||||
- Support for feature detection: `withFeatureCheck()`
|
||||
- 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'`
|
||||
- Provide Helpers `'ua-parser-js/helpers'`
|
||||
- Support for ES module `import { UAParser } from 'ua-parser-js'`
|
||||
- Provided Enums submodule `'ua-parser-js/enums'`
|
||||
- Provided Extensions submodule `'ua-parser-js/extensions'`
|
||||
- Provided Helpers submodule `'ua-parser-js/helpers'`
|
||||
|
||||
## Version 2.0.0-beta.3
|
||||
|
||||
- Breaking:
|
||||
- AR/VR devices moved to new device type: `xr`
|
||||
- New property in `browser`: `type`
|
||||
- In `ua-parser-js/extensions` submodule, `bots` divided into `crawler` / `fetcher`
|
||||
- New features:
|
||||
- Parse directly from command line using `npx ua-parser-js`
|
||||
- Extensions can be passed as a list to `UAParser()`
|
||||
- Add new browser: Pico Browser, Twitter, Wolvic
|
||||
- Improve browser detection: DuckDuckGo, ICEBrowser, Klar, QQ, Sleipnir
|
||||
- Improve device detection: Oculus Quest & Oppo Pad
|
||||
- Update latest client hints spec: `formFactor` -> `formFactors`
|
||||
|
||||
## Version 2.0.0-beta.2
|
||||
|
||||
- Increase UA_MAX_LENGTH to 500
|
||||
- Add TypeScript declaration file in `ua-parser-js/extensions` submodule
|
||||
- Improve TypeScript module resolution
|
||||
- Add new methods in `ua-parser-js/helpers` submodule: `isAppleSilicon()` & `isChromiumBased()`
|
||||
- Fix misidentified WebView token as device model
|
||||
- Add new browser: Alipay, Klarna, Opera GX, Smart Lenovo Browser, Vivo Browser
|
||||
- Rename browser: Avant, Baidu, Samsung Internet, Sogou Explorer, Sogou Mobile, WeChat
|
||||
- Improve client-hints detection: Edge, Xbox
|
||||
|
||||
## Version 2.0.0-beta.1
|
||||
|
||||
- Update Client Hints Form-Factor
|
||||
- Provide in-package type definitions
|
||||
- Add new device: Ulefone
|
||||
- Improve device detection: Realme, Xiaomi Redmi
|
||||
|
||||
## Version 2.0.0-alpha.3
|
||||
|
||||
- Add `withFeatureCheck()` method
|
||||
- Add `isFrozenUA()` method in `helpers` submodule
|
||||
- Add `MediaPlayers` & `Modules` in `extensions` submodule
|
||||
- Add `isFrozenUA()` method in `ua-parser-js/helpers` submodule
|
||||
- Add `MediaPlayers` & `Modules` in `ua-parser-js/extensions` submodule
|
||||
- Fix issue with ESM import
|
||||
|
||||
## 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
|
||||
|
||||
- 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
|
||||
|
||||
|
||||
@@ -33,6 +69,21 @@
|
||||
|
||||
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.37
|
||||
|
||||
- Fix misidentified WebView token as device model
|
||||
- Increase UA_MAX_LENGTH to 500
|
||||
- Add new browser: Alipay, Klarna, Smart Lenovo Browser, Vivo Browser
|
||||
- Add new device: Ulefone
|
||||
- Improve device detection: Realme, Xiaomi Redmi
|
||||
- Rename browser: Avant, Baidu, Samsung Internet, Sogou Explorer, Sogou Mobile, WeChat
|
||||
|
||||
## Version 0.7.36 / 1.0.36
|
||||
- Add new browser: Snapchat
|
||||
- Add new devices: Infinix, Tecno
|
||||
- Improve device detection: Amazon Fire TV, Xiaomi POCO
|
||||
- Improve OS detection: iOS
|
||||
|
||||
## Version 0.7.35 / 1.0.35
|
||||
- Fix result from user-supplied user-agent being altered
|
||||
- Add new browser: Heytap, TikTok
|
||||
29
CODE_OF_CONDUCT.md
Normal file
29
CODE_OF_CONDUCT.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# UAParser.js Code of Conduct
|
||||
|
||||
## Introduction
|
||||
|
||||
Welcome to the UAParser.js community! We're here to collaborate on developing an awesome project. Here are some general guidelines to make our community a great place:
|
||||
|
||||
### 1. Be Kind, Honest, and Respectful
|
||||
|
||||
Always treat others with kindness and respect. We value different opinions and encourage positive communication.
|
||||
|
||||
### 2. Keep Conversations Civil and On-Topic
|
||||
|
||||
Please keep discussions related to the project. If you want to talk about something else, find the right place for it.
|
||||
|
||||
### 3. Mutual Assistance, Appreciation, and Acknowledgement
|
||||
|
||||
Feel free to ask for help, show gratitude for contributions, and make sure to give credit where it's due.
|
||||
|
||||
### 4. Resolving Disagreements
|
||||
|
||||
In the event of a disagreement, we encourage open and respectful dialogue. It's important to remember that it's okay to have differing opinions, and if a common ground can't be reached, we suggest using the 'agree to disagree' approach.
|
||||
|
||||
## Reporting Issues
|
||||
|
||||
If you see any behavior that goes against this code of conduct, report it to [f@faisalman.com](mailto:f@faisalman.com).
|
||||
|
||||
## Conclusion
|
||||
|
||||
Together, we can make this project awesome!
|
||||
7
CONTRIBUTING.md
Normal file
7
CONTRIBUTING.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# UAParser.js: How to Contribute
|
||||
|
||||
* Fork and clone this repository
|
||||
* Make some changes as required
|
||||
* Write unit test to showcase its functionality under `/test`
|
||||
* Run the test suites to make sure it's not breaking anything `$ npm run build+test`
|
||||
* Submit a pull request under `develop` branch & check the CLA in the submission form
|
||||
73
LICENSE.md
Normal file
73
LICENSE.md
Normal file
@@ -0,0 +1,73 @@
|
||||
# UAPARSER.JS PRO PERSONAL LICENSE
|
||||
|
||||
Version 2, July 2024
|
||||
|
||||
Copyright (C) 2023-2024 Faisal Salman <f+ua-parser-js@faisalman.com>
|
||||
|
||||
---
|
||||
|
||||
## Definitions
|
||||
|
||||
"We" are the team behind UAParser.js.
|
||||
|
||||
"You" are the individual who is responsible for purchasing this license.
|
||||
|
||||
"The Code" is UAParser.js.
|
||||
|
||||
"Project" is what you built with The Code.
|
||||
|
||||
---
|
||||
|
||||
## License
|
||||
|
||||
We retain all title, intellectual property, and ownership rights to The Code.
|
||||
|
||||
The Code is licensed, not sold, to You for use solely subject to the terms and conditions detailed here.
|
||||
|
||||
We grant You (and only You) a personal, limited, non-exclusive, non-transferable, non-sublicensable, royalty-free right to use, copy, and modify The Code.
|
||||
|
||||
This license is only valid for You as one (1) individual and cannot be transferred to another individual or organization.
|
||||
|
||||
---
|
||||
|
||||
## Rights
|
||||
|
||||
You may use and modify The Code to create as many personal, hobby, educational, and other non-profit projects as you want for yourself.
|
||||
|
||||
You may create any number of copies of The Code for yourself.
|
||||
|
||||
You have the right to get lifetime updates and one (1) year of support, starting from the time you make the purchase.
|
||||
|
||||
---
|
||||
|
||||
## Restrictions
|
||||
|
||||
You may not use or modify The Code in such a way that it may be used directly for commercial purposes.
|
||||
|
||||
You may not redistribute The Code, as-is or modified, except as a part of a Project that you made for yourself.
|
||||
|
||||
You may not deliver a Project that contains The Code as an open-source Project that might be used for commercial purposes by the general public, except with our written consent.
|
||||
|
||||
You may not use The Code for unlawful, inappropriate, illegal, or offensive purposes.
|
||||
|
||||
---
|
||||
|
||||
## Limitations
|
||||
|
||||
The Code is provided 'as is' without warranty of any kind, expressed or implied.
|
||||
|
||||
We shall not be liable for any damages, including but not limited to, direct, indirect, special, incidental, or consequential damages or losses that occur by the use of The Code.
|
||||
|
||||
We reserve the right to discontinue the lifetime updates for The Code at any time, with or without notice.
|
||||
|
||||
We offer support only for questions within the scope of The Code's functionality or related issues at our sole discretion.
|
||||
|
||||
---
|
||||
|
||||
## Termination
|
||||
|
||||
This license is effective indefinitely but can be revoked at any time if there is a violation of any of the terms.
|
||||
|
||||
---
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
22
PULL_REQUEST_TEMPLATE.md
Normal file
22
PULL_REQUEST_TEMPLATE.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# Prerequisites
|
||||
|
||||
- [ ] I have read and follow the contributing guidelines
|
||||
- [ ] I have read and accept the [Contributor License Agreement (CLA)](https://gist.github.com/faisalman/2ed16621ebb544157eba85a7f7381417) Document and I hereby sign the CLA
|
||||
|
||||
# Type of Change
|
||||
|
||||
Bug fix, feature, docs update, ...
|
||||
|
||||
# Description
|
||||
|
||||
Please include a summary of the change (current behavior vs new behavior), which issue is fixed (you can also link to an open issue here), and why this change is necessary.
|
||||
|
||||
# Test
|
||||
|
||||
Please describe the tests that you ran to verify your changes.
|
||||
|
||||
# Impact
|
||||
|
||||
Does this PR introduce a breaking change? What changes might users need to make due to this PR?
|
||||
|
||||
# Other Info
|
||||
23
README.md
Normal file
23
README.md
Normal file
@@ -0,0 +1,23 @@
|
||||
<p align="center">
|
||||
<a href="https://uaparser.dev"><img src="https://raw.githubusercontent.com/faisalman/ua-parser-js/gh-pages/images/uap-header.png"></a>
|
||||
</p>
|
||||
|
||||
# UAParser.js
|
||||
|
||||
Thank you for purchasing UAParser.js PRO Personal License, if you haven't please oreder here: https://store.faisalman.com
|
||||
|
||||
# Download
|
||||
|
||||
```sh
|
||||
npm install @ua-parser-js/pro-personal
|
||||
```
|
||||
|
||||
# Documentation
|
||||
|
||||
https://docs.uaparser.dev
|
||||
|
||||
# License
|
||||
|
||||
UAParser.js PRO Personal
|
||||
|
||||
Copyright (c) 2012-2024 Faisal Salman <<f@faisalman.com>>
|
||||
17
bower.json
17
bower.json
@@ -1,17 +0,0 @@
|
||||
{
|
||||
"name": "ua-parser-js",
|
||||
"version": "2.0.0-alpha.3",
|
||||
"authors": [
|
||||
"Faisal Salman <f@faisalman.com>"
|
||||
],
|
||||
"private": false,
|
||||
"main": "src/ua-parser.js",
|
||||
"ignore": [
|
||||
"build",
|
||||
"node_modules",
|
||||
"bower_components",
|
||||
"test",
|
||||
"tests"
|
||||
],
|
||||
"dependencies": {}
|
||||
}
|
||||
8
dist/ua-parser.min.js
vendored
8
dist/ua-parser.min.js
vendored
File diff suppressed because one or more lines are too long
8
dist/ua-parser.pack.js
vendored
8
dist/ua-parser.pack.js
vendored
File diff suppressed because one or more lines are too long
21
license.md
21
license.md
@@ -1,21 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2012-2023 Faisal Salman <<f@faisalman.com>>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
1497
package-lock.json
generated
1497
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
name: 'faisalman:ua-parser-js',
|
||||
version: '2.0.0-alpha.3',
|
||||
version: '2.0.0-beta.3',
|
||||
summary: 'Lightweight JavaScript-based user-agent string parser',
|
||||
git: 'https://github.com/faisalman/ua-parser-js.git',
|
||||
documentation: 'readme.md'
|
||||
|
||||
63
package.json
Normal file → Executable file
63
package.json
Normal file → Executable file
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"title": "UAParser.js",
|
||||
"name": "ua-parser-js",
|
||||
"version": "2.0.0-alpha.3",
|
||||
"title": "UAParser.js PRO Personal",
|
||||
"name": "@ua-parser-js/pro-personal",
|
||||
"version": "2.0.0-beta.3",
|
||||
"author": "Faisal Salman <f@faisalman.com> (http://faisalman.com)",
|
||||
"description": "Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent & Client Hints data. Supports browser & node.js environment",
|
||||
"keywords": [
|
||||
@@ -14,7 +14,12 @@
|
||||
"device",
|
||||
"cpu",
|
||||
"jquery-plugin",
|
||||
"ecosystem:jquery"
|
||||
"ecosystem:jquery",
|
||||
"ua-parser-js",
|
||||
"browser-detection",
|
||||
"device-detection",
|
||||
"os-detection",
|
||||
"bot-detection"
|
||||
],
|
||||
"homepage": "https://github.com/faisalman/ua-parser-js",
|
||||
"contributors": [
|
||||
@@ -35,8 +40,11 @@
|
||||
"Carl C Von Lewin <carlchristianlewin@gmail.com>",
|
||||
"CESAR RAMOS <c@imagenproactiva.com>",
|
||||
"Chad Killingsworth <ckillingsworth@jackhenry.com>",
|
||||
"chenhui9279 <chenhui9279@autohome.com.cn>",
|
||||
"chenyuan-new <53860479+chenyuan-new@users.noreply.github.com>",
|
||||
"Christopher De Cairos <chris.decairos@gmail.com>",
|
||||
"Cyrille David <cyrille@qonto.eu>",
|
||||
"Dante <duanjl.china@gmail.com>",
|
||||
"Dario Vladovic <d.vladimyr@gmail.com>",
|
||||
"David Annez <david.annez@gmail.com>",
|
||||
"Davit Barbakadze <jayarjo@gmail.com>",
|
||||
@@ -59,10 +67,12 @@
|
||||
"Faisal Salman <f@faisalman.com>",
|
||||
"Frédéric Camblor <fcamblor@gmail.com>",
|
||||
"Frederik Ring <frederik.ring@gmail.com>",
|
||||
"Garrit Franke <garrit@slashdev.space>",
|
||||
"Gerald Host <me@jacobford.co.uk>",
|
||||
"Germán M. Bravo <german.mb@gmail.com>",
|
||||
"Grigory Dmitrenko <grigory@snsk.ru>",
|
||||
"gulpin <gulping.gulpin@gmail.com>",
|
||||
"Hans Ott <hansott@hotmail.be>",
|
||||
"Hendrik Helwich <h.helwich@iplabs.de>",
|
||||
"Hermann Ebert <ebbmo@HE.local>",
|
||||
"hr6r <hedian@gmail.com>",
|
||||
@@ -70,6 +80,7 @@
|
||||
"Ildar Kamalov <i.kamalov@adguard.com>",
|
||||
"insanehong <insane.hong@navercorp.com>",
|
||||
"jackpoll <jackpoll123456@gmail.com>",
|
||||
"Jacky Choo <jackychoo@adly-macbook.local>",
|
||||
"Jake Mc <startswithaj@users.noreply.github.com>",
|
||||
"JBYoshi <12983479+JBYoshi@users.noreply.github.com>",
|
||||
"Joey Parrish <joeyparrish@google.com>",
|
||||
@@ -79,11 +90,14 @@
|
||||
"Josh Goldberg <joshuakgoldberg@outlook.com>",
|
||||
"Junki-Ishida <junki_ishida@dwango.co.jp>",
|
||||
"Kendall Buchanan <kendall@kendagriff.com>",
|
||||
"KnifeLemon <role___play@naver.com>",
|
||||
"kNoAPP <alldoneb@gmail.com>",
|
||||
"Lee Treveil <leetreveil@gmail.com>",
|
||||
"leonardo <leofiore@libero.it>",
|
||||
"Levente Balogh <balogh.levente.hu@gmail.com>",
|
||||
"Liam Quinn <lquinn@blackberry.com>",
|
||||
"Lithin <lithin@webklipper.com>",
|
||||
"liujunlve <liujunlve@henhaoji.com>",
|
||||
"ll-syber <670159357@qq.com>",
|
||||
"Loris Guignard <loris.guignard@gmail.com>",
|
||||
"Lukas Drgon <lukas.drgon@gmail.com>",
|
||||
@@ -98,6 +112,8 @@
|
||||
"Max Nordlund <max.nordlund@gmail.com>",
|
||||
"Michael Hess <mhess@connectify.me>",
|
||||
"MimyyK <michele.marais@hakisa.com>",
|
||||
"Mok <mok@moekm.com>",
|
||||
"nabetama <mao.nabeta@gmail.com>",
|
||||
"naoh <naoh.cs03g@nctu.edu.tw>",
|
||||
"Nicholas Ionata <nionata@ufl.edu>",
|
||||
"Nikhil Motiani <nikhil.motiani@outlook.com>",
|
||||
@@ -106,7 +122,9 @@
|
||||
"niris <nirisix@gmail.com>",
|
||||
"Nobuo Okada <nookada@yahoo-corp.jp>",
|
||||
"o.drapeza <o.drapeza@tinkoff.ru>",
|
||||
"Oscar Becerra <oscarbecerra@google.com>",
|
||||
"otakuSiD <otakusid@gmail.com>",
|
||||
"Paris Morgan <paris@8thwall.com>",
|
||||
"patrick-nurt <github@pereira.dk>",
|
||||
"Pavel Studeny <studeny@avast.com>",
|
||||
"Peter Dave Hello <PeterDaveHello@users.noreply.github.com>",
|
||||
@@ -116,19 +134,24 @@
|
||||
"Queen Vinyl Darkscratch <vinyldarkscratch@gmail.com>",
|
||||
"Raine Makelainen <raine.makelainen@jolla.com>",
|
||||
"Raman Savaryn <homeneartheocean@gmail.com>",
|
||||
"Riley Shaw <rileyjshaw@users.noreply.github.com>",
|
||||
"Robert Tod <robert@qubit.com>",
|
||||
"roman.savarin <roman.savarin@skywindgroup.com>",
|
||||
"Ron Korland <ron@testim.io>",
|
||||
"Ross Noble <rosshnoble@gmail.com>",
|
||||
"ruicong <466403866@qq.com>",
|
||||
"Runar Heggset <rukki093@gmail.com>",
|
||||
"Ryohei Shima <shima01dev@gmail.com>",
|
||||
"Sandro Sonntag <sandro.sonntag@adorsys.de>",
|
||||
"sgautrea <shanegautreau@gmail.com>",
|
||||
"shaharmor <shahar@peer5.com>",
|
||||
"Shane Gautreau <sgautrea@opentext.com>",
|
||||
"Shane Thacker <shane@steadymade.com>",
|
||||
"Shreedhar <shreedhar@uber.com>",
|
||||
"Simon Eisenmann <simon@longsleep.org>",
|
||||
"Simon Lang <me@simonlang.org>",
|
||||
"Stiekel <histkc@gmail.com>",
|
||||
"sunny-mwx <30586210+sunny-mwx@users.noreply.github.com>",
|
||||
"sUP <dani3l@gmail.com>",
|
||||
"Sylvain Gizard <sylvain.gizard@gmail.com>",
|
||||
"szchenghuang <szchenghuang@gmail.com>",
|
||||
@@ -136,19 +159,24 @@
|
||||
"Tony Tomarchio <tony@tomarchio.cc>",
|
||||
"Ulrich Schmidt <u.schmidt@velian.de>",
|
||||
"Vadim Kurachevsky <vadim@hmvs.org>",
|
||||
"Varun Sharma <varunsh@stepsecurity.io>",
|
||||
"XhmikosR <xhmikosr@gmail.com>",
|
||||
"Yılmaz <yilmazdemir36@gmail.com>",
|
||||
"yuanyang <work_yuanyang@163.com>",
|
||||
"Yun Young-jin <yupmin@yupmin-office-macmini.local>",
|
||||
"Zach Bjornson <zbbjornson@gmail.com>"
|
||||
"Zach Bjornson <zbbjornson@gmail.com>",
|
||||
"Ziding Zhang <zidingz@gmail.com>"
|
||||
],
|
||||
"type": "commonjs",
|
||||
"types": "src/main/ua-parser.d.ts",
|
||||
"main": "src/main/ua-parser.js",
|
||||
"module": "src/main/ua-parser.mjs",
|
||||
"browser": "dist/ua-parser.pack.js",
|
||||
"exports": {
|
||||
".": {
|
||||
"require": "./src/main/ua-parser.js",
|
||||
"import": "./src/main/ua-parser.mjs"
|
||||
"import": "./src/main/ua-parser.mjs",
|
||||
"types": "./src/main/ua-parser.d.ts"
|
||||
},
|
||||
"./enums": {
|
||||
"require": "./src/enums/ua-parser-enums.js",
|
||||
@@ -156,42 +184,49 @@
|
||||
},
|
||||
"./extensions": {
|
||||
"require": "./src/extensions/ua-parser-extensions.js",
|
||||
"import": "./src/extensions/ua-parser-extensions.mjs"
|
||||
"import": "./src/extensions/ua-parser-extensions.mjs",
|
||||
"types": "./src/extensions/ua-parser-extensions.d.ts"
|
||||
},
|
||||
"./helpers": {
|
||||
"require": "./src/helpers/ua-parser-helpers.js",
|
||||
"import": "./src/helpers/ua-parser-helpers.mjs"
|
||||
"import": "./src/helpers/ua-parser-helpers.mjs",
|
||||
"types": "./src/helpers/ua-parser-helpers.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"src"
|
||||
],
|
||||
"bin": "./script/cli.js",
|
||||
"scripts": {
|
||||
"build": "./script/build-dist.sh && ./script/build-module.js",
|
||||
"build+test": "npm run build && npm run test",
|
||||
"fuzz": "jazzer ./test/jazzer-fuzz-test.js --sync",
|
||||
"test": "./script/test-all.sh",
|
||||
"test:jshint": "jshint src && jshint script",
|
||||
"test:dts-lint": "tsd --typings src/main/ua-parser.d.ts --files test/dts-test.ts",
|
||||
"test:eslint": "eslint src && eslint script",
|
||||
"test:jshint": "jshint src/main",
|
||||
"test:lockfile-lint": "npx lockfile-lint -p package-lock.json",
|
||||
"test:mocha": "mocha -R list test/mocha*js",
|
||||
"test:mocha": "mocha test/mocha*js",
|
||||
"test:playwright": "playwright test"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/parser": "7.15.8",
|
||||
"@babel/traverse": "7.15.4",
|
||||
"@babel/traverse": "7.23.2",
|
||||
"@jazzer.js/core": "^1.4.0",
|
||||
"@playwright/test": "~1.32.2",
|
||||
"jshint": "~2.13.6",
|
||||
"mocha": "~8.2.0",
|
||||
"requirejs": "2.3.2",
|
||||
"safe-regex": "^2.1.1",
|
||||
"tsd": "^0.29.0",
|
||||
"uglify-js": "~3.12.0"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/faisalman/ua-parser-js.git"
|
||||
},
|
||||
"license": "MIT",
|
||||
"license": "UAParser.js-PRO-Personal",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
@@ -202,8 +237,8 @@
|
||||
"test": "test"
|
||||
},
|
||||
"bugs": "https://github.com/faisalman/ua-parser-js/issues",
|
||||
"demo": "https://faisalman.github.io/ua-parser-js",
|
||||
"download": "https://raw.github.com/faisalman/ua-parser-js/master/dist/ua-parser.min.js",
|
||||
"demo": "https://uaparser.js.org",
|
||||
"download": "https://raw.github.com/faisalman/ua-parser-js/master/dist/ua-parser.pack.js",
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
|
||||
653
readme.md
653
readme.md
@@ -1,653 +0,0 @@
|
||||
<p align="center">
|
||||
<img src="https://raw.githubusercontent.com/faisalman/ua-parser-js/gh-pages/images/logo.png" width="256" height="256">
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://www.npmjs.com/package/ua-parser-js"><img src="https://img.shields.io/npm/dw/ua-parser-js?color=red&logo=npm&label=NPM%20DOWNLOADS&style=for-the-badge"></a>
|
||||
<a href="https://www.jsdelivr.com/package/npm/ua-parser-js"><img src="https://img.shields.io/jsdelivr/gh/hw/faisalman/ua-parser-js?logo=jsdelivr&style=for-the-badge"></a>
|
||||
<a href="https://github.com/faisalman/ua-parser-js"><img src="https://img.shields.io/github/stars/faisalman/ua-parser-js?color=yellow&logo=github&style=for-the-badge"></a>
|
||||
<a href="https://bundlephobia.com/package/ua-parser-js@1.0.35"><img src="https://img.shields.io/bundlephobia/minzip/ua-parser-js?logo=hackthebox&logoColor=white&style=for-the-badge"/></a>
|
||||
<a href="https://github.com/faisalman/ua-parser-js/graphs/contributors"><img src="https://img.shields.io/github/contributors/faisalman/ua-parser-js?color=purple&logo=githubsponsors&style=for-the-badge"></a>
|
||||
<a href="https://www.npmjs.com/package/ua-parser-js"><img src="https://img.shields.io/npm/v/ua-parser-js.svg?logo=npm&color=red&style=for-the-badge"></a>
|
||||
<a href="https://cdnjs.com/libraries/UAParser.js"><img src="https://img.shields.io/cdnjs/v/UAParser.js.svg?color=orange&style=for-the-badge"></a>
|
||||
<img src="https://img.shields.io/ossf-scorecard/github.com/faisalman/ua-parser-js?label=openssf%20scorecard&style=for-the-badge">
|
||||
</p>
|
||||
|
||||
# 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).
|
||||
|
||||
* Author : Faisal Salman <<f@faisalman.com>>
|
||||
* Demo : https://faisalman.github.io/ua-parser-js
|
||||
* Source : https://github.com/faisalman/ua-parser-js
|
||||
* Documentation :
|
||||
* v1 : https://github.com/faisalman/ua-parser-js/tree/1.0.35#documentation
|
||||
* v2 : https://faisalman.github.io/ua-parser-js-docs/v2
|
||||
|
||||
***
|
||||
|
||||
### From Our Sponsors:
|
||||
<table>
|
||||
<thead>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<a href="https://opencollective.com/ua-parser-js">↗ Become a sponsor</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
---
|
||||
|
||||
# Version 2.0
|
||||
What's new & breaking, please read [CHANGELOG](changelog.md) before upgrading.
|
||||
|
||||
# Documentation
|
||||
### `UAParser([user-agent:string][,extensions:object][,headers:object(since@2.0)]):IData`
|
||||
|
||||
In browser environment you don't need to pass the user-agent string to the function, as it should automatically get the string from the `window.navigator.userAgent`. Whereas in nodejs environment, the user-agent string must be passed in order for the function to work (usually you can find the user-agent in: `request.headers["user-agent"]`).
|
||||
|
||||
## Constructor
|
||||
|
||||
#### * `new UAParser([user-agent:string][,extensions:object][,headers:object(since@2.0)]):UAParser`
|
||||
|
||||
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:
|
||||
|
||||
```js
|
||||
let parser = new UAParser("your user-agent here"); // you need to pass the user-agent for nodejs
|
||||
console.log(parser); // {}
|
||||
let parserResults = parser.getResult();
|
||||
console.log(parserResults);
|
||||
/*
|
||||
{
|
||||
ua : "",
|
||||
browser : {},
|
||||
engine : {},
|
||||
os : {},
|
||||
device : {},
|
||||
cpu : {}
|
||||
}
|
||||
*/
|
||||
```
|
||||
|
||||
#### * `UAParser([user-agent:string][,extensions:object][,headers:object(since@2.0)]):IData`
|
||||
|
||||
When you call `UAParser` without the `new` keyword, it will automatically call `getResult()` function and return the parsed results.
|
||||
|
||||
```sh
|
||||
returns result object `{ ua: '', browser: {}, cpu: {}, device: {}, engine: {}, os: {} }`
|
||||
```
|
||||
|
||||
## `UAParser`:
|
||||
|
||||
#### Methods table
|
||||
The methods are self explanatory, here's a small overview on all the available methods:
|
||||
* `getResult()` - returns all function object calls, user-agent string, browser info, cpu, device, engine, os:
|
||||
`{ ua: '', browser: {}, cpu: {}, device: {}, engine: {}, os: {} }`.
|
||||
|
||||
* `getBrowser()` - returns the browser name and version.
|
||||
* `getDevice()` - returns the device model, type, vendor.
|
||||
* `getEngine()` - returns the current browser engine name and version.
|
||||
* `getOS()` - returns the running operating system name and version.
|
||||
* `getCPU()` - returns CPU architectural design name.
|
||||
* `getUA()` - returns the user-agent string.
|
||||
* `setUA(ua)` - set a custom user-agent to be parsed.
|
||||
|
||||
---
|
||||
|
||||
#### * `getResult():IData`
|
||||
|
||||
```sh
|
||||
returns `{ ua: '', browser: {}, cpu: {}, device: {}, engine: {}, os: {} }`
|
||||
```
|
||||
|
||||
#### * `getBrowser():IData`
|
||||
|
||||
```sh
|
||||
returns `{ name: '', version: '' }`
|
||||
|
||||
# Possible 'browser.name':
|
||||
2345Explorer, 360 Browser, Amaya, Android Browser, Arora, Avant, Avast, AVG,
|
||||
BIDUBrowser, Baidu, Basilisk, Blazer, Bolt, Brave, Bowser, Camino, Chimera,
|
||||
[Mobile] Chrome [Headless/WebView], Chromium, Cobalt, Comodo Dragon, Dillo,
|
||||
Dolphin, Doris, DuckDuckGo, Edge, Electron, Epiphany, Facebook, Falkon, Fennec,
|
||||
Firebird, [Mobile] Firefox [Focus/Reality], Flock, Flow, GSA, GoBrowser, HeyTap,
|
||||
Huawei Browser, ICE Browser, IE, IEMobile, IceApe, IceCat, IceDragon, Iceweasel,
|
||||
Instagram, Iridium, Iron, Jasmine, Kakao[Story/Talk], K-Meleon, Kindle, Klar,
|
||||
Konqueror, LBBROWSER, Line, LinkedIn, Links, Lunascape, Lynx, MIUI Browser,
|
||||
Maemo Browser, Maemo, Maxthon, MetaSr Midori, Minimo, Mosaic, Mozilla, NetFront,
|
||||
NetSurf, Netfront, Netscape, NokiaBrowser, Obigo, Oculus Browser, OmniWeb,
|
||||
Opera Coast, Opera [Mini/Mobi/Tablet], PaleMoon, PhantomJS, Phoenix, Polaris,
|
||||
Puffin, QQ, QQBrowser, QQBrowserLite, Quark, QupZilla, RockMelt, [Mobile] Safari,
|
||||
Sailfish Browser, Samsung Browser, SeaMonkey, Silk, Skyfire, Sleipnir, Slim,
|
||||
SlimBrowser, Snapchat, Swiftfox, Tesla, TikTok, Tizen Browser, UCBrowser,
|
||||
UP.Browser, Viera, Vivaldi, Waterfox, WeChat, Weibo, Yandex, baidu, iCab, w3m,
|
||||
Whale Browser, ...
|
||||
|
||||
# 'browser.version' determined dynamically
|
||||
```
|
||||
|
||||
#### * `getDevice():IData`
|
||||
|
||||
```sh
|
||||
returns `{ model: '', type: '', vendor: '' }`
|
||||
|
||||
# Possible 'device.type':
|
||||
console, mobile, tablet, smarttv, wearable, embedded
|
||||
|
||||
##########
|
||||
# NOTE: 'desktop' is not a possible device type.
|
||||
# UAParser only reports info directly available from the UA string, which is not the case for 'desktop' device type.
|
||||
# If you wish to detect desktop devices, you must handle the needed logic yourself.
|
||||
# You can read more about it in this issue: https://github.com/faisalman/ua-parser-js/issues/182
|
||||
##########
|
||||
|
||||
# Possible 'device.vendor':
|
||||
Acer, Alcatel, Amazon, Apple, Archos, ASUS, AT&T, BenQ, BlackBerry, Dell,
|
||||
Essential, Facebook, Fairphone, GeeksPhone, Google, HP, HTC, Huawei, Infinix, Jolla,
|
||||
Kobo, Lenovo, LG, Meizu, Microsoft, Motorola, Nexian, Nintendo, Nokia, Nvidia,
|
||||
OnePlus, OPPO, Ouya, Palm, Panasonic, Pebble, Polytron, Realme, RIM, Roku, Samsung,
|
||||
Sharp, Siemens, Sony[Ericsson], Sprint, Tecno, Tesla, Vivo, Vodafone, Xbox, Xiaomi,
|
||||
Zebra, ZTE, ...
|
||||
|
||||
# 'device.model' determined dynamically
|
||||
```
|
||||
|
||||
#### * `getEngine():IData`
|
||||
|
||||
```sh
|
||||
returns `{ name: '', version: '' }`
|
||||
|
||||
# Possible 'engine.name'
|
||||
Amaya, Blink, EdgeHTML, Flow, Gecko, Goanna, iCab, KHTML, LibWeb, Links, Lynx,
|
||||
NetFront, NetSurf, Presto, Tasman, Trident, w3m, WebKit
|
||||
|
||||
# 'engine.version' determined dynamically
|
||||
```
|
||||
|
||||
#### * `getOS():IData`
|
||||
|
||||
```sh
|
||||
returns `{ name: '', version: '' }`
|
||||
|
||||
# Possible 'os.name'
|
||||
AIX, Amiga OS, Android[-x86], Arch, Bada, BeOS, BlackBerry, CentOS, Chromium OS,
|
||||
Contiki, Fedora, Firefox OS, FreeBSD, Debian, Deepin, DragonFly, elementary OS,
|
||||
Fuchsia, Gentoo, GhostBSD, GNU, Haiku, HarmonyOS, HP-UX, Hurd, iOS, Joli, KaiOS,
|
||||
Linpus, Linspire,Linux, Mac OS, Maemo, Mageia, Mandriva, Manjaro, MeeGo, Minix,
|
||||
Mint, Morph OS, NetBSD, NetRange, NetTV, Nintendo, OpenBSD, OpenVMS, OS/2, Palm,
|
||||
PC-BSD, PCLinuxOS, Plan9, PlayStation, QNX, Raspbian, RedHat, RIM Tablet OS,
|
||||
RISC OS, Sabayon, Sailfish, SerenityOS, Series40, Slackware, Solaris, SUSE, Symbian,
|
||||
Tizen, Ubuntu, Unix, VectorLinux, Viera, watchOS, WebOS, Windows [Phone/Mobile],
|
||||
Zenwalk, ...
|
||||
|
||||
# 'os.version' determined dynamically
|
||||
```
|
||||
|
||||
#### * `getCPU():IData`
|
||||
|
||||
```sh
|
||||
returns `{ architecture: '' }`
|
||||
|
||||
# Possible 'cpu.architecture'
|
||||
68k, amd64, arm[64/hf], avr, ia[32/64], irix[64], mips[64], pa-risc, ppc, sparc[64]
|
||||
```
|
||||
|
||||
#### * `getUA():string`
|
||||
|
||||
```sh
|
||||
returns user-agent string of current instance
|
||||
```
|
||||
|
||||
#### * `setUA(ua:string):UAParser`
|
||||
|
||||
```sh
|
||||
set user-agent string to be parsed
|
||||
returns current instance
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## `IData`: `since@2.0`
|
||||
|
||||
#### Methods table
|
||||
The methods are self explanatory, here's a small overview on all the available methods:
|
||||
* `is(value)` - returns `true` if the passed value matches a value of current object, `false` otherwise
|
||||
* `toString()` - returns the full-name values of current object as a string
|
||||
* `withClientHints()` - returns an object with re-updated data from client hints
|
||||
* `withFeatureCheck()` - returns an object with re-updated data from feature detection
|
||||
|
||||
---
|
||||
|
||||
#### * `is(value:string):boolean`
|
||||
|
||||
```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`
|
||||
|
||||
```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<IData>|Thenable<IData>|IData`
|
||||
|
||||
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
|
||||
});
|
||||
```
|
||||
|
||||
#### * `withFeatureCheck():IData`
|
||||
|
||||
This method allows us to examine other features beyond `navigator.userAgent` to further improve detection of the following:
|
||||
- browser : Brave (check for `navigator.isBrave`)
|
||||
- device : iPad (check for `navigator.standalone` & `navigator.maxTouchPoints`)
|
||||
|
||||
```js
|
||||
// suppose this code runs on iPad
|
||||
const withoutFeatureCheck = UAParser();
|
||||
const withFeatureCheck = UAParser().withFeatureCheck();
|
||||
|
||||
console.log(withoutFeatureCheck.device); // { vendor : "Apple", model : "Macintosh", type : undefined }
|
||||
console.log(withFeatureCheck.device); // { vendor : "Apple", model : "iPad", type : "tablet" }
|
||||
```
|
||||
|
||||
## 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
|
||||
|
||||
## Using HTML
|
||||
|
||||
```html
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<script src="ua-parser.min.js"></script>
|
||||
<script>
|
||||
|
||||
var uap = new UAParser();
|
||||
console.log(uap.getResult());
|
||||
/*
|
||||
/// This will print an object structured like this:
|
||||
{
|
||||
ua: "",
|
||||
browser: {
|
||||
name: "",
|
||||
version: "",
|
||||
major: ""
|
||||
},
|
||||
engine: {
|
||||
name: "",
|
||||
version: ""
|
||||
},
|
||||
os: {
|
||||
name: "",
|
||||
version: ""
|
||||
},
|
||||
device: {
|
||||
model: "",
|
||||
type: "",
|
||||
vendor: ""
|
||||
},
|
||||
cpu: {
|
||||
architecture: ""
|
||||
}
|
||||
}
|
||||
*/
|
||||
// Default result depends on current window.navigator.userAgent value
|
||||
|
||||
// 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";
|
||||
uap.setUA(uastring1);
|
||||
var result = uap.getResult();
|
||||
// You can also use UAParser constructor directly without having to create an instance:
|
||||
// var ua = UAParser(uastring1);
|
||||
|
||||
console.log(result.browser); // {name: "Chromium", version: "15.0.874.106"}
|
||||
console.log(result.device); // {model: undefined, type: undefined, vendor: undefined}
|
||||
console.log(result.os); // {name: "Ubuntu", version: "11.10"}
|
||||
console.log(result.os.version); // "11.10"
|
||||
console.log(result.engine.name); // "WebKit"
|
||||
console.log(result.cpu.architecture); // "amd64"
|
||||
|
||||
// Do some other tests
|
||||
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(uap.getOS()); // {name: "OpenBSD", version: undefined}
|
||||
console.log(uap.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';
|
||||
console.log(uap.setUA(uastring3).getDevice().model); // "PlayBook"
|
||||
console.log(uap.getOS()) // {name: "RIM Tablet OS", version: "1.0.0"}
|
||||
console.log(uap.getBrowser().name); // "Safari"
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
## Using node.js
|
||||
|
||||
Note: Device information is not available in the NodeJS environment.
|
||||
|
||||
```sh
|
||||
$ npm install ua-parser-js
|
||||
```
|
||||
|
||||
```js
|
||||
var http = require('http');
|
||||
var uap = require('ua-parser-js');
|
||||
|
||||
http.createServer(function (req, res) {
|
||||
// get user-agent header
|
||||
var ua = uap(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
|
||||
res.end(JSON.stringify(ua, null, ' '));
|
||||
})
|
||||
.listen(1337, '127.0.0.1');
|
||||
|
||||
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
|
||||
|
||||
```sh
|
||||
$ npm install --save @types/ua-parser-js
|
||||
# Download TS type definition from DefinitelyTyped repository:
|
||||
# https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/ua-parser-js
|
||||
```
|
||||
|
||||
## Using jQuery/Zepto ($.ua)
|
||||
|
||||
Although written in vanilla js, this library will automatically detect if jQuery/Zepto is present and create `$.ua` object (with values based on its User-Agent) along with `window.UAParser` constructor. To get/set user-agent you can use: `$.ua.get()` / `$.ua.set(uastring)`.
|
||||
|
||||
```js
|
||||
// Say we are in a browser with default user-agent: 'Mozilla/5.0 (Linux; U; Android 2.3.4; en-us; Sprint APA7373KT Build/GRJ22) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0':
|
||||
|
||||
// Get the details
|
||||
console.log($.ua.device); // {vendor: "HTC", model: "Evo Shift 4G", type: "mobile"}
|
||||
console.log($.ua.os); // {name: "Android", version: "2.3.4"}
|
||||
console.log($.ua.os.name); // "Android"
|
||||
console.log($.ua.get()); // "Mozilla/5.0 (Linux; U; Android 2.3.4; en-us; Sprint APA7373KT Build/GRJ22) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0"
|
||||
|
||||
// Now lets try to reset to another custom user-agent
|
||||
$.ua.set('Mozilla/5.0 (Linux; U; Android 3.0.1; en-us; Xoom Build/HWI69) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13');
|
||||
|
||||
// Test again
|
||||
console.log($.ua.browser.name); // "Safari"
|
||||
console.log($.ua.engine.name); // "Webkit"
|
||||
console.log($.ua.device); // {vendor: "Motorola", model: "Xoom", type: "tablet"}
|
||||
console.log(parseInt($.ua.browser.version.split('.')[0], 10)); // 4
|
||||
|
||||
// Add class to <body> tag
|
||||
// <body class="ua-browser-safari ua-devicetype-tablet">
|
||||
$('body').addClass('ua-browser-' + $.ua.browser.name + ' ua-devicetype-' + $.ua.device.type);
|
||||
```
|
||||
|
||||
# Development
|
||||
|
||||
## Backers & Sponsors
|
||||
|
||||
<a href="https://opencollective.com/ua-parser-js"><img src="https://opencollective.com/ua-parser-js/organizations.svg?avatarHeight=64"></a>
|
||||
<a href="https://opencollective.com/ua-parser-js"><img src="https://opencollective.com/ua-parser-js/individuals.svg?avatarHeight=64"></a>
|
||||
|
||||
<a href="https://www.paypal.me/faisalman/"><img src="https://cdn.rawgit.com/twolfson/paypal-github-button/1.0.0/dist/button.svg" height="40"></a>
|
||||
|
||||
## Contributors
|
||||
|
||||
<a href="https://github.com/faisalman/ua-parser-js/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=faisalman/ua-parser-js" />
|
||||
</a>
|
||||
|
||||
Made with [contributors-img](https://contrib.rocks).
|
||||
|
||||
## How To Contribute
|
||||
|
||||
* Fork and clone this repository
|
||||
* Make some changes as required
|
||||
* Write unit test to showcase its functionality
|
||||
* Run the test suites to make sure it's not breaking anything `$ npm test`
|
||||
* Submit a pull request under `develop` branch
|
||||
|
||||
# License
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2012-2023 Faisal Salman <<f@faisalman.com>>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -1,57 +1,58 @@
|
||||
#!/usr/bin/env node
|
||||
/* jshint esversion: 6 */
|
||||
const fs = require('fs');
|
||||
const PATH = {
|
||||
main : {
|
||||
src : 'src/main/ua-parser.js',
|
||||
dest : 'src/main/ua-parser.mjs',
|
||||
title : ''
|
||||
},
|
||||
enums : {
|
||||
src : 'src/enums/ua-parser-enums.js',
|
||||
dest :'src/enums/ua-parser-enums.mjs',
|
||||
title : 'enums'
|
||||
},
|
||||
extensions : {
|
||||
src : 'src/extensions/ua-parser-extensions.js',
|
||||
dest : 'src/extensions/ua-parser-extensions.mjs',
|
||||
title : 'extensions'
|
||||
},
|
||||
helpers : {
|
||||
src : 'src/helpers/ua-parser-helpers.js',
|
||||
dest : 'src/helpers/ua-parser-helpers.mjs',
|
||||
title : 'helpers'
|
||||
}
|
||||
};
|
||||
const generateMJS = (module, replacers) => {
|
||||
const { src, dest, title } = PATH[module];
|
||||
|
||||
const generateMJS = (module) => {
|
||||
let { src, dest, title, replacements } = module;
|
||||
let text = fs.readFileSync(src, 'utf-8');
|
||||
replacers.forEach(replacer => {
|
||||
text = text.replace(replacer[0], replacer[1]);
|
||||
|
||||
replacements.push(
|
||||
[/const (.+?)\s*=\s*require\((.+)\)/ig, 'import $1 from $2'],
|
||||
[/module\.exports =/ig, 'export']
|
||||
);
|
||||
replacements.forEach(rep => {
|
||||
text = text.replace(rep[0], rep[1]);
|
||||
});
|
||||
|
||||
console.log(`Generate ${dest}`);
|
||||
|
||||
fs.writeFileSync(dest,
|
||||
`// Generated ESM version of UAParser.js ${title}
|
||||
`// Generated ESM version of ${title}
|
||||
// DO NOT EDIT THIS FILE!
|
||||
// Source: /${src}
|
||||
|
||||
${text}`, 'utf-8');
|
||||
|
||||
};
|
||||
|
||||
// ua-parser.mjs
|
||||
generateMJS('main', [
|
||||
[/\(func[\s\S]+strict\';/ig, ''],
|
||||
[/esversion\: 3/ig, 'esversion: 6'],
|
||||
[/\/[\/\s]+export[\s\S]+/ig,'export {UAParser};']
|
||||
]);
|
||||
const modules = [
|
||||
{
|
||||
src : 'src/main/ua-parser.js',
|
||||
dest : 'src/main/ua-parser.mjs',
|
||||
title : 'ua-parser-js',
|
||||
replacements : [
|
||||
[/\(func[\s\S]+strict\';/ig, ''],
|
||||
[/esversion\: 3/ig, 'esversion: 6'],
|
||||
[/\/[\/\s]+export[\s\S]+/ig,'export {UAParser};']
|
||||
]
|
||||
},{
|
||||
src : 'src/enums/ua-parser-enums.js',
|
||||
dest :'src/enums/ua-parser-enums.mjs',
|
||||
title : 'ua-parser-js/enums',
|
||||
replacements : []
|
||||
},
|
||||
{
|
||||
src : 'src/extensions/ua-parser-extensions.js',
|
||||
dest : 'src/extensions/ua-parser-extensions.mjs',
|
||||
title : 'ua-parser-js/extensions',
|
||||
replacements : []
|
||||
},
|
||||
{
|
||||
src : 'src/helpers/ua-parser-helpers.js',
|
||||
dest : 'src/helpers/ua-parser-helpers.mjs',
|
||||
title : 'ua-parser-js/helpers',
|
||||
replacements : []
|
||||
}
|
||||
];
|
||||
|
||||
// ua-parser-enum.mjs
|
||||
generateMJS('enums', [[/module\.exports =/ig, 'export']]);
|
||||
|
||||
// ua-parser-extension.mjs
|
||||
generateMJS('extensions', [[/module\.exports =/ig, 'export']]);
|
||||
|
||||
// ua-parser-helpers.mjs
|
||||
generateMJS('helpers', [[/module\.exports =/ig, 'export']]);
|
||||
modules.forEach(module => generateMJS(module));
|
||||
4
script/cli.js
Executable file
4
script/cli.js
Executable file
@@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const UAParser = require('ua-parser-js');
|
||||
console.log(JSON.stringify(process.argv.slice(2).map(ua => UAParser(ua)), null, 4));
|
||||
@@ -9,6 +9,7 @@ echo '
|
||||
- lint js code
|
||||
'
|
||||
npm run test:jshint || exit 1
|
||||
#npm run test:eslint || exit 1
|
||||
|
||||
echo '
|
||||
- test using mocha
|
||||
@@ -23,4 +24,9 @@ npm run test:playwright || exit 1
|
||||
echo '
|
||||
- lint lockfile
|
||||
'
|
||||
npm run test:lockfile-lint || exit 1
|
||||
npm run test:lockfile-lint || exit 1
|
||||
|
||||
echo '
|
||||
- lint d.ts files
|
||||
'
|
||||
npm run test:dts-lint || exit 1
|
||||
@@ -1,103 +1,363 @@
|
||||
///////////////////////////////////////////////
|
||||
/* Enums for UAParser.js v2.0.0-alpha.3
|
||||
/* Enums for UAParser.js v2.0.0-beta.3
|
||||
https://github.com/faisalman/ua-parser-js
|
||||
Author: Faisal Salman <f@faisalman.com>
|
||||
MIT License */
|
||||
UAParser.js PRO Personal License */
|
||||
//////////////////////////////////////////////
|
||||
|
||||
/*jshint esversion: 6 */
|
||||
|
||||
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',
|
||||
const Browser = Object.freeze({
|
||||
_2345_EXPLORER: '2345Explorer',
|
||||
_360: '360 Browser',
|
||||
ALIPAY: 'Alipay',
|
||||
AMAYA: 'Amaya',
|
||||
ANDROID: 'Android Browser',
|
||||
ARORA: 'Arora',
|
||||
AVANT: 'Avant',
|
||||
AVAST: 'Avast Secure Browser',
|
||||
AVG: 'AVG Secure Browser',
|
||||
BAIDU: 'Baidu Browser',
|
||||
BASILISK: 'Basilisk',
|
||||
BLAZER: 'Blazer',
|
||||
BOLT: 'Bolt',
|
||||
BOWSER: 'Bowser',
|
||||
BRAVE: 'Brave',
|
||||
CAMINO: 'Camino',
|
||||
CHIMERA: 'Chimera',
|
||||
CHROME: 'Chrome',
|
||||
CHROME_HEADLESS: 'Chrome Headless',
|
||||
CHROME_MOBILE: 'Mobile Chrome',
|
||||
CHROME_WEBVIEW: 'Chrome WebView',
|
||||
CHROMIUM: 'Chromium',
|
||||
COBALT: 'Cobalt',
|
||||
COC_COC: 'Coc Coc',
|
||||
COMODO_DRAGON: 'Comodo Dragon',
|
||||
CONKEROR: 'Conkeror',
|
||||
DILLO: 'Dillo',
|
||||
DOLPHIN: 'Dolphin',
|
||||
DORIS: 'Doris',
|
||||
DUCKDUCKGO: 'DuckDuckGo',
|
||||
EDGE: 'Edge',
|
||||
EPIPHANY: 'Epiphany',
|
||||
FACEBOOK: 'Facebook',
|
||||
FALKON: 'Falkon',
|
||||
FIREBIRD: 'Firebird',
|
||||
FIREFOX: 'Firefox',
|
||||
FIREFOX_FOCUS: 'Firefox Focus',
|
||||
FIREFOX_MOBILE: 'Mobile Firefox',
|
||||
FIREFOX_REALITY: 'Firefox Reality',
|
||||
FENNEC: 'Fennec',
|
||||
FLOCK: 'Flock',
|
||||
FLOW: 'Flow',
|
||||
GO: 'GoBrowser',
|
||||
GOOGLE_SEARCH: 'GSA',
|
||||
HEYTAP: 'HeyTap',
|
||||
HUAWEI: 'Huawei Browser',
|
||||
ICAB: 'iCab',
|
||||
ICE: 'ICE Browser',
|
||||
ICEAPE: 'IceApe',
|
||||
ICECAT: 'IceCat',
|
||||
ICEDRAGON: 'IceDragon',
|
||||
ICEWEASEL: 'IceWeasel',
|
||||
IE: 'IE',
|
||||
INSTAGRAM: 'Instagram',
|
||||
IRIDIUM: 'Iridium',
|
||||
IRON: 'Iron',
|
||||
JASMINE: 'Jasmine',
|
||||
KONQUEROR: 'Konqueror',
|
||||
KAKAO: 'KakaoTalk',
|
||||
KHTML: 'KHTML',
|
||||
K_MELEON: 'K-Meleon',
|
||||
KLAR: 'Klar',
|
||||
KLARNA: 'Klarna',
|
||||
KINDLE: 'Kindle',
|
||||
LENOVO: 'Smart Lenovo Browser',
|
||||
LIEBAO: 'LBBROWSER',
|
||||
LINE: 'Line',
|
||||
LINKEDIN: 'LinkedIn',
|
||||
LINKS: 'Links',
|
||||
LUNASCAPE: 'Lunascape',
|
||||
LYNX: 'Lynx',
|
||||
MAEMO: 'Maemo Browser',
|
||||
MAXTHON: 'Maxthon',
|
||||
MIDORI: 'Midori',
|
||||
MINIMO: 'Minimo',
|
||||
MIUI: 'MIUI Browser',
|
||||
MOZILLA: 'Mozilla',
|
||||
MOSAIC: 'Mosaic',
|
||||
NAVER: 'Naver',
|
||||
NETFRONT: 'NetFront',
|
||||
NETSURF : 'NetSurf',
|
||||
PRESTO : 'Presto',
|
||||
TASMAN : 'Tasman',
|
||||
TRIDENT : 'Trident',
|
||||
W3M : 'w3m',
|
||||
WEBKIT : 'WebKit'
|
||||
NETSCAPE: 'Netscape',
|
||||
NETSURF: 'Netsurf',
|
||||
NOKIA: 'Nokia Browser',
|
||||
OBIGO: 'Obigo',
|
||||
OCULUS: 'Oculus Browser',
|
||||
OMNIWEB: 'OmniWeb',
|
||||
OPERA: 'Opera',
|
||||
OPERA_COAST: 'Opera Coast',
|
||||
OPERA_MINI: 'Opera Mini',
|
||||
OPERA_MOBI: 'Opera Mobi',
|
||||
OPERA_TABLET: 'Opera Tablet',
|
||||
OPERA_TOUCH: 'Opera Touch',
|
||||
OVI: 'OviBrowser',
|
||||
PALEMOON: 'PaleMoon',
|
||||
PHANTOMJS: 'PhantomJS',
|
||||
PHOENIX: 'Phoenix',
|
||||
PICOBROWSER: 'Pico Browser',
|
||||
POLARIS: 'Polaris',
|
||||
PUFFIN: 'Puffin',
|
||||
QQ: 'QQBrowser',
|
||||
QQ_LITE: 'QQBrowserLite',
|
||||
QUARK: 'Quark',
|
||||
QUPZILLA: 'QupZilla',
|
||||
REKONQ: 'rekonq',
|
||||
ROCKMELT: 'Rockmelt',
|
||||
SAFARI: 'Safari',
|
||||
SAFARI_MOBILE: 'Mobile Safari',
|
||||
SAILFISH: 'Sailfish Browser',
|
||||
SAMSUNG: 'Samsung Internet',
|
||||
SEAMONKEY: 'SeaMonkey',
|
||||
SILK: 'Silk',
|
||||
SKYFIRE: 'Skyfire',
|
||||
SLEIPNIR: 'Sleipnir',
|
||||
SLIMBROWSER: 'SlimBrowser',
|
||||
SNAPCHAT: 'Snapchat',
|
||||
SOGOU_EXPLORER: 'Sogou Explorer',
|
||||
SOGOU_MOBILE: 'Sogou Mobile',
|
||||
SWIFTFOX: 'Swiftfox',
|
||||
TESLA: 'Tesla',
|
||||
TIKTOK: 'TikTok',
|
||||
TIZEN: 'Tizen Browser',
|
||||
TWITTER: 'Twitter',
|
||||
UC: 'UCBrowser',
|
||||
UP: 'UP.Browser',
|
||||
VIVALDI: 'Vivaldi',
|
||||
VIVO: 'Vivo Browser',
|
||||
W3M: 'w3m',
|
||||
WATERFOX: 'Waterfox',
|
||||
WEBKIT: 'WebKit',
|
||||
WECHAT: 'WeChat',
|
||||
WEIBO: 'Weibo',
|
||||
WHALE: 'Whale',
|
||||
WOLVIC: 'Wolvic',
|
||||
YANDEX: 'Yandex'
|
||||
|
||||
// TODO : test!
|
||||
});
|
||||
|
||||
const OSName = Object.freeze({
|
||||
WINDOWS : 'Windows',
|
||||
LINUX : 'Linux',
|
||||
MACOS : 'macOS',
|
||||
IOS : 'iOS',
|
||||
ANDROID : 'Android'
|
||||
const BrowserType = Object.freeze({
|
||||
CRAWLER: 'crawler',
|
||||
CLI: 'cli',
|
||||
EMAIL: 'email',
|
||||
FETCHER: 'fetcher',
|
||||
INAPP: 'inapp',
|
||||
MODULE: 'module'
|
||||
});
|
||||
|
||||
const CPU = Object.freeze({
|
||||
ARM : 'arm',
|
||||
ARM_64: 'arm64',
|
||||
ARM_HF: 'armhf',
|
||||
AVR: 'avr',
|
||||
AVR_32: 'avr32',
|
||||
IA64: 'ia64',
|
||||
IRIX: 'irix',
|
||||
IRIX_64: 'irix64',
|
||||
MIPS: 'mips',
|
||||
MIPS_64: 'mips64',
|
||||
M68K: '68k',
|
||||
PA_RISC: 'pa-risc',
|
||||
PPC: 'ppc',
|
||||
SPARC: 'sparc',
|
||||
SPARC_64: 'sparc64',
|
||||
X86: 'ia32',
|
||||
X86_64: 'amd64'
|
||||
});
|
||||
|
||||
const Device = Object.freeze({
|
||||
CONSOLE: 'console',
|
||||
DESKTOP: 'desktop',
|
||||
EMBEDDED: 'embedded',
|
||||
MOBILE: 'mobile',
|
||||
SMARTTV: 'smarttv',
|
||||
TABLET: 'tablet',
|
||||
WEARABLE: 'wearable',
|
||||
XR: 'xr'
|
||||
});
|
||||
|
||||
const Vendor = Object.freeze({
|
||||
ACER: 'Acer',
|
||||
ALCATEL: 'Alcatel',
|
||||
APPLE: 'Apple',
|
||||
AMAZON: 'Amazon',
|
||||
ARCHOS: 'Archos',
|
||||
ASUS: 'ASUS',
|
||||
ATT: 'AT&T',
|
||||
BENQ: 'BenQ',
|
||||
BLACKBERRY: 'BlackBerry',
|
||||
DELL: 'Dell',
|
||||
ESSENTIAL: 'Essential',
|
||||
FACEBOOK: 'Facebook',
|
||||
FAIRPHONE: 'Fairphone',
|
||||
GEEKSPHONE: 'GeeksPhone',
|
||||
GENERIC: 'Generic',
|
||||
GOOGLE: 'Google',
|
||||
HP: 'HP',
|
||||
HTC: 'HTC',
|
||||
HUAWEI: 'Huawei',
|
||||
INFINIX: 'Infinix',
|
||||
JOLLA: 'Jolla',
|
||||
KOBO: 'Kobo',
|
||||
LENOVO: 'Lenovo',
|
||||
LG: 'LG',
|
||||
MEIZU: 'Meizu',
|
||||
MICROSOFT: 'Microsoft',
|
||||
MOTOROLA: 'Motorola',
|
||||
NEXIAN: 'Nexian',
|
||||
NINTENDO: 'Nintendo',
|
||||
NOKIA: 'Nokia',
|
||||
NVIDIA: 'Nvidia',
|
||||
ONEPLUS: 'OnePlus',
|
||||
OPPO: 'OPPO',
|
||||
OUYA: 'Ouya',
|
||||
PALM: 'Palm',
|
||||
PANASONIC: 'Panasonic',
|
||||
PEBBLE: 'Pebble',
|
||||
POLYTRON: 'Polytron',
|
||||
REALME: 'Realme',
|
||||
RIM: 'RIM',
|
||||
ROKU: 'Roku',
|
||||
SAMSUNG: 'Samsung',
|
||||
SHARP: 'Sharp',
|
||||
SIEMENS: 'Siemens',
|
||||
SONY: 'Sony',
|
||||
SPRINT: 'Sprint',
|
||||
TECHNISAT: 'TechniSAT',
|
||||
TECNO: 'Tecno',
|
||||
TESLA: 'Tesla',
|
||||
ULEFONE: 'Ulefone',
|
||||
VIVO: 'Vivo',
|
||||
VODAFONE: 'Vodafone',
|
||||
XBOX: 'Xbox',
|
||||
XIAOMI: 'Xiaomi',
|
||||
ZEBRA: 'Zebra',
|
||||
ZTE: 'ZTE',
|
||||
|
||||
// TODO : test!
|
||||
});
|
||||
|
||||
const Engine = Object.freeze({
|
||||
AMAYA: 'Amaya',
|
||||
BLINK: 'Blink',
|
||||
EDGEHTML: 'EdgeHTML',
|
||||
FLOW: 'Flow',
|
||||
GECKO: 'Gecko',
|
||||
GOANNA: 'Goanna',
|
||||
ICAB: 'iCab',
|
||||
KHTML: 'KHTML',
|
||||
LIBWEB: 'LibWeb',
|
||||
LINKS: 'Links',
|
||||
LYNX: 'Lynx',
|
||||
NETFRONT: 'NetFront',
|
||||
NETSURF: 'NetSurf',
|
||||
PRESTO: 'Presto',
|
||||
TASMAN: 'Tasman',
|
||||
TRIDENT: 'Trident',
|
||||
W3M: 'w3m',
|
||||
WEBKIT: 'WebKit'
|
||||
});
|
||||
|
||||
const OS = Object.freeze({
|
||||
AIX: 'AIX',
|
||||
AMIGA_OS: 'Amiga OS',
|
||||
ANDROID: 'Android',
|
||||
ANDROID_X86: 'Android-x86',
|
||||
ARCH: 'Arch',
|
||||
BADA: 'Bada',
|
||||
BEOS: 'BeOS',
|
||||
BLACKBERRY: 'BlackBerry',
|
||||
CENTOS: 'CentOS',
|
||||
CHROME_OS: 'Chrome OS',
|
||||
CHROMECAST: 'Chromecast',
|
||||
CONTIKI: 'Contiki',
|
||||
DEBIAN: 'Debian',
|
||||
DEEPIN: 'Deepin',
|
||||
DRAGONFLY: 'DragonFly',
|
||||
ELEMENTARY_OS: 'elementary OS',
|
||||
FEDORA: 'Fedora',
|
||||
FIREFOX_OS: 'Firefox OS',
|
||||
FREEBSD: 'FreeBSD',
|
||||
FUCHSIA: 'Fuchsia',
|
||||
GENTOO: 'Gentoo',
|
||||
GHOSTBSD: 'GhostBSD',
|
||||
GNU: 'GNU',
|
||||
HAIKU: 'Haiku',
|
||||
HARMONYOS: 'HarmonyOS',
|
||||
HP_UX: 'HP-UX',
|
||||
HURD: 'Hurd',
|
||||
IOS: 'iOS',
|
||||
JOLI: 'Joli',
|
||||
KAIOS: 'KaiOS',
|
||||
LINPUS: 'Linpus',
|
||||
LINSPIRE: 'Linspire',
|
||||
LINUX: 'Linux',
|
||||
MACOS: 'macOS',
|
||||
MAEMO: 'Maemo',
|
||||
MAGEIA: 'Mageia',
|
||||
MANDRIVA: 'Mandriva',
|
||||
MANJARO: 'Manjaro',
|
||||
MEEGO: 'MeeGo',
|
||||
MINIX: 'Minix',
|
||||
MINT: 'Mint',
|
||||
MORPH_OS: 'Morph OS',
|
||||
NETBSD: 'NetBSD',
|
||||
NETRANGE: 'NetRange',
|
||||
NETTV: 'NetTV',
|
||||
NINTENDO: 'Nintendo',
|
||||
OPENBSD: 'OpenBSD',
|
||||
OPENVMS: 'OpenVMS',
|
||||
OS2: 'OS/2',
|
||||
PALM: 'Palm',
|
||||
PC_BSD: 'PC-BSD',
|
||||
PCLINUXOS: 'PCLinuxOS',
|
||||
PLAN9: 'Plan9',
|
||||
PLAYSTATION: 'PlayStation',
|
||||
QNX: 'QNX',
|
||||
RASPBIAN: 'Raspbian',
|
||||
REDHAT: 'RedHat',
|
||||
RIM_TABLET_OS: 'RIM Tablet OS',
|
||||
RISC_OS: 'RISC OS',
|
||||
SABAYON: 'Sabayon',
|
||||
SAILFISH: 'Sailfish',
|
||||
SERENITYOS: 'SerenityOS',
|
||||
SERIES40: 'Series40',
|
||||
SLACKWARE: 'Slackware',
|
||||
SOLARIS: 'Solaris',
|
||||
SUSE: 'SUSE',
|
||||
SYMBIAN: 'Symbian',
|
||||
TIZEN: 'Tizen',
|
||||
UBUNTU: 'Ubuntu',
|
||||
UNIX: 'Unix',
|
||||
VECTORLINUX: 'VectorLinux',
|
||||
VIERA: 'Viera',
|
||||
WATCHOS: 'watchOS',
|
||||
WEBOS: 'WebOS',
|
||||
WINDOWS: 'Windows',
|
||||
WINDOWS_MOBILE: 'Windows Mobile',
|
||||
WINDOWS_PHONE: 'Windows Phone',
|
||||
XBOX: 'Xbox',
|
||||
ZENWALK: 'Zenwalk'
|
||||
|
||||
// TODO : test!
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
BrowserName,
|
||||
CPUArch,
|
||||
DeviceType,
|
||||
DeviceVendor,
|
||||
EngineName,
|
||||
OSName
|
||||
Browser,
|
||||
BrowserType,
|
||||
CPU,
|
||||
Device,
|
||||
Vendor,
|
||||
Engine,
|
||||
OS
|
||||
};
|
||||
@@ -1,107 +1,367 @@
|
||||
// Generated ESM version of UAParser.js enums
|
||||
// Generated ESM version of ua-parser-js/enums
|
||||
// DO NOT EDIT THIS FILE!
|
||||
// Source: /src/enums/ua-parser-enums.js
|
||||
|
||||
///////////////////////////////////////////////
|
||||
/* Enums for UAParser.js v2.0.0-alpha.3
|
||||
/* Enums for UAParser.js v2.0.0-beta.3
|
||||
https://github.com/faisalman/ua-parser-js
|
||||
Author: Faisal Salman <f@faisalman.com>
|
||||
MIT License */
|
||||
UAParser.js PRO Personal License */
|
||||
//////////////////////////////////////////////
|
||||
|
||||
/*jshint esversion: 6 */
|
||||
|
||||
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',
|
||||
const Browser = Object.freeze({
|
||||
_2345_EXPLORER: '2345Explorer',
|
||||
_360: '360 Browser',
|
||||
ALIPAY: 'Alipay',
|
||||
AMAYA: 'Amaya',
|
||||
ANDROID: 'Android Browser',
|
||||
ARORA: 'Arora',
|
||||
AVANT: 'Avant',
|
||||
AVAST: 'Avast Secure Browser',
|
||||
AVG: 'AVG Secure Browser',
|
||||
BAIDU: 'Baidu Browser',
|
||||
BASILISK: 'Basilisk',
|
||||
BLAZER: 'Blazer',
|
||||
BOLT: 'Bolt',
|
||||
BOWSER: 'Bowser',
|
||||
BRAVE: 'Brave',
|
||||
CAMINO: 'Camino',
|
||||
CHIMERA: 'Chimera',
|
||||
CHROME: 'Chrome',
|
||||
CHROME_HEADLESS: 'Chrome Headless',
|
||||
CHROME_MOBILE: 'Mobile Chrome',
|
||||
CHROME_WEBVIEW: 'Chrome WebView',
|
||||
CHROMIUM: 'Chromium',
|
||||
COBALT: 'Cobalt',
|
||||
COC_COC: 'Coc Coc',
|
||||
COMODO_DRAGON: 'Comodo Dragon',
|
||||
CONKEROR: 'Conkeror',
|
||||
DILLO: 'Dillo',
|
||||
DOLPHIN: 'Dolphin',
|
||||
DORIS: 'Doris',
|
||||
DUCKDUCKGO: 'DuckDuckGo',
|
||||
EDGE: 'Edge',
|
||||
EPIPHANY: 'Epiphany',
|
||||
FACEBOOK: 'Facebook',
|
||||
FALKON: 'Falkon',
|
||||
FIREBIRD: 'Firebird',
|
||||
FIREFOX: 'Firefox',
|
||||
FIREFOX_FOCUS: 'Firefox Focus',
|
||||
FIREFOX_MOBILE: 'Mobile Firefox',
|
||||
FIREFOX_REALITY: 'Firefox Reality',
|
||||
FENNEC: 'Fennec',
|
||||
FLOCK: 'Flock',
|
||||
FLOW: 'Flow',
|
||||
GO: 'GoBrowser',
|
||||
GOOGLE_SEARCH: 'GSA',
|
||||
HEYTAP: 'HeyTap',
|
||||
HUAWEI: 'Huawei Browser',
|
||||
ICAB: 'iCab',
|
||||
ICE: 'ICE Browser',
|
||||
ICEAPE: 'IceApe',
|
||||
ICECAT: 'IceCat',
|
||||
ICEDRAGON: 'IceDragon',
|
||||
ICEWEASEL: 'IceWeasel',
|
||||
IE: 'IE',
|
||||
INSTAGRAM: 'Instagram',
|
||||
IRIDIUM: 'Iridium',
|
||||
IRON: 'Iron',
|
||||
JASMINE: 'Jasmine',
|
||||
KONQUEROR: 'Konqueror',
|
||||
KAKAO: 'KakaoTalk',
|
||||
KHTML: 'KHTML',
|
||||
K_MELEON: 'K-Meleon',
|
||||
KLAR: 'Klar',
|
||||
KLARNA: 'Klarna',
|
||||
KINDLE: 'Kindle',
|
||||
LENOVO: 'Smart Lenovo Browser',
|
||||
LIEBAO: 'LBBROWSER',
|
||||
LINE: 'Line',
|
||||
LINKEDIN: 'LinkedIn',
|
||||
LINKS: 'Links',
|
||||
LUNASCAPE: 'Lunascape',
|
||||
LYNX: 'Lynx',
|
||||
MAEMO: 'Maemo Browser',
|
||||
MAXTHON: 'Maxthon',
|
||||
MIDORI: 'Midori',
|
||||
MINIMO: 'Minimo',
|
||||
MIUI: 'MIUI Browser',
|
||||
MOZILLA: 'Mozilla',
|
||||
MOSAIC: 'Mosaic',
|
||||
NAVER: 'Naver',
|
||||
NETFRONT: 'NetFront',
|
||||
NETSURF : 'NetSurf',
|
||||
PRESTO : 'Presto',
|
||||
TASMAN : 'Tasman',
|
||||
TRIDENT : 'Trident',
|
||||
W3M : 'w3m',
|
||||
WEBKIT : 'WebKit'
|
||||
NETSCAPE: 'Netscape',
|
||||
NETSURF: 'Netsurf',
|
||||
NOKIA: 'Nokia Browser',
|
||||
OBIGO: 'Obigo',
|
||||
OCULUS: 'Oculus Browser',
|
||||
OMNIWEB: 'OmniWeb',
|
||||
OPERA: 'Opera',
|
||||
OPERA_COAST: 'Opera Coast',
|
||||
OPERA_MINI: 'Opera Mini',
|
||||
OPERA_MOBI: 'Opera Mobi',
|
||||
OPERA_TABLET: 'Opera Tablet',
|
||||
OPERA_TOUCH: 'Opera Touch',
|
||||
OVI: 'OviBrowser',
|
||||
PALEMOON: 'PaleMoon',
|
||||
PHANTOMJS: 'PhantomJS',
|
||||
PHOENIX: 'Phoenix',
|
||||
PICOBROWSER: 'Pico Browser',
|
||||
POLARIS: 'Polaris',
|
||||
PUFFIN: 'Puffin',
|
||||
QQ: 'QQBrowser',
|
||||
QQ_LITE: 'QQBrowserLite',
|
||||
QUARK: 'Quark',
|
||||
QUPZILLA: 'QupZilla',
|
||||
REKONQ: 'rekonq',
|
||||
ROCKMELT: 'Rockmelt',
|
||||
SAFARI: 'Safari',
|
||||
SAFARI_MOBILE: 'Mobile Safari',
|
||||
SAILFISH: 'Sailfish Browser',
|
||||
SAMSUNG: 'Samsung Internet',
|
||||
SEAMONKEY: 'SeaMonkey',
|
||||
SILK: 'Silk',
|
||||
SKYFIRE: 'Skyfire',
|
||||
SLEIPNIR: 'Sleipnir',
|
||||
SLIMBROWSER: 'SlimBrowser',
|
||||
SNAPCHAT: 'Snapchat',
|
||||
SOGOU_EXPLORER: 'Sogou Explorer',
|
||||
SOGOU_MOBILE: 'Sogou Mobile',
|
||||
SWIFTFOX: 'Swiftfox',
|
||||
TESLA: 'Tesla',
|
||||
TIKTOK: 'TikTok',
|
||||
TIZEN: 'Tizen Browser',
|
||||
TWITTER: 'Twitter',
|
||||
UC: 'UCBrowser',
|
||||
UP: 'UP.Browser',
|
||||
VIVALDI: 'Vivaldi',
|
||||
VIVO: 'Vivo Browser',
|
||||
W3M: 'w3m',
|
||||
WATERFOX: 'Waterfox',
|
||||
WEBKIT: 'WebKit',
|
||||
WECHAT: 'WeChat',
|
||||
WEIBO: 'Weibo',
|
||||
WHALE: 'Whale',
|
||||
WOLVIC: 'Wolvic',
|
||||
YANDEX: 'Yandex'
|
||||
|
||||
// TODO : test!
|
||||
});
|
||||
|
||||
const OSName = Object.freeze({
|
||||
WINDOWS : 'Windows',
|
||||
LINUX : 'Linux',
|
||||
MACOS : 'macOS',
|
||||
IOS : 'iOS',
|
||||
ANDROID : 'Android'
|
||||
const BrowserType = Object.freeze({
|
||||
CRAWLER: 'crawler',
|
||||
CLI: 'cli',
|
||||
EMAIL: 'email',
|
||||
FETCHER: 'fetcher',
|
||||
INAPP: 'inapp',
|
||||
MODULE: 'module'
|
||||
});
|
||||
|
||||
const CPU = Object.freeze({
|
||||
ARM : 'arm',
|
||||
ARM_64: 'arm64',
|
||||
ARM_HF: 'armhf',
|
||||
AVR: 'avr',
|
||||
AVR_32: 'avr32',
|
||||
IA64: 'ia64',
|
||||
IRIX: 'irix',
|
||||
IRIX_64: 'irix64',
|
||||
MIPS: 'mips',
|
||||
MIPS_64: 'mips64',
|
||||
M68K: '68k',
|
||||
PA_RISC: 'pa-risc',
|
||||
PPC: 'ppc',
|
||||
SPARC: 'sparc',
|
||||
SPARC_64: 'sparc64',
|
||||
X86: 'ia32',
|
||||
X86_64: 'amd64'
|
||||
});
|
||||
|
||||
const Device = Object.freeze({
|
||||
CONSOLE: 'console',
|
||||
DESKTOP: 'desktop',
|
||||
EMBEDDED: 'embedded',
|
||||
MOBILE: 'mobile',
|
||||
SMARTTV: 'smarttv',
|
||||
TABLET: 'tablet',
|
||||
WEARABLE: 'wearable',
|
||||
XR: 'xr'
|
||||
});
|
||||
|
||||
const Vendor = Object.freeze({
|
||||
ACER: 'Acer',
|
||||
ALCATEL: 'Alcatel',
|
||||
APPLE: 'Apple',
|
||||
AMAZON: 'Amazon',
|
||||
ARCHOS: 'Archos',
|
||||
ASUS: 'ASUS',
|
||||
ATT: 'AT&T',
|
||||
BENQ: 'BenQ',
|
||||
BLACKBERRY: 'BlackBerry',
|
||||
DELL: 'Dell',
|
||||
ESSENTIAL: 'Essential',
|
||||
FACEBOOK: 'Facebook',
|
||||
FAIRPHONE: 'Fairphone',
|
||||
GEEKSPHONE: 'GeeksPhone',
|
||||
GENERIC: 'Generic',
|
||||
GOOGLE: 'Google',
|
||||
HP: 'HP',
|
||||
HTC: 'HTC',
|
||||
HUAWEI: 'Huawei',
|
||||
INFINIX: 'Infinix',
|
||||
JOLLA: 'Jolla',
|
||||
KOBO: 'Kobo',
|
||||
LENOVO: 'Lenovo',
|
||||
LG: 'LG',
|
||||
MEIZU: 'Meizu',
|
||||
MICROSOFT: 'Microsoft',
|
||||
MOTOROLA: 'Motorola',
|
||||
NEXIAN: 'Nexian',
|
||||
NINTENDO: 'Nintendo',
|
||||
NOKIA: 'Nokia',
|
||||
NVIDIA: 'Nvidia',
|
||||
ONEPLUS: 'OnePlus',
|
||||
OPPO: 'OPPO',
|
||||
OUYA: 'Ouya',
|
||||
PALM: 'Palm',
|
||||
PANASONIC: 'Panasonic',
|
||||
PEBBLE: 'Pebble',
|
||||
POLYTRON: 'Polytron',
|
||||
REALME: 'Realme',
|
||||
RIM: 'RIM',
|
||||
ROKU: 'Roku',
|
||||
SAMSUNG: 'Samsung',
|
||||
SHARP: 'Sharp',
|
||||
SIEMENS: 'Siemens',
|
||||
SONY: 'Sony',
|
||||
SPRINT: 'Sprint',
|
||||
TECHNISAT: 'TechniSAT',
|
||||
TECNO: 'Tecno',
|
||||
TESLA: 'Tesla',
|
||||
ULEFONE: 'Ulefone',
|
||||
VIVO: 'Vivo',
|
||||
VODAFONE: 'Vodafone',
|
||||
XBOX: 'Xbox',
|
||||
XIAOMI: 'Xiaomi',
|
||||
ZEBRA: 'Zebra',
|
||||
ZTE: 'ZTE',
|
||||
|
||||
// TODO : test!
|
||||
});
|
||||
|
||||
const Engine = Object.freeze({
|
||||
AMAYA: 'Amaya',
|
||||
BLINK: 'Blink',
|
||||
EDGEHTML: 'EdgeHTML',
|
||||
FLOW: 'Flow',
|
||||
GECKO: 'Gecko',
|
||||
GOANNA: 'Goanna',
|
||||
ICAB: 'iCab',
|
||||
KHTML: 'KHTML',
|
||||
LIBWEB: 'LibWeb',
|
||||
LINKS: 'Links',
|
||||
LYNX: 'Lynx',
|
||||
NETFRONT: 'NetFront',
|
||||
NETSURF: 'NetSurf',
|
||||
PRESTO: 'Presto',
|
||||
TASMAN: 'Tasman',
|
||||
TRIDENT: 'Trident',
|
||||
W3M: 'w3m',
|
||||
WEBKIT: 'WebKit'
|
||||
});
|
||||
|
||||
const OS = Object.freeze({
|
||||
AIX: 'AIX',
|
||||
AMIGA_OS: 'Amiga OS',
|
||||
ANDROID: 'Android',
|
||||
ANDROID_X86: 'Android-x86',
|
||||
ARCH: 'Arch',
|
||||
BADA: 'Bada',
|
||||
BEOS: 'BeOS',
|
||||
BLACKBERRY: 'BlackBerry',
|
||||
CENTOS: 'CentOS',
|
||||
CHROME_OS: 'Chrome OS',
|
||||
CHROMECAST: 'Chromecast',
|
||||
CONTIKI: 'Contiki',
|
||||
DEBIAN: 'Debian',
|
||||
DEEPIN: 'Deepin',
|
||||
DRAGONFLY: 'DragonFly',
|
||||
ELEMENTARY_OS: 'elementary OS',
|
||||
FEDORA: 'Fedora',
|
||||
FIREFOX_OS: 'Firefox OS',
|
||||
FREEBSD: 'FreeBSD',
|
||||
FUCHSIA: 'Fuchsia',
|
||||
GENTOO: 'Gentoo',
|
||||
GHOSTBSD: 'GhostBSD',
|
||||
GNU: 'GNU',
|
||||
HAIKU: 'Haiku',
|
||||
HARMONYOS: 'HarmonyOS',
|
||||
HP_UX: 'HP-UX',
|
||||
HURD: 'Hurd',
|
||||
IOS: 'iOS',
|
||||
JOLI: 'Joli',
|
||||
KAIOS: 'KaiOS',
|
||||
LINPUS: 'Linpus',
|
||||
LINSPIRE: 'Linspire',
|
||||
LINUX: 'Linux',
|
||||
MACOS: 'macOS',
|
||||
MAEMO: 'Maemo',
|
||||
MAGEIA: 'Mageia',
|
||||
MANDRIVA: 'Mandriva',
|
||||
MANJARO: 'Manjaro',
|
||||
MEEGO: 'MeeGo',
|
||||
MINIX: 'Minix',
|
||||
MINT: 'Mint',
|
||||
MORPH_OS: 'Morph OS',
|
||||
NETBSD: 'NetBSD',
|
||||
NETRANGE: 'NetRange',
|
||||
NETTV: 'NetTV',
|
||||
NINTENDO: 'Nintendo',
|
||||
OPENBSD: 'OpenBSD',
|
||||
OPENVMS: 'OpenVMS',
|
||||
OS2: 'OS/2',
|
||||
PALM: 'Palm',
|
||||
PC_BSD: 'PC-BSD',
|
||||
PCLINUXOS: 'PCLinuxOS',
|
||||
PLAN9: 'Plan9',
|
||||
PLAYSTATION: 'PlayStation',
|
||||
QNX: 'QNX',
|
||||
RASPBIAN: 'Raspbian',
|
||||
REDHAT: 'RedHat',
|
||||
RIM_TABLET_OS: 'RIM Tablet OS',
|
||||
RISC_OS: 'RISC OS',
|
||||
SABAYON: 'Sabayon',
|
||||
SAILFISH: 'Sailfish',
|
||||
SERENITYOS: 'SerenityOS',
|
||||
SERIES40: 'Series40',
|
||||
SLACKWARE: 'Slackware',
|
||||
SOLARIS: 'Solaris',
|
||||
SUSE: 'SUSE',
|
||||
SYMBIAN: 'Symbian',
|
||||
TIZEN: 'Tizen',
|
||||
UBUNTU: 'Ubuntu',
|
||||
UNIX: 'Unix',
|
||||
VECTORLINUX: 'VectorLinux',
|
||||
VIERA: 'Viera',
|
||||
WATCHOS: 'watchOS',
|
||||
WEBOS: 'WebOS',
|
||||
WINDOWS: 'Windows',
|
||||
WINDOWS_MOBILE: 'Windows Mobile',
|
||||
WINDOWS_PHONE: 'Windows Phone',
|
||||
XBOX: 'Xbox',
|
||||
ZENWALK: 'Zenwalk'
|
||||
|
||||
// TODO : test!
|
||||
});
|
||||
|
||||
export {
|
||||
BrowserName,
|
||||
CPUArch,
|
||||
DeviceType,
|
||||
DeviceVendor,
|
||||
EngineName,
|
||||
OSName
|
||||
Browser,
|
||||
BrowserType,
|
||||
CPU,
|
||||
Device,
|
||||
Vendor,
|
||||
Engine,
|
||||
OS
|
||||
};
|
||||
14
src/extensions/ua-parser-extensions.d.ts
vendored
Normal file
14
src/extensions/ua-parser-extensions.d.ts
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
// Type definitions for Helpers submodule of UAParser.js v2.0.0-beta.3
|
||||
// Project: https://github.com/faisalman/ua-parser-js
|
||||
// Definitions by: Faisal Salman <https://github.com/faisalman>
|
||||
|
||||
import type { UAParserExt } from "../main/ua-parser";
|
||||
|
||||
export const CLIs: UAParserExt;
|
||||
export const Crawlers: UAParserExt;
|
||||
export const ExtraDevices: UAParserExt;
|
||||
export const Emails: UAParserExt;
|
||||
export const Fetchers: UAParserExt;
|
||||
export const InApps: UAParserExt;
|
||||
export const MediaPlayers: UAParserExt;
|
||||
export const Modules: UAParserExt;
|
||||
@@ -1,8 +1,8 @@
|
||||
///////////////////////////////////////////////
|
||||
/* Extensions for UAParser.js v2.0.0-alpha.3
|
||||
/* Extensions for UAParser.js v2.0.0-beta.3
|
||||
https://github.com/faisalman/ua-parser-js
|
||||
Author: Faisal Salman <f@faisalman.com>
|
||||
MIT License */
|
||||
UAParser.js PRO Personal License */
|
||||
//////////////////////////////////////////////
|
||||
|
||||
/*jshint esversion: 6 */
|
||||
@@ -14,33 +14,74 @@ const VENDOR = 'vendor';
|
||||
const VERSION = 'version';
|
||||
const MOBILE = 'mobile';
|
||||
const TABLET = 'tablet';
|
||||
const CRAWLER = 'crawler';
|
||||
const CLI = 'cli';
|
||||
const EMAIL = 'email';
|
||||
const FETCHER = 'fetcher';
|
||||
const INAPP = 'inapp';
|
||||
const MODULE = 'module';
|
||||
|
||||
const Apps = Object.freeze({
|
||||
browser : [
|
||||
[/chatlyio\/([\d\.]+)/i], [VERSION, 'Slack', [TYPE, 'app']]
|
||||
]
|
||||
});
|
||||
|
||||
const Bots = Object.freeze({
|
||||
browser : [
|
||||
// Googlebot / BingBot / MSNBot / FacebookBot
|
||||
[/((?:google|bing|msn|facebook)bot(?:[\-imagevdo]{0,6})|bingpreview)\/([\w\.]+)/i], [NAME, VERSION, [TYPE, 'bot']],
|
||||
|
||||
// GPTBot - https://platform.openai.com/docs/gptbot
|
||||
[/(gptbot)\/([\w\.]+)/i], [NAME, VERSION, [TYPE, 'bot']],
|
||||
|
||||
// Slackbot - https://api.slack.com/robots
|
||||
[/(slack(?:bot)?(?:-imgproxy|-linkexpanding)?) ([\w\.]+)/i], [NAME, VERSION, [TYPE, 'bot']]
|
||||
]
|
||||
});
|
||||
//////////////////////
|
||||
// COMMAND LINE APPS
|
||||
/////////////////////
|
||||
|
||||
const CLIs = Object.freeze({
|
||||
browser : [
|
||||
// wget / curl / lynx
|
||||
[/(wget|curl|lynx)\/([\w\.]+)/i], [NAME, VERSION, [TYPE, 'cli']]
|
||||
// wget / curl / lynx
|
||||
[/(wget|curl|lynx)[\/ ]([\w\.]+)/i], [NAME, VERSION, [TYPE, CLI]]
|
||||
]
|
||||
});
|
||||
|
||||
////////////////////////
|
||||
// CRAWLERS / SPIDERS
|
||||
///////////////////////
|
||||
|
||||
const Crawlers = Object.freeze({
|
||||
browser : [
|
||||
// Amazonbot - https://developer.amazon.com/amazonbot
|
||||
// Applebot - http://apple.com/go/applebot
|
||||
// Bingbot - http://www.bing.com/bingbot.htm
|
||||
// DuckDuckBot - http://duckduckgo.com/duckduckbot.html
|
||||
// FacebookBot - https://developers.facebook.com/docs/sharing/bot/
|
||||
// GPTBot - https://platform.openai.com/docs/gptbot
|
||||
[/((?:amazon|apple|bing|duckduck|facebook|gpt)bot)\/([\w\.]+)/i],
|
||||
[NAME, VERSION, [TYPE, CRAWLER]],
|
||||
|
||||
// Baiduspider https://help.baidu.com/question?prod_id=99&class=0&id=3001
|
||||
[/(baiduspider)[-imagevdonsfcpr]{0,6}\/([\w\.]+)/i],
|
||||
[NAME, VERSION, [TYPE, CRAWLER]],
|
||||
|
||||
// Bytespider
|
||||
// Yahoo! Slurp - http://help.yahoo.com/help/us/ysearch/slurp
|
||||
[/((?:bytespider|(?=yahoo! )slurp))/i],
|
||||
[NAME, [TYPE, CRAWLER]],
|
||||
|
||||
// ClaudeBot
|
||||
[/(claude(?:bot|-web))\/([\w\.]+)/i],
|
||||
[NAME, VERSION, [TYPE, CRAWLER]],
|
||||
|
||||
// Googlebot - http://www.google.com/bot.html
|
||||
[
|
||||
/(google(?:bot|other)(?:-image|-video|-news|-extended)?|(?:storebot-)?google(?:-inspectiontool)?)\/?([\w\.]*)/i
|
||||
],
|
||||
[NAME, VERSION, [TYPE, CRAWLER]],
|
||||
|
||||
// Sogou Spider
|
||||
[/(sogou (?:pic|head|web|orion|news) spider)\/([\w\.]+)/i],
|
||||
[NAME, VERSION, [TYPE, CRAWLER]],
|
||||
|
||||
// Yandex Bots - https://yandex.com/bots
|
||||
[
|
||||
/(yandex(?:(?:mobile)?(?:accessibility|additional|renderresources|screenshot|sprav)?bot|image(?:s|resizer)|video(?:parser)?|blogs|adnet|favicons|fordomain|market|media|metrika|news|ontodb(?:api)?|pagechecker|partner|rca|tracker|turbo|vertis|webmaster|antivirus))\/([\w\.]+)/i
|
||||
],
|
||||
[NAME, VERSION, [TYPE, CRAWLER]]
|
||||
]
|
||||
});
|
||||
|
||||
//////////////////
|
||||
// EXTRA DEVICES
|
||||
/////////////////
|
||||
|
||||
const ExtraDevices = Object.freeze({
|
||||
device : [[
|
||||
/(nook)[\w ]+build\/(\w+)/i, // Nook
|
||||
@@ -117,13 +158,63 @@ const ExtraDevices = Object.freeze({
|
||||
]
|
||||
});
|
||||
|
||||
///////////////
|
||||
// EMAIL APPS
|
||||
//////////////
|
||||
|
||||
const Emails = Object.freeze({
|
||||
browser : [
|
||||
// Microsoft Outlook / Thunderbird
|
||||
[/(microsoft outlook|thunderbird)[\s\/]([\w\.]+)/i], [NAME, VERSION, [TYPE, 'email']]
|
||||
// Microsoft Outlook / Thunderbird
|
||||
[/(microsoft outlook|thunderbird)[\s\/]([\w\.]+)/i], [NAME, VERSION, [TYPE, EMAIL]]
|
||||
]
|
||||
});
|
||||
|
||||
///////////////////////
|
||||
// ON-DEMAND SCRAPERS
|
||||
//////////////////////
|
||||
|
||||
const Fetchers = Object.freeze({
|
||||
browser : [
|
||||
// BingPreview / Mastodon / Pinterestbot / Redditbot / Telegrambot / Twitterbot
|
||||
[/(bingpreview|mastodon|(?:discord|linkedin|pinterest|reddit|telegram|twitter)bot)\/([\w\.]+)/i],
|
||||
[NAME, VERSION, [TYPE, FETCHER]],
|
||||
|
||||
// Google Bots / Snapchat
|
||||
[/(feedfetcher-google|google-read-aloud|(?=bot; )snapchat)/i],
|
||||
[NAME, [TYPE, FETCHER]],
|
||||
|
||||
|
||||
// Slackbot - https://api.slack.com/robots
|
||||
[/(slack(?:bot)?(?:-imgproxy|-linkexpanding)?) ([\w\.]+)/i],
|
||||
[NAME, VERSION, [TYPE, FETCHER]],
|
||||
|
||||
// WhatsApp
|
||||
[/(whatsapp)\/([\w\.]+)[\/ ][ianw]/i],
|
||||
[NAME, VERSION, [TYPE, FETCHER]],
|
||||
|
||||
// Yandex Bots - https://yandex.com/bots
|
||||
[
|
||||
/(yandex(?:calendar|direct(?:dyn)?|searchshop)|yadirectfetcher)\/([\w\.]+)/i,
|
||||
/(yandex(?:sitelinks|userproxy))/i
|
||||
],
|
||||
[NAME, VERSION, [TYPE, FETCHER]]
|
||||
]
|
||||
});
|
||||
|
||||
////////////////////
|
||||
// IN-APP BROWSERS
|
||||
///////////////////
|
||||
|
||||
const InApps = Object.freeze({
|
||||
browser : [
|
||||
[/chatlyio\/([\d\.]+)/i], [VERSION, 'Slack', [TYPE, INAPP]]
|
||||
]
|
||||
});
|
||||
|
||||
//////////////////////
|
||||
// MEDIA PLAYER APPS
|
||||
/////////////////////
|
||||
|
||||
const MediaPlayers = Object.freeze({
|
||||
browser : [[
|
||||
|
||||
@@ -230,19 +321,24 @@ const MediaPlayers = Object.freeze({
|
||||
]
|
||||
});
|
||||
|
||||
////////////////////////
|
||||
// MODULES / LIBRARIES
|
||||
///////////////////////
|
||||
|
||||
const Modules = Object.freeze({
|
||||
browser : [
|
||||
// Axios/jsdom/Scrapy
|
||||
[/\b(axios|jsdom|scrapy)\/([\w\.]+)/i], [NAME, VERSION, [TYPE, 'module']]
|
||||
// Axios/jsdom/Scrapy
|
||||
[/\b(axios|jsdom|scrapy)\/([\w\.]+)/i], [NAME, VERSION, [TYPE, MODULE]]
|
||||
]
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
Apps,
|
||||
Bots,
|
||||
CLIs,
|
||||
Crawlers,
|
||||
ExtraDevices,
|
||||
Emails,
|
||||
Fetchers,
|
||||
InApps,
|
||||
MediaPlayers,
|
||||
Modules
|
||||
};
|
||||
@@ -1,12 +1,12 @@
|
||||
// Generated ESM version of UAParser.js extensions
|
||||
// Generated ESM version of ua-parser-js/extensions
|
||||
// DO NOT EDIT THIS FILE!
|
||||
// Source: /src/extensions/ua-parser-extensions.js
|
||||
|
||||
///////////////////////////////////////////////
|
||||
/* Extensions for UAParser.js v2.0.0-alpha.3
|
||||
/* Extensions for UAParser.js v2.0.0-beta.3
|
||||
https://github.com/faisalman/ua-parser-js
|
||||
Author: Faisal Salman <f@faisalman.com>
|
||||
MIT License */
|
||||
UAParser.js PRO Personal License */
|
||||
//////////////////////////////////////////////
|
||||
|
||||
/*jshint esversion: 6 */
|
||||
@@ -18,33 +18,74 @@ const VENDOR = 'vendor';
|
||||
const VERSION = 'version';
|
||||
const MOBILE = 'mobile';
|
||||
const TABLET = 'tablet';
|
||||
const CRAWLER = 'crawler';
|
||||
const CLI = 'cli';
|
||||
const EMAIL = 'email';
|
||||
const FETCHER = 'fetcher';
|
||||
const INAPP = 'inapp';
|
||||
const MODULE = 'module';
|
||||
|
||||
const Apps = Object.freeze({
|
||||
browser : [
|
||||
[/chatlyio\/([\d\.]+)/i], [VERSION, 'Slack', [TYPE, 'app']]
|
||||
]
|
||||
});
|
||||
|
||||
const Bots = Object.freeze({
|
||||
browser : [
|
||||
// Googlebot / BingBot / MSNBot / FacebookBot
|
||||
[/((?:google|bing|msn|facebook)bot(?:[\-imagevdo]{0,6})|bingpreview)\/([\w\.]+)/i], [NAME, VERSION, [TYPE, 'bot']],
|
||||
|
||||
// GPTBot - https://platform.openai.com/docs/gptbot
|
||||
[/(gptbot)\/([\w\.]+)/i], [NAME, VERSION, [TYPE, 'bot']],
|
||||
|
||||
// Slackbot - https://api.slack.com/robots
|
||||
[/(slack(?:bot)?(?:-imgproxy|-linkexpanding)?) ([\w\.]+)/i], [NAME, VERSION, [TYPE, 'bot']]
|
||||
]
|
||||
});
|
||||
//////////////////////
|
||||
// COMMAND LINE APPS
|
||||
/////////////////////
|
||||
|
||||
const CLIs = Object.freeze({
|
||||
browser : [
|
||||
// wget / curl / lynx
|
||||
[/(wget|curl|lynx)\/([\w\.]+)/i], [NAME, VERSION, [TYPE, 'cli']]
|
||||
// wget / curl / lynx
|
||||
[/(wget|curl|lynx)[\/ ]([\w\.]+)/i], [NAME, VERSION, [TYPE, CLI]]
|
||||
]
|
||||
});
|
||||
|
||||
////////////////////////
|
||||
// CRAWLERS / SPIDERS
|
||||
///////////////////////
|
||||
|
||||
const Crawlers = Object.freeze({
|
||||
browser : [
|
||||
// Amazonbot - https://developer.amazon.com/amazonbot
|
||||
// Applebot - http://apple.com/go/applebot
|
||||
// Bingbot - http://www.bing.com/bingbot.htm
|
||||
// DuckDuckBot - http://duckduckgo.com/duckduckbot.html
|
||||
// FacebookBot - https://developers.facebook.com/docs/sharing/bot/
|
||||
// GPTBot - https://platform.openai.com/docs/gptbot
|
||||
[/((?:amazon|apple|bing|duckduck|facebook|gpt)bot)\/([\w\.]+)/i],
|
||||
[NAME, VERSION, [TYPE, CRAWLER]],
|
||||
|
||||
// Baiduspider https://help.baidu.com/question?prod_id=99&class=0&id=3001
|
||||
[/(baiduspider)[-imagevdonsfcpr]{0,6}\/([\w\.]+)/i],
|
||||
[NAME, VERSION, [TYPE, CRAWLER]],
|
||||
|
||||
// Bytespider
|
||||
// Yahoo! Slurp - http://help.yahoo.com/help/us/ysearch/slurp
|
||||
[/((?:bytespider|(?=yahoo! )slurp))/i],
|
||||
[NAME, [TYPE, CRAWLER]],
|
||||
|
||||
// ClaudeBot
|
||||
[/(claude(?:bot|-web))\/([\w\.]+)/i],
|
||||
[NAME, VERSION, [TYPE, CRAWLER]],
|
||||
|
||||
// Googlebot - http://www.google.com/bot.html
|
||||
[
|
||||
/(google(?:bot|other)(?:-image|-video|-news|-extended)?|(?:storebot-)?google(?:-inspectiontool)?)\/?([\w\.]*)/i
|
||||
],
|
||||
[NAME, VERSION, [TYPE, CRAWLER]],
|
||||
|
||||
// Sogou Spider
|
||||
[/(sogou (?:pic|head|web|orion|news) spider)\/([\w\.]+)/i],
|
||||
[NAME, VERSION, [TYPE, CRAWLER]],
|
||||
|
||||
// Yandex Bots - https://yandex.com/bots
|
||||
[
|
||||
/(yandex(?:(?:mobile)?(?:accessibility|additional|renderresources|screenshot|sprav)?bot|image(?:s|resizer)|video(?:parser)?|blogs|adnet|favicons|fordomain|market|media|metrika|news|ontodb(?:api)?|pagechecker|partner|rca|tracker|turbo|vertis|webmaster|antivirus))\/([\w\.]+)/i
|
||||
],
|
||||
[NAME, VERSION, [TYPE, CRAWLER]]
|
||||
]
|
||||
});
|
||||
|
||||
//////////////////
|
||||
// EXTRA DEVICES
|
||||
/////////////////
|
||||
|
||||
const ExtraDevices = Object.freeze({
|
||||
device : [[
|
||||
/(nook)[\w ]+build\/(\w+)/i, // Nook
|
||||
@@ -121,13 +162,63 @@ const ExtraDevices = Object.freeze({
|
||||
]
|
||||
});
|
||||
|
||||
///////////////
|
||||
// EMAIL APPS
|
||||
//////////////
|
||||
|
||||
const Emails = Object.freeze({
|
||||
browser : [
|
||||
// Microsoft Outlook / Thunderbird
|
||||
[/(microsoft outlook|thunderbird)[\s\/]([\w\.]+)/i], [NAME, VERSION, [TYPE, 'email']]
|
||||
// Microsoft Outlook / Thunderbird
|
||||
[/(microsoft outlook|thunderbird)[\s\/]([\w\.]+)/i], [NAME, VERSION, [TYPE, EMAIL]]
|
||||
]
|
||||
});
|
||||
|
||||
///////////////////////
|
||||
// ON-DEMAND SCRAPERS
|
||||
//////////////////////
|
||||
|
||||
const Fetchers = Object.freeze({
|
||||
browser : [
|
||||
// BingPreview / Mastodon / Pinterestbot / Redditbot / Telegrambot / Twitterbot
|
||||
[/(bingpreview|mastodon|(?:discord|linkedin|pinterest|reddit|telegram|twitter)bot)\/([\w\.]+)/i],
|
||||
[NAME, VERSION, [TYPE, FETCHER]],
|
||||
|
||||
// Google Bots / Snapchat
|
||||
[/(feedfetcher-google|google-read-aloud|(?=bot; )snapchat)/i],
|
||||
[NAME, [TYPE, FETCHER]],
|
||||
|
||||
|
||||
// Slackbot - https://api.slack.com/robots
|
||||
[/(slack(?:bot)?(?:-imgproxy|-linkexpanding)?) ([\w\.]+)/i],
|
||||
[NAME, VERSION, [TYPE, FETCHER]],
|
||||
|
||||
// WhatsApp
|
||||
[/(whatsapp)\/([\w\.]+)[\/ ][ianw]/i],
|
||||
[NAME, VERSION, [TYPE, FETCHER]],
|
||||
|
||||
// Yandex Bots - https://yandex.com/bots
|
||||
[
|
||||
/(yandex(?:calendar|direct(?:dyn)?|searchshop)|yadirectfetcher)\/([\w\.]+)/i,
|
||||
/(yandex(?:sitelinks|userproxy))/i
|
||||
],
|
||||
[NAME, VERSION, [TYPE, FETCHER]]
|
||||
]
|
||||
});
|
||||
|
||||
////////////////////
|
||||
// IN-APP BROWSERS
|
||||
///////////////////
|
||||
|
||||
const InApps = Object.freeze({
|
||||
browser : [
|
||||
[/chatlyio\/([\d\.]+)/i], [VERSION, 'Slack', [TYPE, INAPP]]
|
||||
]
|
||||
});
|
||||
|
||||
//////////////////////
|
||||
// MEDIA PLAYER APPS
|
||||
/////////////////////
|
||||
|
||||
const MediaPlayers = Object.freeze({
|
||||
browser : [[
|
||||
|
||||
@@ -234,19 +325,24 @@ const MediaPlayers = Object.freeze({
|
||||
]
|
||||
});
|
||||
|
||||
////////////////////////
|
||||
// MODULES / LIBRARIES
|
||||
///////////////////////
|
||||
|
||||
const Modules = Object.freeze({
|
||||
browser : [
|
||||
// Axios/jsdom/Scrapy
|
||||
[/\b(axios|jsdom|scrapy)\/([\w\.]+)/i], [NAME, VERSION, [TYPE, 'module']]
|
||||
// Axios/jsdom/Scrapy
|
||||
[/\b(axios|jsdom|scrapy)\/([\w\.]+)/i], [NAME, VERSION, [TYPE, MODULE]]
|
||||
]
|
||||
});
|
||||
|
||||
export {
|
||||
Apps,
|
||||
Bots,
|
||||
CLIs,
|
||||
Crawlers,
|
||||
ExtraDevices,
|
||||
Emails,
|
||||
Fetchers,
|
||||
InApps,
|
||||
MediaPlayers,
|
||||
Modules
|
||||
};
|
||||
15
src/helpers/ua-parser-helpers.d.ts
vendored
Normal file
15
src/helpers/ua-parser-helpers.d.ts
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
// Type definitions for Helpers submodule of UAParser.js v2.0.0-beta.3
|
||||
// Project: https://github.com/faisalman/ua-parser-js
|
||||
// Definitions by: Faisal Salman <https://github.com/faisalman>
|
||||
|
||||
import { IResult } from "../main/ua-parser";
|
||||
|
||||
declare function isAppleSilicon(res: IResult): boolean;
|
||||
declare function isChromiumBased(res: IResult): boolean;
|
||||
declare function isFrozenUA(ua: string): boolean;
|
||||
|
||||
export {
|
||||
isAppleSilicon,
|
||||
isChromiumBased,
|
||||
isFrozenUA
|
||||
}
|
||||
@@ -1,42 +1,22 @@
|
||||
///////////////////////////////////////////////
|
||||
/* Helpers for UAParser.js v2.0.0-alpha.3
|
||||
/* Helpers for UAParser.js v2.0.0-beta.3
|
||||
https://github.com/faisalman/ua-parser-js
|
||||
Author: Faisal Salman <f@faisalman.com>
|
||||
MIT License */
|
||||
AGPLv3 License */
|
||||
//////////////////////////////////////////////
|
||||
|
||||
/*jshint esversion: 6 */
|
||||
|
||||
/*
|
||||
# Reference:
|
||||
https://www.chromium.org/updates/ua-reduction/
|
||||
const { CPU, OS, Engine } = require('../enums/ua-parser-enums');
|
||||
|
||||
# Desktop
|
||||
---
|
||||
Format:
|
||||
Mozilla/5.0 (<unifiedPlatform>) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/<majorVersion>.0.0.0 Safari/537.36
|
||||
const isAppleSilicon = (res) => res.os.is(OS.MACOS) && res.cpu.is(CPU.ARM);
|
||||
|
||||
Possible <unifiedPlatform> values:
|
||||
- Windows NT 10.0; Win64; x64
|
||||
- Macintosh; Intel Mac OS X 10_15_7
|
||||
- X11; Linux x86_64
|
||||
- X11; CrOS x86_64 14541.0.0
|
||||
- Fuchsia
|
||||
const isChromiumBased = (res) => res.engine.is(Engine.BLINK);
|
||||
|
||||
# Mobile & Tablet: (except iOS/Android WebView)
|
||||
---
|
||||
Format:
|
||||
Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/<majorVersion>.0.0.0 <deviceCompat> Safari/537.36
|
||||
|
||||
Possible <deviceCompat> values:
|
||||
- "Mobile"
|
||||
- "" (empty string for Tablets & Desktop)
|
||||
*/
|
||||
|
||||
const frozenUA = /Mozilla\/5\.0 \((Windows NT 10\.0; Win64; x64|Macintosh; Intel Mac OS X 10_15_7|X11; Linux x86_64|X11; CrOS x86_64 14541\.0\.0|Fuchsia|Linux; Android 10; K)\) AppleWebKit\/537\.36 \(KHTML, like Gecko\) Chrome\/\d+\.0\.0\.0 (Mobile )?Safari\/537\.36/;
|
||||
|
||||
const isFrozenUA = str => frozenUA.test(str);
|
||||
const isFrozenUA = (ua) => /^Mozilla\/5\.0 \((Windows NT 10\.0; Win64; x64|Macintosh; Intel Mac OS X 10_15_7|X11; Linux x86_64|X11; CrOS x86_64 14541\.0\.0|Fuchsia|Linux; Android 10; K)\) AppleWebKit\/537\.36 \(KHTML, like Gecko\) Chrome\/\d+\.0\.0\.0 (Mobile )?Safari\/537\.36/.test(ua);
|
||||
|
||||
module.exports = {
|
||||
isAppleSilicon,
|
||||
isChromiumBased,
|
||||
isFrozenUA
|
||||
};
|
||||
}
|
||||
@@ -1,46 +1,26 @@
|
||||
// Generated ESM version of UAParser.js helpers
|
||||
// Generated ESM version of ua-parser-js/helpers
|
||||
// DO NOT EDIT THIS FILE!
|
||||
// Source: /src/helpers/ua-parser-helpers.js
|
||||
|
||||
///////////////////////////////////////////////
|
||||
/* Helpers for UAParser.js v2.0.0-alpha.3
|
||||
/* Helpers for UAParser.js v2.0.0-beta.3
|
||||
https://github.com/faisalman/ua-parser-js
|
||||
Author: Faisal Salman <f@faisalman.com>
|
||||
MIT License */
|
||||
AGPLv3 License */
|
||||
//////////////////////////////////////////////
|
||||
|
||||
/*jshint esversion: 6 */
|
||||
|
||||
/*
|
||||
# Reference:
|
||||
https://www.chromium.org/updates/ua-reduction/
|
||||
import { CPU, OS, Engine } from '../enums/ua-parser-enums';
|
||||
|
||||
# Desktop
|
||||
---
|
||||
Format:
|
||||
Mozilla/5.0 (<unifiedPlatform>) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/<majorVersion>.0.0.0 Safari/537.36
|
||||
const isAppleSilicon = (res) => res.os.is(OS.MACOS) && res.cpu.is(CPU.ARM);
|
||||
|
||||
Possible <unifiedPlatform> values:
|
||||
- Windows NT 10.0; Win64; x64
|
||||
- Macintosh; Intel Mac OS X 10_15_7
|
||||
- X11; Linux x86_64
|
||||
- X11; CrOS x86_64 14541.0.0
|
||||
- Fuchsia
|
||||
const isChromiumBased = (res) => res.engine.is(Engine.BLINK);
|
||||
|
||||
# Mobile & Tablet: (except iOS/Android WebView)
|
||||
---
|
||||
Format:
|
||||
Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/<majorVersion>.0.0.0 <deviceCompat> Safari/537.36
|
||||
|
||||
Possible <deviceCompat> values:
|
||||
- "Mobile"
|
||||
- "" (empty string for Tablets & Desktop)
|
||||
*/
|
||||
|
||||
const frozenUA = /Mozilla\/5\.0 \((Windows NT 10\.0; Win64; x64|Macintosh; Intel Mac OS X 10_15_7|X11; Linux x86_64|X11; CrOS x86_64 14541\.0\.0|Fuchsia|Linux; Android 10; K)\) AppleWebKit\/537\.36 \(KHTML, like Gecko\) Chrome\/\d+\.0\.0\.0 (Mobile )?Safari\/537\.36/;
|
||||
|
||||
const isFrozenUA = str => frozenUA.test(str);
|
||||
const isFrozenUA = (ua) => /^Mozilla\/5\.0 \((Windows NT 10\.0; Win64; x64|Macintosh; Intel Mac OS X 10_15_7|X11; Linux x86_64|X11; CrOS x86_64 14541\.0\.0|Fuchsia|Linux; Android 10; K)\) AppleWebKit\/537\.36 \(KHTML, like Gecko\) Chrome\/\d+\.0\.0\.0 (Mobile )?Safari\/537\.36/.test(ua);
|
||||
|
||||
export {
|
||||
isAppleSilicon,
|
||||
isChromiumBased,
|
||||
isFrozenUA
|
||||
};
|
||||
}
|
||||
109
src/main/ua-parser.d.ts
vendored
Normal file
109
src/main/ua-parser.d.ts
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
// Type definitions for UAParser.js v2.0.0-beta.3
|
||||
// Project: https://github.com/faisalman/ua-parser-js
|
||||
// Definitions by: Faisal Salman <https://github.com/faisalman>
|
||||
|
||||
declare namespace UAParser {
|
||||
|
||||
interface IData<T> {
|
||||
is(val: string): boolean;
|
||||
toString(): string;
|
||||
withClientHints(): PromiseLike<T> | T;
|
||||
withFeatureCheck(): T;
|
||||
}
|
||||
|
||||
interface IBrowser extends IData<IBrowser> {
|
||||
name?: string;
|
||||
version?: string;
|
||||
major?: string;
|
||||
type?: 'crawler' | 'cli' | 'email' | 'fetcher' | 'inapp' | 'module';
|
||||
}
|
||||
|
||||
interface ICPU extends IData<ICPU> {
|
||||
architecture?: 'ia32' | 'ia64' | 'amd64' | 'arm' | 'arm64' | 'armhf' | 'avr' | 'irix' | 'irix64' | 'mips' | 'mips64' | '68k' | 'ppc' | 'sparc' | 'sparc64';
|
||||
}
|
||||
|
||||
interface IDevice extends IData<IDevice> {
|
||||
type?: 'mobile' | 'tablet' | 'console' | 'smarttv' | 'wearable' | 'xr' | 'embedded';
|
||||
vendor?: string;
|
||||
model?: string;
|
||||
}
|
||||
|
||||
interface IEngine extends IData<IEngine> {
|
||||
name?: 'Amaya' | 'Blink' | 'EdgeHTML' | 'Flow' | 'Gecko' | 'Goanna' | 'iCab' | 'KHTML' | 'LibWeb' | 'Links' | 'Lynx' | 'NetFront' | 'NetSurf' | 'Presto' | 'Tasman' | 'Trident' | 'w3m' | 'WebKit';
|
||||
version?: string;
|
||||
}
|
||||
|
||||
interface IOS extends IData<IOS> {
|
||||
name?: string;
|
||||
version?: string;
|
||||
}
|
||||
|
||||
interface IResult extends IData<IResult> {
|
||||
ua: string;
|
||||
browser: IBrowser;
|
||||
cpu: ICPU;
|
||||
device: IDevice;
|
||||
engine: IEngine;
|
||||
os: IOS;
|
||||
}
|
||||
|
||||
type RegexMap = ((RegExp | string | (string | RegExp | Function)[])[])[];
|
||||
type UAParserProps = 'browser' | 'cpu' | 'device' | 'engine' | 'os';
|
||||
type UAParserExt = Partial<Record<UAParserProps, RegexMap>> | Partial<Record<UAParserProps, RegexMap>>[];
|
||||
|
||||
export function UAParser(uastring?: string, extensions?: UAParserExt, headers?: Record<string, string>): IResult;
|
||||
export function UAParser(uastring?: string, headers?: Record<string, string>): IResult;
|
||||
export function UAParser(extensions?: UAParserExt, headers?: Record<string, string>): IResult;
|
||||
export function UAParser(headers?: Record<string, string>): IResult;
|
||||
|
||||
export class UAParser {
|
||||
|
||||
static readonly BROWSER: {
|
||||
NAME: 'name';
|
||||
VERSION: 'version';
|
||||
MAJOR: 'major';
|
||||
TYPE: 'type';
|
||||
};
|
||||
static readonly CPU: {
|
||||
ARCHITECTURE: 'architecture';
|
||||
};
|
||||
static readonly DEVICE: {
|
||||
TYPE: 'type';
|
||||
VENDOR: 'vendor';
|
||||
MODEL: 'model';
|
||||
CONSOLE: 'console';
|
||||
MOBILE: 'mobile';
|
||||
SMARTTV: 'smarttv';
|
||||
TABLET: 'tablet';
|
||||
WEARABLE: 'wearable';
|
||||
XR: 'xr';
|
||||
EMBEDDED: 'embedded';
|
||||
};
|
||||
static readonly ENGINE: {
|
||||
NAME: 'name';
|
||||
VERSION: 'version';
|
||||
};
|
||||
static readonly OS: {
|
||||
NAME: 'name';
|
||||
VERSION: 'version';
|
||||
};
|
||||
static readonly VERSION: string;
|
||||
|
||||
constructor(uastring?: string, extensions?: UAParserExt, headers?: Record<string, string>);
|
||||
constructor(uastring?: string, headers?: Record<string, string>);
|
||||
constructor(extensions?: UAParserExt, headers?: Record<string, string>);
|
||||
constructor(headers?: Record<string, string>);
|
||||
|
||||
getUA(): string;
|
||||
getBrowser(): IBrowser;
|
||||
getCPU(): ICPU;
|
||||
getDevice(): IDevice;
|
||||
getEngine(): IEngine;
|
||||
getOS(): IOS;
|
||||
getResult(): IResult;
|
||||
setUA(uastring: string): UAParser;
|
||||
}
|
||||
}
|
||||
|
||||
export as namespace UAParser;
|
||||
export = UAParser;
|
||||
@@ -1,10 +1,10 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
/* UAParser.js v2.0.0-alpha.3
|
||||
Copyright © 2012-2023 Faisal Salman <f@faisalman.com>
|
||||
MIT License *//*
|
||||
/* UAParser.js v2.0.0-beta.3
|
||||
Copyright © 2012-2024 Faisal Salman <f@faisalman.com>
|
||||
UAParser.js PRO Personal License *//*
|
||||
Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data.
|
||||
Supports browser & node.js environment.
|
||||
Demo : https://faisalman.github.io/ua-parser-js
|
||||
Demo : https://uaparser.dev
|
||||
Source : https://github.com/faisalman/ua-parser-js */
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -19,8 +19,7 @@
|
||||
// Constants
|
||||
/////////////
|
||||
|
||||
|
||||
var LIBVERSION = '2.0.0-alpha.3',
|
||||
var LIBVERSION = '2.0.0-beta.3',
|
||||
EMPTY = '',
|
||||
UNKNOWN = '?',
|
||||
FUNC_TYPE = 'function',
|
||||
@@ -39,10 +38,12 @@
|
||||
TABLET = 'tablet',
|
||||
SMARTTV = 'smarttv',
|
||||
WEARABLE = 'wearable',
|
||||
XR = 'xr',
|
||||
EMBEDDED = 'embedded',
|
||||
USER_AGENT = 'user-agent',
|
||||
UA_MAX_LENGTH = 350,
|
||||
UA_MAX_LENGTH = 500,
|
||||
BRANDS = 'brands',
|
||||
FORMFACTORS = 'formFactors',
|
||||
FULLVERLIST = 'fullVersionList',
|
||||
PLATFORM = 'platform',
|
||||
PLATFORMVER = 'platformVersion',
|
||||
@@ -51,11 +52,12 @@
|
||||
CH_HEADER_FULL_VER_LIST = CH_HEADER + '-full-version-list',
|
||||
CH_HEADER_ARCH = CH_HEADER + '-arch',
|
||||
CH_HEADER_BITNESS = CH_HEADER + '-' + BITNESS,
|
||||
CH_HEADER_FORM_FACTORS = CH_HEADER + '-form-factors',
|
||||
CH_HEADER_MOBILE = CH_HEADER + '-' + MOBILE,
|
||||
CH_HEADER_MODEL = CH_HEADER + '-' + MODEL,
|
||||
CH_HEADER_PLATFORM = CH_HEADER + '-' + PLATFORM,
|
||||
CH_HEADER_PLATFORM_VER = CH_HEADER_PLATFORM + '-version',
|
||||
CH_ALL_VALUES = [BRANDS, FULLVERLIST, MOBILE, MODEL, PLATFORM, PLATFORMVER, ARCHITECTURE, BITNESS],
|
||||
CH_ALL_VALUES = [BRANDS, FULLVERLIST, MOBILE, MODEL, PLATFORM, PLATFORMVER, ARCHITECTURE, FORMFACTORS, BITNESS],
|
||||
UA_BROWSER = 'browser',
|
||||
UA_CPU = 'cpu',
|
||||
UA_DEVICE = 'device',
|
||||
@@ -68,6 +70,7 @@
|
||||
BLACKBERRY = 'BlackBerry',
|
||||
GOOGLE = 'Google',
|
||||
HUAWEI = 'Huawei',
|
||||
LENOVO = 'Lenovo',
|
||||
LG = 'LG',
|
||||
MICROSOFT = 'Microsoft',
|
||||
MOTOROLA = 'Motorola',
|
||||
@@ -83,9 +86,11 @@
|
||||
FIREFOX = 'Firefox',
|
||||
OPERA = 'Opera',
|
||||
FACEBOOK = 'Facebook',
|
||||
SOGOU = 'Sogou',
|
||||
WINDOWS = 'Windows';
|
||||
|
||||
var NAVIGATOR = (typeof window !== UNDEF_TYPE && window.navigator) ?
|
||||
var isWindow = typeof window !== UNDEF_TYPE,
|
||||
NAVIGATOR = (isWindow && window.navigator) ?
|
||||
window.navigator :
|
||||
undefined,
|
||||
NAVIGATOR_UADATA = (NAVIGATOR && NAVIGATOR.userAgentData) ?
|
||||
@@ -96,12 +101,21 @@
|
||||
// Helper
|
||||
//////////
|
||||
|
||||
var extend = function (regexes, extensions) {
|
||||
var mergedRegexes = {};
|
||||
for (var i in regexes) {
|
||||
mergedRegexes[i] = extensions[i] && extensions[i].length % 2 === 0 ? extensions[i].concat(regexes[i]) : regexes[i];
|
||||
var extend = function (defaultRgx, extensions) {
|
||||
var mergedRgx = {};
|
||||
var extraRgx = extensions;
|
||||
if (!isExtensions(extensions)) {
|
||||
extraRgx = {};
|
||||
for (var i in extensions) {
|
||||
for (var j in extensions[i]) {
|
||||
extraRgx[j] = extensions[i][j].concat(extraRgx[j] ? extraRgx[j] : []);
|
||||
}
|
||||
}
|
||||
}
|
||||
return mergedRegexes;
|
||||
for (var k in defaultRgx) {
|
||||
mergedRgx[k] = extraRgx[k] && extraRgx[k].length % 2 === 0 ? extraRgx[k].concat(defaultRgx[k]) : defaultRgx[k];
|
||||
}
|
||||
return mergedRgx;
|
||||
},
|
||||
enumerize = function (arr) {
|
||||
var enums = {};
|
||||
@@ -117,28 +131,35 @@
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return typeof str1 === STR_TYPE ? lowerize(str2).indexOf(lowerize(str1)) !== -1 : false;
|
||||
return isString(str1) ? lowerize(str2).indexOf(lowerize(str1)) !== -1 : false;
|
||||
},
|
||||
isExtensions = function (obj) {
|
||||
isExtensions = function (obj, deep) {
|
||||
for (var prop in obj) {
|
||||
return /^(browser|cpu|device|engine|os)$/.test(prop);
|
||||
return /^(browser|cpu|device|engine|os)$/.test(prop) || (deep ? isExtensions(obj[prop]) : false);
|
||||
}
|
||||
},
|
||||
isString = function (val) {
|
||||
return typeof val === STR_TYPE;
|
||||
},
|
||||
itemListToArray = function (header) {
|
||||
if (!header) return undefined;
|
||||
var arr = [];
|
||||
var tokens = strip(/\\?\"/g, header).split(', ');
|
||||
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] };
|
||||
if (tokens[i].indexOf(';') > -1) {
|
||||
var token = trim(tokens[i]).split(';v=');
|
||||
arr[i] = { brand : token[0], version : token[1] };
|
||||
} else {
|
||||
arr[i] = trim(tokens[i]);
|
||||
}
|
||||
}
|
||||
return arr;
|
||||
},
|
||||
lowerize = function (str) {
|
||||
return typeof(str) === STR_TYPE ? str.toLowerCase() : str;
|
||||
return isString(str) ? str.toLowerCase() : str;
|
||||
},
|
||||
majorize = function (version) {
|
||||
return typeof(version) === STR_TYPE ? strip(/[^\d\.]/g, version).split('.')[0] : undefined;
|
||||
return isString(version) ? strip(/[^\d\.]/g, version).split('.')[0] : undefined;
|
||||
},
|
||||
setProps = function (arr) {
|
||||
for (var i in arr) {
|
||||
@@ -152,15 +173,15 @@
|
||||
return this;
|
||||
},
|
||||
strip = function (pattern, str) {
|
||||
return str.replace(pattern, EMPTY);
|
||||
return isString(str) ? str.replace(pattern, EMPTY) : str;
|
||||
},
|
||||
stripQuotes = function (val) {
|
||||
return typeof val === STR_TYPE ? strip(/\"/g, val) : val;
|
||||
stripQuotes = function (str) {
|
||||
return strip(/\\?\"/g, str);
|
||||
},
|
||||
trim = function (str, len) {
|
||||
if (typeof(str) === STR_TYPE) {
|
||||
if (isString(str)) {
|
||||
str = strip(/^\s\s*/, str);
|
||||
return typeof(len) === UNDEF_TYPE ? str : str.substring(0, UA_MAX_LENGTH);
|
||||
return typeof len === UNDEF_TYPE ? str : str.substring(0, UA_MAX_LENGTH);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -237,7 +258,7 @@
|
||||
return (i === UNKNOWN) ? undefined : i;
|
||||
}
|
||||
}
|
||||
return str;
|
||||
return map.hasOwnProperty('*') ? map['*'] : str;
|
||||
};
|
||||
|
||||
///////////////
|
||||
@@ -256,6 +277,17 @@
|
||||
'8.1' : 'NT 6.3',
|
||||
'10' : ['NT 6.4', 'NT 10.0'],
|
||||
'RT' : 'ARM'
|
||||
},
|
||||
|
||||
formFactorsMap = {
|
||||
'embedded' : 'Automotive',
|
||||
'mobile' : 'Mobile',
|
||||
'tablet' : ['Tablet', 'EInk'],
|
||||
'smarttv' : 'TV',
|
||||
'wearable' : 'Watch',
|
||||
'xr' : ['VR', 'XR'],
|
||||
'?' : ['Desktop', 'Unknown'],
|
||||
'*' : undefined
|
||||
};
|
||||
|
||||
//////////////
|
||||
@@ -279,28 +311,33 @@
|
||||
], [NAME, VERSION], [
|
||||
/opios[\/ ]+([\w\.]+)/i // Opera mini on iphone >= 8.0
|
||||
], [VERSION, [NAME, OPERA+' Mini']], [
|
||||
/\bop(?:rg)?x\/([\w\.]+)/i // Opera GX
|
||||
], [VERSION, [NAME, OPERA+' GX']], [
|
||||
/\bopr\/([\w\.]+)/i // Opera Webkit
|
||||
], [VERSION, [NAME, OPERA]], [
|
||||
|
||||
// Mixed
|
||||
/\bb[ai]*d(?:uhd|[ub]*[aekoprswx]{5,6})[\/ ]?([\w\.]+)/i // Baidu
|
||||
], [VERSION, [NAME, 'Baidu']], [
|
||||
/(kindle)\/([\w\.]+)/i, // Kindle
|
||||
/(lunascape|maxthon|netfront|jasmine|blazer)[\/ ]?([\w\.]*)/i, // Lunascape/Maxthon/Netfront/Jasmine/Blazer
|
||||
/(lunascape|maxthon|netfront|jasmine|blazer|sleipnir)[\/ ]?([\w\.]*)/i,
|
||||
// Lunascape/Maxthon/Netfront/Jasmine/Blazer/Sleipnir
|
||||
// Trident based
|
||||
/(avant |iemobile|slim)(?:browser)?[\/ ]?([\w\.]*)/i, // Avant/IEMobile/SlimBrowser
|
||||
/(ba?idubrowser)[\/ ]?([\w\.]+)/i, // Baidu Browser
|
||||
/(avant|iemobile|slim)\s?(?:browser)?[\/ ]?([\w\.]*)/i, // Avant/IEMobile/SlimBrowser
|
||||
/(?:ms|\()(ie) ([\w\.]+)/i, // Internet Explorer
|
||||
|
||||
// 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,
|
||||
// Rekonq/Puffin/Brave/Whale/QQBrowserLite/QQ//Vivaldi/DuckDuckGo
|
||||
/(flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi|iridium|phantomjs|bowser|quark|qupzilla|falkon|rekonq|puffin|brave|whale(?!.+naver)|qqbrowserlite|duckduckgo|klar)\/([-\w\.]+)/i,
|
||||
// Rekonq/Puffin/Brave/Whale/QQBrowserLite/QQ//Vivaldi/DuckDuckGo/Klar
|
||||
/(heytap|ovi)browser\/([\d\.]+)/i, // HeyTap/Ovi
|
||||
/(weibo)__([\d\.]+)/i // Weibo
|
||||
], [NAME, VERSION], [
|
||||
/\bddg\/([\w\.]+)/i // DuckDuckGo
|
||||
], [VERSION, [NAME, 'DuckDuckGo']], [
|
||||
/(?:\buc? ?browser|(?:juc.+)ucweb)[\/ ]?([\w\.]+)/i // UCBrowser
|
||||
], [VERSION, [NAME, 'UCBrowser']], [
|
||||
/microm.+\bqbcore\/([\w\.]+)/i, // WeChat Desktop for Windows Built-in Browser
|
||||
/\bqbcore\/([\w\.]+).+microm/i
|
||||
], [VERSION, [NAME, 'WeChat(Win) Desktop']], [
|
||||
/\bqbcore\/([\w\.]+).+microm/i,
|
||||
/micromessenger\/([\w\.]+)/i // WeChat
|
||||
], [VERSION, [NAME, 'WeChat']], [
|
||||
/konqueror\/([\w\.]+)/i // Konqueror
|
||||
@@ -309,6 +346,8 @@
|
||||
], [VERSION, [NAME, 'IE']], [
|
||||
/ya(?:search)?browser\/([\w\.]+)/i // Yandex
|
||||
], [VERSION, [NAME, 'Yandex']], [
|
||||
/slbrowser\/([\w\.]+)/i // Smart Lenovo Browser
|
||||
], [VERSION, [NAME, 'Smart ' + LENOVO + SUFFIX_BROWSER]], [
|
||||
/(avast|avg)\/([\w\.]+)/i // Avast/AVG Secure Browser
|
||||
], [[NAME, /(.+)/, '$1 Secure' + SUFFIX_BROWSER], VERSION], [
|
||||
/\bfocus\/([\w\.]+)/i // Firefox Focus
|
||||
@@ -327,26 +366,36 @@
|
||||
], [VERSION, [NAME, PREFIX_MOBILE + FIREFOX]], [
|
||||
/\bqihu|(qi?ho?o?|360)browser/i // 360
|
||||
], [[NAME, '360' + SUFFIX_BROWSER]], [
|
||||
/(oculus|samsung|sailfish|huawei)browser\/([\w\.]+)/i
|
||||
], [[NAME, /(.+)/, '$1' + SUFFIX_BROWSER], VERSION], [ // Oculus/Samsung/Sailfish/Huawei Browser
|
||||
/\b(qq)\/([\w\.]+)/i // QQ
|
||||
], [[NAME, /(.+)/, '$1Browser'], VERSION], [
|
||||
/(oculus|sailfish|huawei|vivo|pico)browser\/([\w\.]+)/i
|
||||
], [[NAME, /(.+)/, '$1' + SUFFIX_BROWSER], VERSION], [ // Oculus/Sailfish/HuaweiBrowser/VivoBrowser/PicoBrowser
|
||||
/samsungbrowser\/([\w\.]+)/i // Samsung Internet
|
||||
], [VERSION, [NAME, SAMSUNG + ' Internet']], [
|
||||
/(comodo_dragon)\/([\w\.]+)/i // Comodo Dragon
|
||||
], [[NAME, /_/g, ' '], VERSION], [
|
||||
/metasr[\/ ]?([\d\.]+)/i // Sogou Explorer
|
||||
], [VERSION, [NAME, SOGOU + ' Explorer']], [
|
||||
/(sogou)mo\w+\/([\d\.]+)/i // Sogou Mobile
|
||||
], [[NAME, SOGOU + ' Mobile'], VERSION], [
|
||||
/(electron)\/([\w\.]+) safari/i, // Electron-based App
|
||||
/(tesla)(?: qtcarbrowser|\/(20\d\d\.[-\w\.]+))/i, // Tesla
|
||||
/m?(qqbrowser|baiduboxapp|2345Explorer)[\/ ]?([\w\.]+)/i // QQBrowser/Baidu App/2345 Browser
|
||||
/m?(qqbrowser|2345Explorer)[\/ ]?([\w\.]+)/i // QQBrowser/2345 Browser
|
||||
], [NAME, VERSION], [
|
||||
/(metasr)[\/ ]?([\w\.]+)/i, // SouGouBrowser
|
||||
/(lbbrowser)/i, // LieBao Browser
|
||||
/(lbbrowser|rekonq)/i, // LieBao Browser/Rekonq
|
||||
/\[(linkedin)app\]/i // LinkedIn App for iOS & Android
|
||||
], [NAME], [
|
||||
|
||||
// WebView
|
||||
/((?:fban\/fbios|fb_iab\/fb4a)(?!.+fbav)|;fbav\/([\w\.]+);)/i // Facebook App for iOS & Android
|
||||
], [[NAME, FACEBOOK], VERSION], [
|
||||
/(Klarna)\/([\w\.]+)/i, // Klarna Shopping Browser for iOS & Android
|
||||
/(kakao(?:talk|story))[\/ ]([\w\.]+)/i, // Kakao App
|
||||
/(naver)\(.*?(\d+\.[\w\.]+).*\)/i, // Naver InApp
|
||||
/safari (line)\/([\w\.]+)/i, // Line App for iOS
|
||||
/\b(line)\/([\w\.]+)\/iab/i, // Line App for Android
|
||||
/(alipay)client\/([\w\.]+)/i, // Alipay
|
||||
/(twitter)(?:and| f.+e\/([\w\.]+))/i, // Twitter
|
||||
/(chromium|instagram|snapchat)[\/ ]([-\w\.]+)/i // Chromium/Instagram/Snapchat
|
||||
], [NAME, VERSION], [
|
||||
/\bgsa\/([\w\.]+) .*safari\//i // Google Search Appliance on iOS
|
||||
@@ -386,23 +435,24 @@
|
||||
], [[NAME, PREFIX_MOBILE + FIREFOX], VERSION], [
|
||||
/(navigator|netscape\d?)\/([-\w\.]+)/i // Netscape
|
||||
], [[NAME, 'Netscape'], VERSION], [
|
||||
/(wolvic)\/([\w\.]+)/i // Wolvic
|
||||
], [NAME, VERSION], [
|
||||
/mobile vr; rv:([\w\.]+)\).+firefox/i // Firefox Reality
|
||||
], [VERSION, [NAME, FIREFOX+' Reality']], [
|
||||
/ekiohf.+(flow)\/([\w\.]+)/i, // Flow
|
||||
/(swiftfox)/i, // Swiftfox
|
||||
/(icedragon|iceweasel|camino|chimera|fennec|maemo browser|minimo|conkeror|klar)[\/ ]?([\w\.\+]+)/i,
|
||||
// IceDragon/Iceweasel/Camino/Chimera/Fennec/Maemo/Minimo/Conkeror/Klar
|
||||
/(icedragon|iceweasel|camino|chimera|fennec|maemo browser|minimo|conkeror)[\/ ]?([\w\.\+]+)/i,
|
||||
// IceDragon/Iceweasel/Camino/Chimera/Fennec/Maemo/Minimo/Conkeror
|
||||
/(seamonkey|k-meleon|icecat|iceape|firebird|phoenix|palemoon|basilisk|waterfox)\/([-\w\.]+)$/i,
|
||||
// Firefox/SeaMonkey/K-Meleon/IceCat/IceApe/Firebird/Phoenix
|
||||
/(firefox)\/([\w\.]+)/i, // Other Firefox-based
|
||||
/(mozilla)\/([\w\.]+) .+rv\:.+gecko\/\d+/i, // Mozilla
|
||||
|
||||
// Other
|
||||
/(polaris|lynx|dillo|icab|doris|amaya|w3m|netsurf|sleipnir|obigo|mosaic|(?:go|ice|up)[\. ]?browser)[-\/ ]?v?([\w\.]+)/i,
|
||||
// Polaris/Lynx/Dillo/iCab/Doris/Amaya/w3m/NetSurf/Sleipnir/Obigo/Mosaic/Go/ICE/UP.Browser
|
||||
/(links) \(([\w\.]+)/i, // Links
|
||||
/panasonic;(viera)/i // Panasonic Viera
|
||||
], [NAME, VERSION], [
|
||||
/(polaris|lynx|dillo|icab|doris|amaya|w3m|netsurf|obigo|mosaic|(?:go|ice|up)[\. ]?browser)[-\/ ]?v?([\w\.]+)/i,
|
||||
// Polaris/Lynx/Dillo/iCab/Doris/Amaya/w3m/NetSurf/Obigo/Mosaic/Go/ICE/UP.Browser
|
||||
/(links) \(([\w\.]+)/i // Links
|
||||
], [NAME, [VERSION, /_/g, '.']], [
|
||||
|
||||
/(cobalt)\/([\w\.]+)/i // Cobalt
|
||||
], [NAME, [VERSION, /[^\d\.]+./, EMPTY]]
|
||||
@@ -478,8 +528,10 @@
|
||||
/\b; (\w+) build\/hm\1/i, // Xiaomi Hongmi 'numeric' models
|
||||
/\b(hm[-_ ]?note?[_ ]?(?:\d\w)?) bui/i, // Xiaomi Hongmi
|
||||
/\b(redmi[\-_ ]?(?:note|k)?[\w_ ]+)(?: bui|\))/i, // Xiaomi Redmi
|
||||
/oid[^\)]+; (m?[12][0-389][01]\w{3,6}[c-y])( bui|; wv|\))/i, // Xiaomi Redmi 'numeric' models
|
||||
/\b(mi[-_ ]?(?:a\d|one|one[_ ]plus|note lte|max|cc)?[_ ]?(?:\d?\w?)[_ ]?(?:plus|se|lite)?)(?: bui|\))/i // Xiaomi Mi
|
||||
], [[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, MOBILE]], [
|
||||
/oid[^\)]+; (2\d{4}(283|rpbf)[cgl])( bui|\))/i, // Redmi Pad
|
||||
/\b(mi[-_ ]?(?:pad)(?:[\w_ ]+))(?: bui|\))/i // Mi Pad tablets
|
||||
],[[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, TABLET]], [
|
||||
|
||||
@@ -487,6 +539,8 @@
|
||||
/; (\w+) bui.+ oppo/i,
|
||||
/\b(cph[12]\d{3}|p(?:af|c[al]|d\w|e[ar])[mt]\d0|x9007|a101op)\b/i
|
||||
], [MODEL, [VENDOR, 'OPPO'], [TYPE, MOBILE]], [
|
||||
/\b(opd2\d{3}a?) bui/i
|
||||
], [MODEL, [VENDOR, 'OPPO'], [TYPE, TABLET]], [
|
||||
|
||||
// Vivo
|
||||
/vivo (\w+)(?: bui|\))/i,
|
||||
@@ -494,7 +548,7 @@
|
||||
], [MODEL, [VENDOR, 'Vivo'], [TYPE, MOBILE]], [
|
||||
|
||||
// Realme
|
||||
/\b(rmx[12]\d{3})(?: bui|;|\))/i
|
||||
/\b(rmx[1-3]\d{3})(?: bui|;|\))/i
|
||||
], [MODEL, [VENDOR, 'Realme'], [TYPE, MOBILE]], [
|
||||
|
||||
// Motorola
|
||||
@@ -516,7 +570,7 @@
|
||||
// Lenovo
|
||||
/(ideatab[-\w ]+)/i,
|
||||
/lenovo ?(s[56]000[-\w]+|tab(?:[\w ]+)|yt[-\d\w]{6}|tb[-\d\w]{6})/i
|
||||
], [MODEL, [VENDOR, 'Lenovo'], [TYPE, TABLET]], [
|
||||
], [MODEL, [VENDOR, LENOVO], [TYPE, TABLET]], [
|
||||
|
||||
// Nokia
|
||||
/(?:maemo|nokia).*(n900|lumia \d+)/i,
|
||||
@@ -580,6 +634,10 @@
|
||||
/droid.+; (m[1-5] note) bui/i,
|
||||
/\bmz-([-\w]{2,})/i
|
||||
], [MODEL, [VENDOR, 'Meizu'], [TYPE, MOBILE]], [
|
||||
|
||||
// Ulefone
|
||||
/; ((?:power )?armor(?:[\w ]{0,8}))(?: bui|\))/i
|
||||
], [MODEL, [VENDOR, 'Ulefone'], [TYPE, MOBILE]], [
|
||||
|
||||
// MIXED
|
||||
/(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus|dell|meizu|motorola|polytron|infinix|tecno)[-_ ]?([-\w]*)/i,
|
||||
@@ -666,12 +724,17 @@
|
||||
], [VENDOR, MODEL, [TYPE, WEARABLE]], [
|
||||
/(watch)(?: ?os[,\/]|\d,\d\/)[\d\.]+/i // Apple Watch
|
||||
], [MODEL, [VENDOR, APPLE], [TYPE, WEARABLE]], [
|
||||
/droid.+; (glass) \d/i // Google Glass
|
||||
], [MODEL, [VENDOR, GOOGLE], [TYPE, WEARABLE]], [
|
||||
/droid.+; (wt63?0{2,3})\)/i
|
||||
], [MODEL, [VENDOR, ZEBRA], [TYPE, WEARABLE]], [
|
||||
/(quest( 2| pro)?)/i // Oculus Quest
|
||||
], [MODEL, [VENDOR, FACEBOOK], [TYPE, WEARABLE]], [
|
||||
|
||||
///////////////////
|
||||
// XR
|
||||
///////////////////
|
||||
|
||||
/droid.+; (glass) \d/i // Google Glass
|
||||
], [MODEL, [VENDOR, GOOGLE], [TYPE, XR]], [
|
||||
/(quest( \d| pro)?)/i // Oculus Quest
|
||||
], [MODEL, [VENDOR, FACEBOOK], [TYPE, XR]], [
|
||||
|
||||
///////////////////
|
||||
// EMBEDDED
|
||||
@@ -686,7 +749,7 @@
|
||||
// MIXED (GENERIC)
|
||||
///////////////////
|
||||
|
||||
/droid .+?; ([^;]+?)(?: bui|\) applew).+? mobile safari/i // Android Phones from Unidentified Vendors
|
||||
/droid .+?; ([^;]+?)(?: bui|; wv\)|\) applew).+? mobile safari/i // Android Phones from Unidentified Vendors
|
||||
], [MODEL, [TYPE, MOBILE]], [
|
||||
/droid .+?; ([^;]+?)(?: bui|\) applew).+?(?! mobile) safari/i // Android Tablets from Unidentified Vendors
|
||||
], [MODEL, [TYPE, TABLET]], [
|
||||
@@ -723,12 +786,12 @@
|
||||
// Windows
|
||||
/microsoft (windows) (vista|xp)/i // Windows (iTunes)
|
||||
], [NAME, VERSION], [
|
||||
/(windows) nt 6\.2; (arm)/i, // Windows RT
|
||||
/(windows (?:phone(?: os)?|mobile))[\/ ]?([\d\.\w ]*)/i, // Windows Phone
|
||||
/(windows)[\/ ]?([ntce\d\. ]+\w)(?!.+xbox)/i
|
||||
/(windows (?:phone(?: os)?|mobile))[\/ ]?([\d\.\w ]*)/i // Windows Phone
|
||||
], [NAME, [VERSION, strMapper, windowsVersionMap]], [
|
||||
/(win(?=3|9|n)|win 9x )([nt\d\.]+)/i
|
||||
], [[NAME, WINDOWS], [VERSION, strMapper, windowsVersionMap]], [
|
||||
/windows nt 6\.2; (arm)/i, // Windows RT
|
||||
/windows[\/ ]?([ntce\d\. ]+\w)(?!.+xbox)/i,
|
||||
/(?:win(?=3|9|n)|win 9x )([nt\d\.]+)/i
|
||||
], [[VERSION, strMapper, windowsVersionMap], [NAME, WINDOWS]], [
|
||||
|
||||
// iOS/macOS
|
||||
/ip[honead]{2,4}\b(?:.*os ([\w]+) like mac|; opera)/i, // iOS
|
||||
@@ -802,7 +865,7 @@
|
||||
var defaultProps = (function () {
|
||||
var props = { init : {}, isIgnore : {}, isIgnoreRgx : {}, toString : {}};
|
||||
setProps.call(props.init, [
|
||||
[UA_BROWSER, [NAME, VERSION, MAJOR]],
|
||||
[UA_BROWSER, [NAME, VERSION, MAJOR, TYPE]],
|
||||
[UA_CPU, [ARCHITECTURE]],
|
||||
[UA_DEVICE, [TYPE, MODEL, VENDOR]],
|
||||
[UA_ENGINE, [NAME, VERSION]],
|
||||
@@ -930,6 +993,7 @@
|
||||
[PLATFORM, stripQuotes(uach[CH_HEADER_PLATFORM])],
|
||||
[PLATFORMVER, stripQuotes(uach[CH_HEADER_PLATFORM_VER])],
|
||||
[ARCHITECTURE, stripQuotes(uach[CH_HEADER_ARCH])],
|
||||
[FORMFACTORS, itemListToArray(uach[CH_HEADER_FORM_FACTORS])],
|
||||
[BITNESS, stripQuotes(uach[CH_HEADER_BITNESS])]
|
||||
]);
|
||||
} else {
|
||||
@@ -1011,21 +1075,21 @@
|
||||
};
|
||||
|
||||
this.parseCH = function () {
|
||||
var ua = this.ua,
|
||||
uaCH = this.uaCH,
|
||||
var uaCH = this.uaCH,
|
||||
rgxMap = this.rgxMap;
|
||||
|
||||
switch (this.itemType) {
|
||||
case UA_BROWSER:
|
||||
var brands = uaCH[FULLVERLIST] || uaCH[BRANDS];
|
||||
var brands = uaCH[FULLVERLIST] || uaCH[BRANDS], prevName;
|
||||
if (brands) {
|
||||
for (var i in brands) {
|
||||
var brandName = brands[i].brand,
|
||||
var brandName = strip(/(Google|Microsoft) /, brands[i].brand || brands[i]),
|
||||
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))
|
||||
if (!/not.a.brand/i.test(brandName) && (!prevName || (/chrom/i.test(prevName) && !/chromi/i.test(brandName)))) {
|
||||
this.set(NAME, brandName)
|
||||
.set(VERSION, brandVersion)
|
||||
.set(MAJOR, majorize(brandVersion));
|
||||
prevName = brandName;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1044,6 +1108,23 @@
|
||||
if (uaCH[MODEL]) {
|
||||
this.set(MODEL, uaCH[MODEL]);
|
||||
}
|
||||
// Xbox-Specific Detection
|
||||
if (uaCH[MODEL] == 'Xbox') {
|
||||
this.set(TYPE, CONSOLE)
|
||||
.set(VENDOR, MICROSOFT);
|
||||
}
|
||||
if (uaCH[FORMFACTORS]) {
|
||||
var ff;
|
||||
if (typeof uaCH[FORMFACTORS] !== 'string') {
|
||||
var idx = 0;
|
||||
while (!ff && idx < uaCH[FORMFACTORS].length) {
|
||||
ff = strMapper(uaCH[FORMFACTORS][idx++], formFactorsMap);
|
||||
}
|
||||
} else {
|
||||
ff = strMapper(uaCH[FORMFACTORS], formFactorsMap);
|
||||
}
|
||||
this.set(TYPE, ff);
|
||||
}
|
||||
break;
|
||||
case UA_OS:
|
||||
var osName = uaCH[PLATFORM];
|
||||
@@ -1053,6 +1134,11 @@
|
||||
this.set(NAME, osName)
|
||||
.set(VERSION, osVersion);
|
||||
}
|
||||
// Xbox-Specific Detection
|
||||
if (this.get(NAME) == WINDOWS && uaCH[MODEL] == 'Xbox') {
|
||||
this.set(NAME, 'Xbox')
|
||||
.set(VERSION, undefined);
|
||||
}
|
||||
break;
|
||||
case UA_RESULT:
|
||||
var data = this.data;
|
||||
@@ -1086,7 +1172,7 @@
|
||||
function UAParser (ua, extensions, headers) {
|
||||
|
||||
if (typeof ua === OBJ_TYPE) {
|
||||
if (isExtensions(ua)) {
|
||||
if (isExtensions(ua, true)) {
|
||||
if (typeof extensions === OBJ_TYPE) {
|
||||
headers = extensions; // case UAParser(extensions, headers)
|
||||
}
|
||||
@@ -1096,7 +1182,7 @@
|
||||
extensions = undefined;
|
||||
}
|
||||
ua = undefined;
|
||||
} else if (typeof ua === STR_TYPE && !isExtensions(extensions)) {
|
||||
} else if (typeof ua === STR_TYPE && !isExtensions(extensions, true)) {
|
||||
headers = extensions; // case UAParser(ua, headers)
|
||||
extensions = undefined;
|
||||
}
|
||||
@@ -1146,7 +1232,7 @@
|
||||
['getResult', createItemFunc(UA_RESULT)],
|
||||
['getUA', function () { return userAgent; }],
|
||||
['setUA', function (ua) {
|
||||
if (typeof ua === STR_TYPE)
|
||||
if (isString(ua))
|
||||
userAgent = ua.length > UA_MAX_LENGTH ? trim(ua, UA_MAX_LENGTH) : ua;
|
||||
return this;
|
||||
}]
|
||||
@@ -1157,7 +1243,7 @@
|
||||
}
|
||||
|
||||
UAParser.VERSION = LIBVERSION;
|
||||
UAParser.BROWSER = enumerize([NAME, VERSION, MAJOR]);
|
||||
UAParser.BROWSER = enumerize([NAME, VERSION, MAJOR, TYPE]);
|
||||
UAParser.CPU = enumerize([ARCHITECTURE]);
|
||||
UAParser.DEVICE = enumerize([MODEL, VENDOR, TYPE, CONSOLE, MOBILE, SMARTTV, TABLET, WEARABLE, EMBEDDED]);
|
||||
UAParser.ENGINE = UAParser.OS = enumerize([NAME, VERSION]);
|
||||
@@ -1167,7 +1253,7 @@
|
||||
//////////
|
||||
|
||||
// check js environment
|
||||
if (typeof(exports) !== UNDEF_TYPE) {
|
||||
if (typeof exports !== UNDEF_TYPE) {
|
||||
// nodejs env
|
||||
if (typeof module !== UNDEF_TYPE && module.exports) {
|
||||
exports = module.exports = UAParser;
|
||||
@@ -1175,11 +1261,11 @@
|
||||
exports.UAParser = UAParser;
|
||||
} else {
|
||||
// requirejs env (optional)
|
||||
if (typeof(define) === FUNC_TYPE && define.amd) {
|
||||
if (typeof define === FUNC_TYPE && define.amd) {
|
||||
define(function () {
|
||||
return UAParser;
|
||||
});
|
||||
} else if (typeof window !== UNDEF_TYPE) {
|
||||
} else if (isWindow) {
|
||||
// browser env
|
||||
window.UAParser = UAParser;
|
||||
}
|
||||
@@ -1190,7 +1276,7 @@
|
||||
// In AMD env the global scope should be kept clean, but jQuery is an exception.
|
||||
// jQuery always exports to global scope, unless jQuery.noConflict(true) is used,
|
||||
// and we should catch that.
|
||||
var $ = typeof window !== UNDEF_TYPE && (window.jQuery || window.Zepto);
|
||||
var $ = isWindow && (window.jQuery || window.Zepto);
|
||||
if ($ && !$.ua) {
|
||||
var parser = new UAParser();
|
||||
$.ua = parser.getResult();
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
// Generated ESM version of UAParser.js
|
||||
// Generated ESM version of ua-parser-js
|
||||
// DO NOT EDIT THIS FILE!
|
||||
// Source: /src/main/ua-parser.js
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
/* UAParser.js v2.0.0-alpha.3
|
||||
Copyright © 2012-2023 Faisal Salman <f@faisalman.com>
|
||||
MIT License *//*
|
||||
/* UAParser.js v2.0.0-beta.3
|
||||
Copyright © 2012-2024 Faisal Salman <f@faisalman.com>
|
||||
UAParser.js PRO Personal License *//*
|
||||
Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data.
|
||||
Supports browser & node.js environment.
|
||||
Demo : https://faisalman.github.io/ua-parser-js
|
||||
Demo : https://uaparser.dev
|
||||
Source : https://github.com/faisalman/ua-parser-js */
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -21,8 +21,7 @@
|
||||
// Constants
|
||||
/////////////
|
||||
|
||||
|
||||
var LIBVERSION = '2.0.0-alpha.3',
|
||||
var LIBVERSION = '2.0.0-beta.3',
|
||||
EMPTY = '',
|
||||
UNKNOWN = '?',
|
||||
FUNC_TYPE = 'function',
|
||||
@@ -41,10 +40,12 @@
|
||||
TABLET = 'tablet',
|
||||
SMARTTV = 'smarttv',
|
||||
WEARABLE = 'wearable',
|
||||
XR = 'xr',
|
||||
EMBEDDED = 'embedded',
|
||||
USER_AGENT = 'user-agent',
|
||||
UA_MAX_LENGTH = 350,
|
||||
UA_MAX_LENGTH = 500,
|
||||
BRANDS = 'brands',
|
||||
FORMFACTORS = 'formFactors',
|
||||
FULLVERLIST = 'fullVersionList',
|
||||
PLATFORM = 'platform',
|
||||
PLATFORMVER = 'platformVersion',
|
||||
@@ -53,11 +54,12 @@
|
||||
CH_HEADER_FULL_VER_LIST = CH_HEADER + '-full-version-list',
|
||||
CH_HEADER_ARCH = CH_HEADER + '-arch',
|
||||
CH_HEADER_BITNESS = CH_HEADER + '-' + BITNESS,
|
||||
CH_HEADER_FORM_FACTORS = CH_HEADER + '-form-factors',
|
||||
CH_HEADER_MOBILE = CH_HEADER + '-' + MOBILE,
|
||||
CH_HEADER_MODEL = CH_HEADER + '-' + MODEL,
|
||||
CH_HEADER_PLATFORM = CH_HEADER + '-' + PLATFORM,
|
||||
CH_HEADER_PLATFORM_VER = CH_HEADER_PLATFORM + '-version',
|
||||
CH_ALL_VALUES = [BRANDS, FULLVERLIST, MOBILE, MODEL, PLATFORM, PLATFORMVER, ARCHITECTURE, BITNESS],
|
||||
CH_ALL_VALUES = [BRANDS, FULLVERLIST, MOBILE, MODEL, PLATFORM, PLATFORMVER, ARCHITECTURE, FORMFACTORS, BITNESS],
|
||||
UA_BROWSER = 'browser',
|
||||
UA_CPU = 'cpu',
|
||||
UA_DEVICE = 'device',
|
||||
@@ -70,6 +72,7 @@
|
||||
BLACKBERRY = 'BlackBerry',
|
||||
GOOGLE = 'Google',
|
||||
HUAWEI = 'Huawei',
|
||||
LENOVO = 'Lenovo',
|
||||
LG = 'LG',
|
||||
MICROSOFT = 'Microsoft',
|
||||
MOTOROLA = 'Motorola',
|
||||
@@ -85,9 +88,11 @@
|
||||
FIREFOX = 'Firefox',
|
||||
OPERA = 'Opera',
|
||||
FACEBOOK = 'Facebook',
|
||||
SOGOU = 'Sogou',
|
||||
WINDOWS = 'Windows';
|
||||
|
||||
var NAVIGATOR = (typeof window !== UNDEF_TYPE && window.navigator) ?
|
||||
var isWindow = typeof window !== UNDEF_TYPE,
|
||||
NAVIGATOR = (isWindow && window.navigator) ?
|
||||
window.navigator :
|
||||
undefined,
|
||||
NAVIGATOR_UADATA = (NAVIGATOR && NAVIGATOR.userAgentData) ?
|
||||
@@ -98,12 +103,21 @@
|
||||
// Helper
|
||||
//////////
|
||||
|
||||
var extend = function (regexes, extensions) {
|
||||
var mergedRegexes = {};
|
||||
for (var i in regexes) {
|
||||
mergedRegexes[i] = extensions[i] && extensions[i].length % 2 === 0 ? extensions[i].concat(regexes[i]) : regexes[i];
|
||||
var extend = function (defaultRgx, extensions) {
|
||||
var mergedRgx = {};
|
||||
var extraRgx = extensions;
|
||||
if (!isExtensions(extensions)) {
|
||||
extraRgx = {};
|
||||
for (var i in extensions) {
|
||||
for (var j in extensions[i]) {
|
||||
extraRgx[j] = extensions[i][j].concat(extraRgx[j] ? extraRgx[j] : []);
|
||||
}
|
||||
}
|
||||
}
|
||||
return mergedRegexes;
|
||||
for (var k in defaultRgx) {
|
||||
mergedRgx[k] = extraRgx[k] && extraRgx[k].length % 2 === 0 ? extraRgx[k].concat(defaultRgx[k]) : defaultRgx[k];
|
||||
}
|
||||
return mergedRgx;
|
||||
},
|
||||
enumerize = function (arr) {
|
||||
var enums = {};
|
||||
@@ -119,28 +133,35 @@
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return typeof str1 === STR_TYPE ? lowerize(str2).indexOf(lowerize(str1)) !== -1 : false;
|
||||
return isString(str1) ? lowerize(str2).indexOf(lowerize(str1)) !== -1 : false;
|
||||
},
|
||||
isExtensions = function (obj) {
|
||||
isExtensions = function (obj, deep) {
|
||||
for (var prop in obj) {
|
||||
return /^(browser|cpu|device|engine|os)$/.test(prop);
|
||||
return /^(browser|cpu|device|engine|os)$/.test(prop) || (deep ? isExtensions(obj[prop]) : false);
|
||||
}
|
||||
},
|
||||
isString = function (val) {
|
||||
return typeof val === STR_TYPE;
|
||||
},
|
||||
itemListToArray = function (header) {
|
||||
if (!header) return undefined;
|
||||
var arr = [];
|
||||
var tokens = strip(/\\?\"/g, header).split(', ');
|
||||
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] };
|
||||
if (tokens[i].indexOf(';') > -1) {
|
||||
var token = trim(tokens[i]).split(';v=');
|
||||
arr[i] = { brand : token[0], version : token[1] };
|
||||
} else {
|
||||
arr[i] = trim(tokens[i]);
|
||||
}
|
||||
}
|
||||
return arr;
|
||||
},
|
||||
lowerize = function (str) {
|
||||
return typeof(str) === STR_TYPE ? str.toLowerCase() : str;
|
||||
return isString(str) ? str.toLowerCase() : str;
|
||||
},
|
||||
majorize = function (version) {
|
||||
return typeof(version) === STR_TYPE ? strip(/[^\d\.]/g, version).split('.')[0] : undefined;
|
||||
return isString(version) ? strip(/[^\d\.]/g, version).split('.')[0] : undefined;
|
||||
},
|
||||
setProps = function (arr) {
|
||||
for (var i in arr) {
|
||||
@@ -154,15 +175,15 @@
|
||||
return this;
|
||||
},
|
||||
strip = function (pattern, str) {
|
||||
return str.replace(pattern, EMPTY);
|
||||
return isString(str) ? str.replace(pattern, EMPTY) : str;
|
||||
},
|
||||
stripQuotes = function (val) {
|
||||
return typeof val === STR_TYPE ? strip(/\"/g, val) : val;
|
||||
stripQuotes = function (str) {
|
||||
return strip(/\\?\"/g, str);
|
||||
},
|
||||
trim = function (str, len) {
|
||||
if (typeof(str) === STR_TYPE) {
|
||||
if (isString(str)) {
|
||||
str = strip(/^\s\s*/, str);
|
||||
return typeof(len) === UNDEF_TYPE ? str : str.substring(0, UA_MAX_LENGTH);
|
||||
return typeof len === UNDEF_TYPE ? str : str.substring(0, UA_MAX_LENGTH);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -239,7 +260,7 @@
|
||||
return (i === UNKNOWN) ? undefined : i;
|
||||
}
|
||||
}
|
||||
return str;
|
||||
return map.hasOwnProperty('*') ? map['*'] : str;
|
||||
};
|
||||
|
||||
///////////////
|
||||
@@ -258,6 +279,17 @@
|
||||
'8.1' : 'NT 6.3',
|
||||
'10' : ['NT 6.4', 'NT 10.0'],
|
||||
'RT' : 'ARM'
|
||||
},
|
||||
|
||||
formFactorsMap = {
|
||||
'embedded' : 'Automotive',
|
||||
'mobile' : 'Mobile',
|
||||
'tablet' : ['Tablet', 'EInk'],
|
||||
'smarttv' : 'TV',
|
||||
'wearable' : 'Watch',
|
||||
'xr' : ['VR', 'XR'],
|
||||
'?' : ['Desktop', 'Unknown'],
|
||||
'*' : undefined
|
||||
};
|
||||
|
||||
//////////////
|
||||
@@ -281,28 +313,33 @@
|
||||
], [NAME, VERSION], [
|
||||
/opios[\/ ]+([\w\.]+)/i // Opera mini on iphone >= 8.0
|
||||
], [VERSION, [NAME, OPERA+' Mini']], [
|
||||
/\bop(?:rg)?x\/([\w\.]+)/i // Opera GX
|
||||
], [VERSION, [NAME, OPERA+' GX']], [
|
||||
/\bopr\/([\w\.]+)/i // Opera Webkit
|
||||
], [VERSION, [NAME, OPERA]], [
|
||||
|
||||
// Mixed
|
||||
/\bb[ai]*d(?:uhd|[ub]*[aekoprswx]{5,6})[\/ ]?([\w\.]+)/i // Baidu
|
||||
], [VERSION, [NAME, 'Baidu']], [
|
||||
/(kindle)\/([\w\.]+)/i, // Kindle
|
||||
/(lunascape|maxthon|netfront|jasmine|blazer)[\/ ]?([\w\.]*)/i, // Lunascape/Maxthon/Netfront/Jasmine/Blazer
|
||||
/(lunascape|maxthon|netfront|jasmine|blazer|sleipnir)[\/ ]?([\w\.]*)/i,
|
||||
// Lunascape/Maxthon/Netfront/Jasmine/Blazer/Sleipnir
|
||||
// Trident based
|
||||
/(avant |iemobile|slim)(?:browser)?[\/ ]?([\w\.]*)/i, // Avant/IEMobile/SlimBrowser
|
||||
/(ba?idubrowser)[\/ ]?([\w\.]+)/i, // Baidu Browser
|
||||
/(avant|iemobile|slim)\s?(?:browser)?[\/ ]?([\w\.]*)/i, // Avant/IEMobile/SlimBrowser
|
||||
/(?:ms|\()(ie) ([\w\.]+)/i, // Internet Explorer
|
||||
|
||||
// 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,
|
||||
// Rekonq/Puffin/Brave/Whale/QQBrowserLite/QQ//Vivaldi/DuckDuckGo
|
||||
/(flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi|iridium|phantomjs|bowser|quark|qupzilla|falkon|rekonq|puffin|brave|whale(?!.+naver)|qqbrowserlite|duckduckgo|klar)\/([-\w\.]+)/i,
|
||||
// Rekonq/Puffin/Brave/Whale/QQBrowserLite/QQ//Vivaldi/DuckDuckGo/Klar
|
||||
/(heytap|ovi)browser\/([\d\.]+)/i, // HeyTap/Ovi
|
||||
/(weibo)__([\d\.]+)/i // Weibo
|
||||
], [NAME, VERSION], [
|
||||
/\bddg\/([\w\.]+)/i // DuckDuckGo
|
||||
], [VERSION, [NAME, 'DuckDuckGo']], [
|
||||
/(?:\buc? ?browser|(?:juc.+)ucweb)[\/ ]?([\w\.]+)/i // UCBrowser
|
||||
], [VERSION, [NAME, 'UCBrowser']], [
|
||||
/microm.+\bqbcore\/([\w\.]+)/i, // WeChat Desktop for Windows Built-in Browser
|
||||
/\bqbcore\/([\w\.]+).+microm/i
|
||||
], [VERSION, [NAME, 'WeChat(Win) Desktop']], [
|
||||
/\bqbcore\/([\w\.]+).+microm/i,
|
||||
/micromessenger\/([\w\.]+)/i // WeChat
|
||||
], [VERSION, [NAME, 'WeChat']], [
|
||||
/konqueror\/([\w\.]+)/i // Konqueror
|
||||
@@ -311,6 +348,8 @@
|
||||
], [VERSION, [NAME, 'IE']], [
|
||||
/ya(?:search)?browser\/([\w\.]+)/i // Yandex
|
||||
], [VERSION, [NAME, 'Yandex']], [
|
||||
/slbrowser\/([\w\.]+)/i // Smart Lenovo Browser
|
||||
], [VERSION, [NAME, 'Smart ' + LENOVO + SUFFIX_BROWSER]], [
|
||||
/(avast|avg)\/([\w\.]+)/i // Avast/AVG Secure Browser
|
||||
], [[NAME, /(.+)/, '$1 Secure' + SUFFIX_BROWSER], VERSION], [
|
||||
/\bfocus\/([\w\.]+)/i // Firefox Focus
|
||||
@@ -329,26 +368,36 @@
|
||||
], [VERSION, [NAME, PREFIX_MOBILE + FIREFOX]], [
|
||||
/\bqihu|(qi?ho?o?|360)browser/i // 360
|
||||
], [[NAME, '360' + SUFFIX_BROWSER]], [
|
||||
/(oculus|samsung|sailfish|huawei)browser\/([\w\.]+)/i
|
||||
], [[NAME, /(.+)/, '$1' + SUFFIX_BROWSER], VERSION], [ // Oculus/Samsung/Sailfish/Huawei Browser
|
||||
/\b(qq)\/([\w\.]+)/i // QQ
|
||||
], [[NAME, /(.+)/, '$1Browser'], VERSION], [
|
||||
/(oculus|sailfish|huawei|vivo|pico)browser\/([\w\.]+)/i
|
||||
], [[NAME, /(.+)/, '$1' + SUFFIX_BROWSER], VERSION], [ // Oculus/Sailfish/HuaweiBrowser/VivoBrowser/PicoBrowser
|
||||
/samsungbrowser\/([\w\.]+)/i // Samsung Internet
|
||||
], [VERSION, [NAME, SAMSUNG + ' Internet']], [
|
||||
/(comodo_dragon)\/([\w\.]+)/i // Comodo Dragon
|
||||
], [[NAME, /_/g, ' '], VERSION], [
|
||||
/metasr[\/ ]?([\d\.]+)/i // Sogou Explorer
|
||||
], [VERSION, [NAME, SOGOU + ' Explorer']], [
|
||||
/(sogou)mo\w+\/([\d\.]+)/i // Sogou Mobile
|
||||
], [[NAME, SOGOU + ' Mobile'], VERSION], [
|
||||
/(electron)\/([\w\.]+) safari/i, // Electron-based App
|
||||
/(tesla)(?: qtcarbrowser|\/(20\d\d\.[-\w\.]+))/i, // Tesla
|
||||
/m?(qqbrowser|baiduboxapp|2345Explorer)[\/ ]?([\w\.]+)/i // QQBrowser/Baidu App/2345 Browser
|
||||
/m?(qqbrowser|2345Explorer)[\/ ]?([\w\.]+)/i // QQBrowser/2345 Browser
|
||||
], [NAME, VERSION], [
|
||||
/(metasr)[\/ ]?([\w\.]+)/i, // SouGouBrowser
|
||||
/(lbbrowser)/i, // LieBao Browser
|
||||
/(lbbrowser|rekonq)/i, // LieBao Browser/Rekonq
|
||||
/\[(linkedin)app\]/i // LinkedIn App for iOS & Android
|
||||
], [NAME], [
|
||||
|
||||
// WebView
|
||||
/((?:fban\/fbios|fb_iab\/fb4a)(?!.+fbav)|;fbav\/([\w\.]+);)/i // Facebook App for iOS & Android
|
||||
], [[NAME, FACEBOOK], VERSION], [
|
||||
/(Klarna)\/([\w\.]+)/i, // Klarna Shopping Browser for iOS & Android
|
||||
/(kakao(?:talk|story))[\/ ]([\w\.]+)/i, // Kakao App
|
||||
/(naver)\(.*?(\d+\.[\w\.]+).*\)/i, // Naver InApp
|
||||
/safari (line)\/([\w\.]+)/i, // Line App for iOS
|
||||
/\b(line)\/([\w\.]+)\/iab/i, // Line App for Android
|
||||
/(alipay)client\/([\w\.]+)/i, // Alipay
|
||||
/(twitter)(?:and| f.+e\/([\w\.]+))/i, // Twitter
|
||||
/(chromium|instagram|snapchat)[\/ ]([-\w\.]+)/i // Chromium/Instagram/Snapchat
|
||||
], [NAME, VERSION], [
|
||||
/\bgsa\/([\w\.]+) .*safari\//i // Google Search Appliance on iOS
|
||||
@@ -388,23 +437,24 @@
|
||||
], [[NAME, PREFIX_MOBILE + FIREFOX], VERSION], [
|
||||
/(navigator|netscape\d?)\/([-\w\.]+)/i // Netscape
|
||||
], [[NAME, 'Netscape'], VERSION], [
|
||||
/(wolvic)\/([\w\.]+)/i // Wolvic
|
||||
], [NAME, VERSION], [
|
||||
/mobile vr; rv:([\w\.]+)\).+firefox/i // Firefox Reality
|
||||
], [VERSION, [NAME, FIREFOX+' Reality']], [
|
||||
/ekiohf.+(flow)\/([\w\.]+)/i, // Flow
|
||||
/(swiftfox)/i, // Swiftfox
|
||||
/(icedragon|iceweasel|camino|chimera|fennec|maemo browser|minimo|conkeror|klar)[\/ ]?([\w\.\+]+)/i,
|
||||
// IceDragon/Iceweasel/Camino/Chimera/Fennec/Maemo/Minimo/Conkeror/Klar
|
||||
/(icedragon|iceweasel|camino|chimera|fennec|maemo browser|minimo|conkeror)[\/ ]?([\w\.\+]+)/i,
|
||||
// IceDragon/Iceweasel/Camino/Chimera/Fennec/Maemo/Minimo/Conkeror
|
||||
/(seamonkey|k-meleon|icecat|iceape|firebird|phoenix|palemoon|basilisk|waterfox)\/([-\w\.]+)$/i,
|
||||
// Firefox/SeaMonkey/K-Meleon/IceCat/IceApe/Firebird/Phoenix
|
||||
/(firefox)\/([\w\.]+)/i, // Other Firefox-based
|
||||
/(mozilla)\/([\w\.]+) .+rv\:.+gecko\/\d+/i, // Mozilla
|
||||
|
||||
// Other
|
||||
/(polaris|lynx|dillo|icab|doris|amaya|w3m|netsurf|sleipnir|obigo|mosaic|(?:go|ice|up)[\. ]?browser)[-\/ ]?v?([\w\.]+)/i,
|
||||
// Polaris/Lynx/Dillo/iCab/Doris/Amaya/w3m/NetSurf/Sleipnir/Obigo/Mosaic/Go/ICE/UP.Browser
|
||||
/(links) \(([\w\.]+)/i, // Links
|
||||
/panasonic;(viera)/i // Panasonic Viera
|
||||
], [NAME, VERSION], [
|
||||
/(polaris|lynx|dillo|icab|doris|amaya|w3m|netsurf|obigo|mosaic|(?:go|ice|up)[\. ]?browser)[-\/ ]?v?([\w\.]+)/i,
|
||||
// Polaris/Lynx/Dillo/iCab/Doris/Amaya/w3m/NetSurf/Obigo/Mosaic/Go/ICE/UP.Browser
|
||||
/(links) \(([\w\.]+)/i // Links
|
||||
], [NAME, [VERSION, /_/g, '.']], [
|
||||
|
||||
/(cobalt)\/([\w\.]+)/i // Cobalt
|
||||
], [NAME, [VERSION, /[^\d\.]+./, EMPTY]]
|
||||
@@ -480,8 +530,10 @@
|
||||
/\b; (\w+) build\/hm\1/i, // Xiaomi Hongmi 'numeric' models
|
||||
/\b(hm[-_ ]?note?[_ ]?(?:\d\w)?) bui/i, // Xiaomi Hongmi
|
||||
/\b(redmi[\-_ ]?(?:note|k)?[\w_ ]+)(?: bui|\))/i, // Xiaomi Redmi
|
||||
/oid[^\)]+; (m?[12][0-389][01]\w{3,6}[c-y])( bui|; wv|\))/i, // Xiaomi Redmi 'numeric' models
|
||||
/\b(mi[-_ ]?(?:a\d|one|one[_ ]plus|note lte|max|cc)?[_ ]?(?:\d?\w?)[_ ]?(?:plus|se|lite)?)(?: bui|\))/i // Xiaomi Mi
|
||||
], [[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, MOBILE]], [
|
||||
/oid[^\)]+; (2\d{4}(283|rpbf)[cgl])( bui|\))/i, // Redmi Pad
|
||||
/\b(mi[-_ ]?(?:pad)(?:[\w_ ]+))(?: bui|\))/i // Mi Pad tablets
|
||||
],[[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, TABLET]], [
|
||||
|
||||
@@ -489,6 +541,8 @@
|
||||
/; (\w+) bui.+ oppo/i,
|
||||
/\b(cph[12]\d{3}|p(?:af|c[al]|d\w|e[ar])[mt]\d0|x9007|a101op)\b/i
|
||||
], [MODEL, [VENDOR, 'OPPO'], [TYPE, MOBILE]], [
|
||||
/\b(opd2\d{3}a?) bui/i
|
||||
], [MODEL, [VENDOR, 'OPPO'], [TYPE, TABLET]], [
|
||||
|
||||
// Vivo
|
||||
/vivo (\w+)(?: bui|\))/i,
|
||||
@@ -496,7 +550,7 @@
|
||||
], [MODEL, [VENDOR, 'Vivo'], [TYPE, MOBILE]], [
|
||||
|
||||
// Realme
|
||||
/\b(rmx[12]\d{3})(?: bui|;|\))/i
|
||||
/\b(rmx[1-3]\d{3})(?: bui|;|\))/i
|
||||
], [MODEL, [VENDOR, 'Realme'], [TYPE, MOBILE]], [
|
||||
|
||||
// Motorola
|
||||
@@ -518,7 +572,7 @@
|
||||
// Lenovo
|
||||
/(ideatab[-\w ]+)/i,
|
||||
/lenovo ?(s[56]000[-\w]+|tab(?:[\w ]+)|yt[-\d\w]{6}|tb[-\d\w]{6})/i
|
||||
], [MODEL, [VENDOR, 'Lenovo'], [TYPE, TABLET]], [
|
||||
], [MODEL, [VENDOR, LENOVO], [TYPE, TABLET]], [
|
||||
|
||||
// Nokia
|
||||
/(?:maemo|nokia).*(n900|lumia \d+)/i,
|
||||
@@ -582,6 +636,10 @@
|
||||
/droid.+; (m[1-5] note) bui/i,
|
||||
/\bmz-([-\w]{2,})/i
|
||||
], [MODEL, [VENDOR, 'Meizu'], [TYPE, MOBILE]], [
|
||||
|
||||
// Ulefone
|
||||
/; ((?:power )?armor(?:[\w ]{0,8}))(?: bui|\))/i
|
||||
], [MODEL, [VENDOR, 'Ulefone'], [TYPE, MOBILE]], [
|
||||
|
||||
// MIXED
|
||||
/(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus|dell|meizu|motorola|polytron|infinix|tecno)[-_ ]?([-\w]*)/i,
|
||||
@@ -668,12 +726,17 @@
|
||||
], [VENDOR, MODEL, [TYPE, WEARABLE]], [
|
||||
/(watch)(?: ?os[,\/]|\d,\d\/)[\d\.]+/i // Apple Watch
|
||||
], [MODEL, [VENDOR, APPLE], [TYPE, WEARABLE]], [
|
||||
/droid.+; (glass) \d/i // Google Glass
|
||||
], [MODEL, [VENDOR, GOOGLE], [TYPE, WEARABLE]], [
|
||||
/droid.+; (wt63?0{2,3})\)/i
|
||||
], [MODEL, [VENDOR, ZEBRA], [TYPE, WEARABLE]], [
|
||||
/(quest( 2| pro)?)/i // Oculus Quest
|
||||
], [MODEL, [VENDOR, FACEBOOK], [TYPE, WEARABLE]], [
|
||||
|
||||
///////////////////
|
||||
// XR
|
||||
///////////////////
|
||||
|
||||
/droid.+; (glass) \d/i // Google Glass
|
||||
], [MODEL, [VENDOR, GOOGLE], [TYPE, XR]], [
|
||||
/(quest( \d| pro)?)/i // Oculus Quest
|
||||
], [MODEL, [VENDOR, FACEBOOK], [TYPE, XR]], [
|
||||
|
||||
///////////////////
|
||||
// EMBEDDED
|
||||
@@ -688,7 +751,7 @@
|
||||
// MIXED (GENERIC)
|
||||
///////////////////
|
||||
|
||||
/droid .+?; ([^;]+?)(?: bui|\) applew).+? mobile safari/i // Android Phones from Unidentified Vendors
|
||||
/droid .+?; ([^;]+?)(?: bui|; wv\)|\) applew).+? mobile safari/i // Android Phones from Unidentified Vendors
|
||||
], [MODEL, [TYPE, MOBILE]], [
|
||||
/droid .+?; ([^;]+?)(?: bui|\) applew).+?(?! mobile) safari/i // Android Tablets from Unidentified Vendors
|
||||
], [MODEL, [TYPE, TABLET]], [
|
||||
@@ -725,12 +788,12 @@
|
||||
// Windows
|
||||
/microsoft (windows) (vista|xp)/i // Windows (iTunes)
|
||||
], [NAME, VERSION], [
|
||||
/(windows) nt 6\.2; (arm)/i, // Windows RT
|
||||
/(windows (?:phone(?: os)?|mobile))[\/ ]?([\d\.\w ]*)/i, // Windows Phone
|
||||
/(windows)[\/ ]?([ntce\d\. ]+\w)(?!.+xbox)/i
|
||||
/(windows (?:phone(?: os)?|mobile))[\/ ]?([\d\.\w ]*)/i // Windows Phone
|
||||
], [NAME, [VERSION, strMapper, windowsVersionMap]], [
|
||||
/(win(?=3|9|n)|win 9x )([nt\d\.]+)/i
|
||||
], [[NAME, WINDOWS], [VERSION, strMapper, windowsVersionMap]], [
|
||||
/windows nt 6\.2; (arm)/i, // Windows RT
|
||||
/windows[\/ ]?([ntce\d\. ]+\w)(?!.+xbox)/i,
|
||||
/(?:win(?=3|9|n)|win 9x )([nt\d\.]+)/i
|
||||
], [[VERSION, strMapper, windowsVersionMap], [NAME, WINDOWS]], [
|
||||
|
||||
// iOS/macOS
|
||||
/ip[honead]{2,4}\b(?:.*os ([\w]+) like mac|; opera)/i, // iOS
|
||||
@@ -804,7 +867,7 @@
|
||||
var defaultProps = (function () {
|
||||
var props = { init : {}, isIgnore : {}, isIgnoreRgx : {}, toString : {}};
|
||||
setProps.call(props.init, [
|
||||
[UA_BROWSER, [NAME, VERSION, MAJOR]],
|
||||
[UA_BROWSER, [NAME, VERSION, MAJOR, TYPE]],
|
||||
[UA_CPU, [ARCHITECTURE]],
|
||||
[UA_DEVICE, [TYPE, MODEL, VENDOR]],
|
||||
[UA_ENGINE, [NAME, VERSION]],
|
||||
@@ -932,6 +995,7 @@
|
||||
[PLATFORM, stripQuotes(uach[CH_HEADER_PLATFORM])],
|
||||
[PLATFORMVER, stripQuotes(uach[CH_HEADER_PLATFORM_VER])],
|
||||
[ARCHITECTURE, stripQuotes(uach[CH_HEADER_ARCH])],
|
||||
[FORMFACTORS, itemListToArray(uach[CH_HEADER_FORM_FACTORS])],
|
||||
[BITNESS, stripQuotes(uach[CH_HEADER_BITNESS])]
|
||||
]);
|
||||
} else {
|
||||
@@ -1013,21 +1077,21 @@
|
||||
};
|
||||
|
||||
this.parseCH = function () {
|
||||
var ua = this.ua,
|
||||
uaCH = this.uaCH,
|
||||
var uaCH = this.uaCH,
|
||||
rgxMap = this.rgxMap;
|
||||
|
||||
switch (this.itemType) {
|
||||
case UA_BROWSER:
|
||||
var brands = uaCH[FULLVERLIST] || uaCH[BRANDS];
|
||||
var brands = uaCH[FULLVERLIST] || uaCH[BRANDS], prevName;
|
||||
if (brands) {
|
||||
for (var i in brands) {
|
||||
var brandName = brands[i].brand,
|
||||
var brandName = strip(/(Google|Microsoft) /, brands[i].brand || brands[i]),
|
||||
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))
|
||||
if (!/not.a.brand/i.test(brandName) && (!prevName || (/chrom/i.test(prevName) && !/chromi/i.test(brandName)))) {
|
||||
this.set(NAME, brandName)
|
||||
.set(VERSION, brandVersion)
|
||||
.set(MAJOR, majorize(brandVersion));
|
||||
prevName = brandName;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1046,6 +1110,23 @@
|
||||
if (uaCH[MODEL]) {
|
||||
this.set(MODEL, uaCH[MODEL]);
|
||||
}
|
||||
// Xbox-Specific Detection
|
||||
if (uaCH[MODEL] == 'Xbox') {
|
||||
this.set(TYPE, CONSOLE)
|
||||
.set(VENDOR, MICROSOFT);
|
||||
}
|
||||
if (uaCH[FORMFACTORS]) {
|
||||
var ff;
|
||||
if (typeof uaCH[FORMFACTORS] !== 'string') {
|
||||
var idx = 0;
|
||||
while (!ff && idx < uaCH[FORMFACTORS].length) {
|
||||
ff = strMapper(uaCH[FORMFACTORS][idx++], formFactorsMap);
|
||||
}
|
||||
} else {
|
||||
ff = strMapper(uaCH[FORMFACTORS], formFactorsMap);
|
||||
}
|
||||
this.set(TYPE, ff);
|
||||
}
|
||||
break;
|
||||
case UA_OS:
|
||||
var osName = uaCH[PLATFORM];
|
||||
@@ -1055,6 +1136,11 @@
|
||||
this.set(NAME, osName)
|
||||
.set(VERSION, osVersion);
|
||||
}
|
||||
// Xbox-Specific Detection
|
||||
if (this.get(NAME) == WINDOWS && uaCH[MODEL] == 'Xbox') {
|
||||
this.set(NAME, 'Xbox')
|
||||
.set(VERSION, undefined);
|
||||
}
|
||||
break;
|
||||
case UA_RESULT:
|
||||
var data = this.data;
|
||||
@@ -1088,7 +1174,7 @@
|
||||
function UAParser (ua, extensions, headers) {
|
||||
|
||||
if (typeof ua === OBJ_TYPE) {
|
||||
if (isExtensions(ua)) {
|
||||
if (isExtensions(ua, true)) {
|
||||
if (typeof extensions === OBJ_TYPE) {
|
||||
headers = extensions; // case UAParser(extensions, headers)
|
||||
}
|
||||
@@ -1098,7 +1184,7 @@
|
||||
extensions = undefined;
|
||||
}
|
||||
ua = undefined;
|
||||
} else if (typeof ua === STR_TYPE && !isExtensions(extensions)) {
|
||||
} else if (typeof ua === STR_TYPE && !isExtensions(extensions, true)) {
|
||||
headers = extensions; // case UAParser(ua, headers)
|
||||
extensions = undefined;
|
||||
}
|
||||
@@ -1148,7 +1234,7 @@
|
||||
['getResult', createItemFunc(UA_RESULT)],
|
||||
['getUA', function () { return userAgent; }],
|
||||
['setUA', function (ua) {
|
||||
if (typeof ua === STR_TYPE)
|
||||
if (isString(ua))
|
||||
userAgent = ua.length > UA_MAX_LENGTH ? trim(ua, UA_MAX_LENGTH) : ua;
|
||||
return this;
|
||||
}]
|
||||
@@ -1159,7 +1245,7 @@
|
||||
}
|
||||
|
||||
UAParser.VERSION = LIBVERSION;
|
||||
UAParser.BROWSER = enumerize([NAME, VERSION, MAJOR]);
|
||||
UAParser.BROWSER = enumerize([NAME, VERSION, MAJOR, TYPE]);
|
||||
UAParser.CPU = enumerize([ARCHITECTURE]);
|
||||
UAParser.DEVICE = enumerize([MODEL, VENDOR, TYPE, CONSOLE, MOBILE, SMARTTV, TABLET, WEARABLE, EMBEDDED]);
|
||||
UAParser.ENGINE = UAParser.OS = enumerize([NAME, VERSION]);
|
||||
|
||||
49
test/dts-test.ts
Normal file
49
test/dts-test.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import { expectType } from 'tsd';
|
||||
import { UAParser, IResult, IBrowser, ICPU, IEngine, IDevice, IOS } from "../src/main/ua-parser";
|
||||
import { isAppleSilicon, isChromiumBased } from "../src/helpers/ua-parser-helpers";
|
||||
|
||||
const uastring = 'Mozilla/5.0 (X11; MyCustomOS; Linux i686; rv:19.0) Gecko/20100101 Firefox/19.0';
|
||||
const extensions = {
|
||||
os : [
|
||||
[/(mycustomos)/], [UAParser.OS.NAME, [UAParser.OS.VERSION, '10']]
|
||||
]
|
||||
};
|
||||
const headers = {
|
||||
'sec-ch-ua-mobile' : '?1'
|
||||
};
|
||||
|
||||
expectType<IResult>(UAParser());
|
||||
expectType<IResult>(UAParser(uastring));
|
||||
expectType<IResult>(UAParser(uastring, extensions));
|
||||
expectType<IResult>(UAParser(uastring, headers));
|
||||
expectType<IResult>(UAParser(extensions, headers));
|
||||
expectType<IResult>(UAParser(extensions));
|
||||
expectType<IResult>(UAParser(headers));
|
||||
expectType<UAParser>(new UAParser());
|
||||
|
||||
const parser = new UAParser(uastring);
|
||||
const browser = parser.getBrowser();
|
||||
|
||||
expectType<IBrowser>(browser);
|
||||
expectType<string | undefined>(browser.name);
|
||||
expectType<string | undefined>(browser.version);
|
||||
expectType<string | undefined>(browser.major);
|
||||
expectType<'crawler' | 'cli' | 'email' | 'fetcher' | 'inapp' | 'module' | undefined>(browser.type);
|
||||
expectType<boolean>(browser.is(''));
|
||||
expectType<string>(browser.toString());
|
||||
expectType<IBrowser | PromiseLike<IBrowser>>(browser.withClientHints());
|
||||
expectType<IBrowser>((<IBrowser>browser.withClientHints()).withFeatureCheck());
|
||||
expectType<boolean>((<IBrowser>browser.withClientHints()).withFeatureCheck().is(''));
|
||||
|
||||
expectType<ICPU>(parser.getCPU());
|
||||
expectType<IDevice>(parser.getDevice());
|
||||
expectType<IEngine>(parser.getEngine());
|
||||
expectType<IOS>(parser.getOS());
|
||||
expectType<IResult>(parser.getResult());
|
||||
expectType<string>(parser.getUA());
|
||||
expectType<UAParser>(parser.setUA(uastring));
|
||||
|
||||
const result = parser.getResult();
|
||||
|
||||
expectType<boolean>(isAppleSilicon(result));
|
||||
expectType<boolean>(isChromiumBased(result));
|
||||
@@ -1,5 +1,5 @@
|
||||
const { FuzzedDataProvider } = require('@jazzer.js/core');
|
||||
const UAParser = require('ua-parser-js');
|
||||
const { UAParser } = require('../src/main/ua-parser');
|
||||
const UA_MAX_LENGTH = 350;
|
||||
|
||||
module.exports.fuzz = function (buffer) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { UAParser } from 'ua-parser-js';
|
||||
import { CPUArch, DeviceType, EngineName } from 'ua-parser-js/enums';
|
||||
import { UAParser } from '../src/main/ua-parser.mjs';
|
||||
import { CPU, Device, Engine } from '../src/enums/ua-parser-enums.mjs';
|
||||
import * as assert from 'assert';
|
||||
|
||||
describe('Returns', () => {
|
||||
@@ -7,8 +7,7 @@ describe('Returns', () => {
|
||||
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 },
|
||||
browser: { name: undefined, version: undefined, major: undefined, type: undefined },
|
||||
cpu: { architecture: undefined },
|
||||
device: { vendor: undefined, model: undefined, type: undefined },
|
||||
engine: { name: undefined, version: undefined},
|
||||
@@ -20,8 +19,8 @@ describe('Returns', () => {
|
||||
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);
|
||||
assert.strictEqual(cpu.is(CPU.ARM), true);
|
||||
assert.strictEqual(device.is(Device.MOBILE), true);
|
||||
assert.strictEqual(engine.is(Engine.GECKO), true);
|
||||
});
|
||||
});
|
||||
@@ -3,77 +3,91 @@ const assert = require('assert');
|
||||
const parseJS = require('@babel/parser').parse;
|
||||
const traverse = require('@babel/traverse').default;
|
||||
const safe = require('safe-regex');
|
||||
const UAParser = require('ua-parser-js');
|
||||
const Ext = require('ua-parser-js/extensions');
|
||||
const { UAParser } = require('../src/main/ua-parser');
|
||||
const clis = require('./specs/browser-clis.json');
|
||||
const crawlers = require('./specs/browser-crawlers.json');
|
||||
const emails = require('./specs/browser-emails.json');
|
||||
const fetchers = require('./specs/browser-fetchers.json');
|
||||
const modules = require('./specs/browser-modules.json');
|
||||
const { CLIs, Crawlers, Emails, Fetchers, Modules } = require('../src/extensions/ua-parser-extensions');
|
||||
|
||||
describe('Bots', () => {
|
||||
it('Can detect bots', () => {
|
||||
const googleBot = 'Googlebot-Video/1.0';
|
||||
const gptBot = 'Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; GPTBot/1.0; +https://openai.com/gptbot)';
|
||||
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 axios = 'axios/1.3.5';
|
||||
const jsdom = 'Mozilla/5.0 (darwin) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/20.0.3';
|
||||
const scrapy = 'Scrapy/1.5.0 (+https://scrapy.org)';
|
||||
|
||||
const botParser = new UAParser(Ext.Bots);
|
||||
assert.deepEqual(botParser.setUA(googleBot).getBrowser(), {name: "Googlebot-Video", version: "1.0", major: "1", type: "bot"});
|
||||
assert.deepEqual(botParser.setUA(gptBot).getBrowser(), {name: "GPTBot", 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 & CLIs
|
||||
const botsAndCLIs = { browser : [...Ext.Bots.browser, ...Ext.CLIs.browser]};
|
||||
const botsAndCLIsParser = new UAParser(botsAndCLIs);
|
||||
assert.deepEqual(botsAndCLIsParser.setUA(wget).getBrowser(), {name: "Wget", version: "1.21.1", major: "1", type:"cli"});
|
||||
assert.deepEqual(botsAndCLIsParser.setUA(facebookBot).getBrowser(), {name: "FacebookBot", version: "1.0", major: "1", type:"bot"});
|
||||
|
||||
const emailParser = new UAParser(Ext.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"});
|
||||
|
||||
const moduleParser = new UAParser(Ext.Modules);
|
||||
assert.deepEqual(moduleParser.setUA(axios).getBrowser(), {name: "axios", version: "1.3.5", major: "1", type: "module"});
|
||||
assert.deepEqual(moduleParser.setUA(jsdom).getBrowser(), {name: "jsdom", version: "20.0.3", major: "20", type: "module"});
|
||||
assert.deepEqual(moduleParser.setUA(scrapy).getBrowser(), {name: "Scrapy", version: "1.5.0", major: "1", type: "module"});
|
||||
});
|
||||
});
|
||||
|
||||
// TODO : move test spec to JSON file
|
||||
|
||||
describe('Testing regexes', () => {
|
||||
|
||||
let regexes;
|
||||
|
||||
before('Read main js file', () => {
|
||||
let code = fs.readFileSync('src/extensions/ua-parser-extensions.js', 'utf8').toString();
|
||||
let ast = parseJS(code, { sourceType: 'script' });
|
||||
regexes = [];
|
||||
traverse(ast, {
|
||||
RegExpLiteral: (path) => {
|
||||
regexes.push(path.node.pattern);
|
||||
}
|
||||
});
|
||||
if (regexes.length === 0) {
|
||||
throw new Error('Regexes cannot be empty!');
|
||||
}
|
||||
});
|
||||
|
||||
describe('Begin testing', () => {
|
||||
it('all regexes in extension file', () => {
|
||||
regexes.forEach(regex => {
|
||||
describe('Test against `safe-regex` : ' + regex, () => {
|
||||
it('should be safe from potentially vulnerable regex', () => {
|
||||
assert.strictEqual(safe(regex), true);
|
||||
});
|
||||
describe('Extensions', () => {
|
||||
[
|
||||
['CLIs', clis, CLIs],
|
||||
['Crawlers', crawlers, Crawlers],
|
||||
['Emails', emails, Emails],
|
||||
['Fetchers', fetchers, Fetchers],
|
||||
['Modules', modules, Modules]
|
||||
]
|
||||
.forEach((list) => {
|
||||
describe(list[0], () => {
|
||||
list[1].forEach((agent) => {
|
||||
it(`Can detect ${agent.desc}`, () => {
|
||||
let browser = UAParser(agent.ua, list[2]).browser;
|
||||
assert.strictEqual(String(browser.name), agent.expect.name);
|
||||
assert.strictEqual(String(browser.version), agent.expect.version);
|
||||
assert.strictEqual(String(browser.type), agent.expect.type);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
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 axios = 'axios/1.3.5';
|
||||
const jsdom = 'Mozilla/5.0 (darwin) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/20.0.3';
|
||||
const scrapy = 'Scrapy/1.5.0 (+https://scrapy.org)';
|
||||
|
||||
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"});
|
||||
|
||||
const moduleParser = new UAParser(Modules);
|
||||
assert.deepEqual(moduleParser.setUA(axios).getBrowser(), {name: "axios", version: "1.3.5", major: "1", type: "module"});
|
||||
assert.deepEqual(moduleParser.setUA(jsdom).getBrowser(), {name: "jsdom", version: "20.0.3", major: "20", type: "module"});
|
||||
assert.deepEqual(moduleParser.setUA(scrapy).getBrowser(), {name: "Scrapy", version: "1.5.0", major: "1", type: "module"});
|
||||
});
|
||||
|
||||
describe('Merge', () => {
|
||||
it('Can merge multiple extensions', () => {
|
||||
const wget = 'Wget/1.21.1';
|
||||
const facebookBot = 'Mozilla/5.0 (compatible; FacebookBot/1.0; +https://developers.facebook.com/docs/sharing/webmasters/facebookbot/)';
|
||||
|
||||
// try merging crawlers & CLIs
|
||||
const crawlersAndCLIs = { browser : [...Crawlers.browser, ...CLIs.browser]};
|
||||
const crawlersAndCLIsParser = new UAParser(crawlersAndCLIs);
|
||||
assert.deepEqual(crawlersAndCLIsParser.setUA(wget).getBrowser(), {name: "Wget", version: "1.21.1", major: "1", type:"cli"});
|
||||
assert.deepEqual(crawlersAndCLIsParser.setUA(facebookBot).getBrowser(), {name: "FacebookBot", version: "1.0", major: "1", type:"crawler"});
|
||||
|
||||
// alternative merge options
|
||||
const crawlersAndCLIsParser2 = new UAParser([Crawlers, CLIs]);
|
||||
const crawlersAndCLIsParser3 = new UAParser(facebookBot, [Crawlers, CLIs]);
|
||||
assert.deepEqual(crawlersAndCLIsParser2.setUA(wget).getBrowser(), {name: "Wget", version: "1.21.1", major: "1", type:"cli"});
|
||||
assert.deepEqual(crawlersAndCLIsParser3.getBrowser(), {name: "FacebookBot", version: "1.0", major: "1", type:"crawler"});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Testing regexes', () => {
|
||||
|
||||
let regexes;
|
||||
let code = fs.readFileSync('src/extensions/ua-parser-extensions.js', 'utf8').toString();
|
||||
let ast = parseJS(code, { sourceType: 'script' });
|
||||
regexes = [];
|
||||
traverse(ast, {
|
||||
RegExpLiteral: (path) => {
|
||||
regexes.push(path.node.pattern);
|
||||
}
|
||||
});
|
||||
|
||||
if (regexes.length === 0) {
|
||||
throw new Error('Regexes cannot be empty!');
|
||||
}
|
||||
|
||||
describe('Checking for potentially vulnerable regex', () => {
|
||||
for (let regex of regexes) {
|
||||
it('Test against `safe-regex` : ' + regex, () => {
|
||||
assert.strictEqual(safe(regex), true);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,35 +1,26 @@
|
||||
const { isFrozenUA } = require('ua-parser-js/helpers');
|
||||
const assert = require('assert');
|
||||
const { UAParser } = require('../src/main/ua-parser');
|
||||
const { isAppleSilicon, isChromiumBased } = require('../src/helpers/ua-parser-helpers');
|
||||
|
||||
describe('isFrozenUA', () => {
|
||||
it('Returns whether a user agent is frozen', () => {
|
||||
describe('isAppleSilicon', () => {
|
||||
it('Can detect Apple Silicon device', () => {
|
||||
|
||||
// non-real ua
|
||||
const macARM = 'Mozilla/5.0 (Macintosh; ARM; Mac OS X 10.15; rv:97.0) Gecko/20100101 Firefox/97.0';
|
||||
const macIntel = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:97.0) Gecko/20100101 Firefox/97.0';
|
||||
|
||||
const regularWindowsUA = "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.1234.56 Safari/537.36";
|
||||
const freezedWindowsUA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.0.0 Safari/537.36";
|
||||
assert.equal(isAppleSilicon(UAParser(macIntel)), false);
|
||||
assert.equal(isAppleSilicon(UAParser(macARM)), true);
|
||||
});
|
||||
});
|
||||
|
||||
const regularMacUA = "";
|
||||
const freezedMacUA = "";
|
||||
describe('isChromiumBased', () => {
|
||||
it('Can detect Chromium-based browser', () => {
|
||||
|
||||
const edge = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.2151.58';
|
||||
const firefox = 'Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/111.0';
|
||||
|
||||
const regularLinuxUA = "";
|
||||
const freezedLinuxUA = "";
|
||||
|
||||
const regularCrOSUA = "";
|
||||
const freezedCrOSUA = "";
|
||||
|
||||
const regularFuchsiaUA = "";
|
||||
const freezedFuchsiaUA = "";
|
||||
|
||||
const regularMobileUA = "Mozilla/5.0 (Linux; Android 9; SM-A205U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.1234.56 Mobile Safari/537.36";
|
||||
const freezedMobileUA = "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.0.0 Mobile Safari/537.36";
|
||||
|
||||
const regularTabletUA = "Mozilla/5.0 (Linux; Android 9; SM-T810) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.1234.56 Safari/537.36";
|
||||
const freezedTabletUA = "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.0.0 Safari/537.36";
|
||||
|
||||
assert.strictEqual(isFrozenUA(regularWindowsUA), false);
|
||||
assert.strictEqual(isFrozenUA(freezedWindowsUA), true);
|
||||
assert.strictEqual(isFrozenUA(regularMobileUA), false);
|
||||
assert.strictEqual(isFrozenUA(freezedMobileUA), true);
|
||||
assert.strictEqual(isFrozenUA(regularTabletUA), false);
|
||||
assert.strictEqual(isFrozenUA(freezedTabletUA), true);
|
||||
assert.equal(isChromiumBased(UAParser(edge)), true);
|
||||
assert.equal(isChromiumBased(UAParser(firefox)), false);
|
||||
});
|
||||
});
|
||||
File diff suppressed because one or more lines are too long
@@ -1,4 +1,3 @@
|
||||
// @ts-check
|
||||
import { test, expect } from '@playwright/test';
|
||||
import path from 'path';
|
||||
import url from 'url';
|
||||
@@ -40,7 +39,8 @@ test('read client hints data', async ({ page }) => {
|
||||
version: '110'
|
||||
}
|
||||
],
|
||||
platform: 'New OS'
|
||||
platform: 'New OS',
|
||||
formFactors: 'New Form Factor'
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -54,6 +54,7 @@ test('read client hints data', async ({ page }) => {
|
||||
|
||||
expect(uap).toHaveProperty('browser.name', 'New Browser');
|
||||
expect(uap).toHaveProperty('os.name', 'New OS');
|
||||
expect(uap).toHaveProperty('device.type', undefined);
|
||||
});
|
||||
|
||||
test('detect Brave', async ({ page }) => {
|
||||
@@ -9,6 +9,26 @@
|
||||
"major" : "undefined"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Alipay",
|
||||
"ua" : "Mozilla/5.0 (Linux; U; Android 10; zh-CN; V2034A Build/QP1A.190711.020) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/69.0.3497.100 UWS/3.22.2.33 Mobile Safari/537.36 UCBS/3.22.2.33_211025173018 NebulaSDK/1.8.100112 Nebula AlipayDefined(nt:WIFI,ws:360|0|2.0) AliApp(AP/10.2.51.7100) AlipayClient/10.2.51.7100 Language/zh-Hans useStatusBar/true isConcaveScreen/true Region/CNAriver/1.0.0",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Alipay",
|
||||
"version" : "10.2.51.7100",
|
||||
"major" : "10"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Alipay",
|
||||
"ua" : "Mozilla/5.0 (Linux; Android 10; VOG-AL00 Build/HUAWEIVOG-AL00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/105.0.5195.148 MYWeb/0.2.103.0_20230131112530 UWS/3.22.2.9999 UCBS/3.22.2.9999_220000000000 Mobile Safari/537.36 NebulaSDK/1.8.100112 Nebula AlipayDefined(nt:WIFI,ws:360|0|3.0) AliApp(AP/10.3.50.9999) AlipayClient/10.3.50.9999 Language/en isConcaveScreen/true Region/CN ProductType/devAriver/1.0.0",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Alipay",
|
||||
"version" : "10.3.50.9999",
|
||||
"major" : "10"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Android Browser on Galaxy Nexus",
|
||||
"ua" : "Mozilla/5.0 (Linux; U; Android 4.0.2; en-us; Galaxy Nexus Build/ICL53F) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30",
|
||||
@@ -64,7 +84,7 @@
|
||||
"ua" : "Mozilla/5.0 (Linux; Android 5.0.2; SAMSUNG SM-G925F Build/LRX22G) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/3.0 Chrome/38.0.2125.102 Mobile Safari/537.36",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Samsung Browser",
|
||||
"name" : "Samsung Internet",
|
||||
"version" : "3.0",
|
||||
"major" : "3"
|
||||
}
|
||||
@@ -94,7 +114,7 @@
|
||||
"ua" : "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; GTB5; Avant Browser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Avant ",
|
||||
"name" : "Avant",
|
||||
"version" : "undefined",
|
||||
"major" : "undefined"
|
||||
}
|
||||
@@ -124,11 +144,81 @@
|
||||
"ua" : "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; baidubrowser 1.x)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "baidubrowser",
|
||||
"name" : "Baidu",
|
||||
"version" : "1.x",
|
||||
"major" : "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Baidu",
|
||||
"ua" : "Mozilla/5.0 (Linux; Android 9; Redmi Note 5 Build/PKQ1.180904.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/110.0.5481.153 Mobile Safari/537.36 bdbrowser/6.4.0.4",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Baidu",
|
||||
"version" : "6.4.0.4",
|
||||
"major" : "6"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Baidu",
|
||||
"ua" : "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.4.9999.1900 Safari/537.31 BDSpark/26.4",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Baidu",
|
||||
"version" : "26.4",
|
||||
"major" : "26"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Baidu",
|
||||
"ua" : "Mozilla/5.0 (iPad; CPU OS 9_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) BaiduHD/5.4.0.0 Mobile/10A406 Safari/8536.25",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Baidu",
|
||||
"version" : "5.4.0.0",
|
||||
"major" : "5"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "BaiDu Browser",
|
||||
"ua" : "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 BIDUBrowser/8.7 Safari/537.36",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Baidu",
|
||||
"version" : "8.7",
|
||||
"major" : "8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "baidu app on iOS",
|
||||
"ua" : "Mozilla/5.0 (iPhone; CPU iPhone OS 12_1_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/16C101 main%2F1.0 baiduboxapp/11.12.0.18 (Baidu; P2 12.1.2)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Baidu",
|
||||
"version" : "11.12.0.18",
|
||||
"major" : "11"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "baidu app on Android",
|
||||
"ua" : "Mozilla/5.0 (Linux; Android 8.1.0; BKK-AL10 Build/HONORBKK-AL10; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/63.0.3239.83 Mobile Safari/537.36 T7/11.11 baiduboxapp/11.11.0.0 (Baidu; P1 8.1.0)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Baidu",
|
||||
"version" : "11.11.0.0",
|
||||
"major" : "11"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Blazer",
|
||||
"ua" : "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; PalmSource/hspr-H102; Blazer/4.0) 16;320x320",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Blazer",
|
||||
"version" : "4.0",
|
||||
"major" : "4"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Bolt",
|
||||
"ua" : "Mozilla/5.0 (X11; 78; CentOS; US-en) AppleWebKit/527+ (KHTML, like Gecko) Bolt/0.862 Version/3.0 Safari/523.15",
|
||||
@@ -309,6 +399,26 @@
|
||||
"major" : "78"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Comodo Dragon",
|
||||
"ua" : "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/535.7 (KHTML, like Gecko) Comodo_Dragon/16.1.1.0 Chrome/16.0.912.63 Safari/535.7",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Comodo Dragon",
|
||||
"version" : "16.1.1.0",
|
||||
"major" : "16"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Conkeror",
|
||||
"ua" : "Mozilla/5.0 (X11; Linux x86_64; rv:6.0.1) Gecko/20110831 conkeror/0.9.3",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "conkeror",
|
||||
"version" : "0.9.3",
|
||||
"major" : "0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Dillo",
|
||||
"ua" : "Dillo/2.2",
|
||||
@@ -339,6 +449,16 @@
|
||||
"major" : "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "DuckDuckGo",
|
||||
"ua" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4.1 Safari/605.1.1517.4.1 Ddg/17.4.1",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "DuckDuckGo",
|
||||
"version" : "17.4.1",
|
||||
"major" : "17"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "DuckDuckGo",
|
||||
"ua" : "Mozilla/5.0 (Linux; Android 8.1.0) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/92.0.4515.131 Mobile DuckDuckGo/5 Safari/537.36",
|
||||
@@ -369,6 +489,16 @@
|
||||
"major" : "5"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Go Browser",
|
||||
"ua" : "NokiaE66/GoBrowser/2.0.297",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "GoBrowser",
|
||||
"version" : "2.0.297",
|
||||
"major" : "2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Waterfox",
|
||||
"ua" : "Mozilla/5.0 (X11; Linux x86_64; rv:55.0) Gecko/20100101 Firefox/55.2.2 Waterfox/55.2.2",
|
||||
@@ -429,6 +559,26 @@
|
||||
"major" : "undefined"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Klarna in-App Browser for iOS",
|
||||
"ua" : "Mozilla/5.0 (iPhone; CPU iPhone OS 16_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Klarna/23.36.223",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Klarna",
|
||||
"version" : "23.36.223",
|
||||
"major" : "23"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Klarna in-App Browser for Android",
|
||||
"ua" : "Mozilla/5.0 (Linux; Android 12; moto g(60)s Build/S3RLS32.114-25-13; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/116.0.0.0 Mobile Safari/537.36 Klarna/23.36.215",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Klarna",
|
||||
"version" : "23.36.215",
|
||||
"major" : "23"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Instagram in-App Browser for iOS",
|
||||
"ua" : "Mozilla/5.0 (iPhone; CPU iPhone OS 14_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Instagram 142.0.0.22.109 (iPhone12,5; iOS 14_1; en_US; en-US; scale=3.00; 1242x2688; 214888322) NW/1",
|
||||
@@ -608,6 +758,16 @@
|
||||
"major" : "2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "ICEBrowser",
|
||||
"ua" : "Mozilla/5.0 (Java 1.6.0_01; Windows XP 5.1 x86; en) ICEbrowser/v6_1_2",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "ICEbrowser",
|
||||
"version" : "6.1.2",
|
||||
"major" : "6"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "IceCat",
|
||||
"ua" : "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.3) Gecko/2008092921 IceCat/3.0.3-g1",
|
||||
@@ -668,6 +828,26 @@
|
||||
"major" : "11"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Iron",
|
||||
"ua" : "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1250.0 Iron/22.0.2150.0 Safari/537.4",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Iron",
|
||||
"version" : "22.0.2150.0",
|
||||
"major" : "22"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Jasmine",
|
||||
"ua" : "SAMSUNG-S8000/S8000XXIF3 SHP/VPP/R5 Jasmine/1.0 Nextreaming SMM-MMS/1.2.0 profile/MIDP-2.1 configuration/CLDC-1.1",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Jasmine",
|
||||
"version" : "1.0",
|
||||
"major" : "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "K-Meleon",
|
||||
"ua" : "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.5) Gecko/20031016 K-Meleon/0.8.2",
|
||||
@@ -688,6 +868,16 @@
|
||||
"major" : "2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Klar < 4.1",
|
||||
"ua" : "Mozilla/5.0 (Linux; Android 7.0) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Klar/1.0 Chrome/58.0.3029.83 Mobile Safari/537.36",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Klar",
|
||||
"version" : "1.0",
|
||||
"major" : "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Konqueror",
|
||||
"ua" : "Mozilla/5.0 (compatible; Konqueror/3.5; Linux; X11; x86_64) KHTML/3.5.6 (like Gecko) (Kubuntu)",
|
||||
@@ -708,6 +898,56 @@
|
||||
"major" : "5"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "PicoBrowser",
|
||||
"ua" : "Mozilla/5.0 (X11; Linux x86_64; Pico Neo3 Link OS5.8.4.0 like Quest) AppleWebKit/537.36 (KHTML, like Gecko) PicoBrowser/3.3.22 Chrome/105.0.5195.68 VR Safari/537.36",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Pico Browser",
|
||||
"version" : "3.3.22",
|
||||
"major" : "3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "PicoBrowser",
|
||||
"ua" : "Mozilla/5.0 (X11; Linux x86_64; PICO 4 OS5.4.0 like Quest) AppleWebKit/537.36 (KHTML, like Gecko) PicoBrowser/3.3.22 Chrome/105.0.5195.68 VR Safari/537.36 OculusBrowser/7.0",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Pico Browser",
|
||||
"version" : "3.3.22",
|
||||
"major" : "3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Rekonq",
|
||||
"ua" : "Mozilla/5.0 (X11; U; Linux x86_64; cs-CZ) AppleWebKit/533.3 (KHTML, like Gecko) rekonq Safari/533.3",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "rekonq",
|
||||
"version" : "undefined",
|
||||
"major" : "undefined"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Smart Lenovo Browser",
|
||||
"ua" : "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36 SLBrowser/8.0.0.10171 SLBChan/8",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Smart Lenovo Browser",
|
||||
"version" : "8.0.0.10171",
|
||||
"major" : "8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Smart Lenovo Browser",
|
||||
"ua" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 SLBrowser/9.0.0.9011 SLBChan/10",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Smart Lenovo Browser",
|
||||
"version" : "9.0.0.9011",
|
||||
"major" : "9"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "LINE on Android",
|
||||
"ua" : "Mozilla/5.0 (Linux; Android 5.0; ASUS_Z00AD Build/LRX21V; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/51.0.2704.81 Mobile Safari/537.36 Line/6.5.1/IAB",
|
||||
@@ -888,6 +1128,26 @@
|
||||
"major" : "6"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "NetSurf in Plan9",
|
||||
"ua" : "Mozilla/5.0 (Plan9) NetSurf/3.12",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "NetSurf",
|
||||
"version" : "3.12",
|
||||
"major" : "3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "NetSurf in Linux",
|
||||
"ua" : "NetSurf/3.10 (Linux; Arch Linux)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "NetSurf",
|
||||
"version" : "3.10",
|
||||
"major" : "3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Nokia Browser",
|
||||
"ua" : "Mozilla/5.0 (Symbian/3; Series60/5.2 NokiaN8-00/025.007; Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/533.4 (KHTML, like Gecko) NokiaBrowser/7.3.1.37 Mobile Safari/533.4 3gpp-gba",
|
||||
@@ -1018,6 +1278,26 @@
|
||||
"major" : "12"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Opera GX on Android",
|
||||
"ua" : "Mozilla/5.0 (Linux; Android 10; Redmi Note 8 Pro Build/QP1A.190711.020) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.5790.168 Mobile Safari/537.36 OPX/2",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Opera GX",
|
||||
"version" : "2",
|
||||
"major" : "2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Opera GX on Windows",
|
||||
"ua" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36 OPR/60.0.3255.50747 OPRGX/60.0.3255.50747",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Opera GX",
|
||||
"version" : "60.0.3255.50747",
|
||||
"major" : "60"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Opera Tablet",
|
||||
"ua" : "Opera/9.80 (Windows NT 6.1; Opera Tablet/15165; U; en) Presto/2.8.149 Version/11.1",
|
||||
@@ -1048,6 +1328,16 @@
|
||||
"major" : "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "OviBrowser",
|
||||
"ua" : "Mozilla/5.0 (Series40; NokiaX3-02/le6.32; Profile/MIDP-2.1 Configuration/CLDC-1.1) Gecko/20100401 S40OviBrowser/1.0.0.11.8",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "OviBrowser",
|
||||
"version" : "1.0.0.11.8",
|
||||
"major" : "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "PhantomJS",
|
||||
"ua" : "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.2 Safari/534.34",
|
||||
@@ -1079,7 +1369,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "QQ",
|
||||
"desc" : "QQBrowser",
|
||||
"ua" : "Mozilla/5.0 (Linux; U; Android 4.4.4; zh-cn; OPPO R7s Build/KTU84P) AppleWebKit/537.36 (KHTML, like Gecko)Version/4.0 Chrome/37.0.0.0 MQQBrowser/7.1 Mobile Safari/537.36",
|
||||
"expect" :
|
||||
{
|
||||
@@ -1088,6 +1378,26 @@
|
||||
"major" : "7"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "QQBrowser",
|
||||
"ua" : "Mozilla/5.0 (Linux; U; Android 9; zh-cn; vivo X21 Build/PKQ1.180819.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/9.9 Mobile Safari/537.36",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "QQBrowser",
|
||||
"version" : "9.9",
|
||||
"major" : "9"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Quark",
|
||||
"ua" : "Mozilla/5.0 (Linux; U; Android 12; zh-Hans-CN; JLH-AN00 Build/HONORJLH-AN00) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.108 Quark/5.8.2.221 Mobile Safari/537.36",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Quark",
|
||||
"version" : "5.8.2.221",
|
||||
"major" : "5"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "QupZilla",
|
||||
"ua" : "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/538.1 (KHTML, like Gecko) QupZilla/1.8.9 Safari/538.1",
|
||||
@@ -1098,6 +1408,16 @@
|
||||
"major" : "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Rekonq 2",
|
||||
"ua" : "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.21 (KHTML, like Gecko) rekonq/2.2.1 Safari/537.21",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "rekonq",
|
||||
"version" : "2.2.1",
|
||||
"major" : "2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "RockMelt",
|
||||
"ua" : "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.7 (KHTML, like Gecko) RockMelt/0.8.36.78 Chrome/7.0.517.44 Safari/534.7",
|
||||
@@ -1129,15 +1449,55 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Samsung Browser",
|
||||
"desc" : "Samsung Internet for Android",
|
||||
"ua" : "Mozilla/5.0 (Linux; Android 6.0.1; SAMSUNG-SM-G925A Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/4.0 Chrome/44.0.2403.133 Mobile Safari/537.36",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Samsung Browser",
|
||||
"name" : "Samsung Internet",
|
||||
"version" : "4.0",
|
||||
"major" : "4"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Samsung Internet for Tizen Mobile",
|
||||
"ua" : "Mozilla/5.0 (Linux; Tizen 2.3; SAMSUNG SM-Z130H) AppleWebKit/537.3 (KHTML, like Gecko) SamsungBrowser/1.0 Mobile Safari/537.3",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Samsung Internet",
|
||||
"version" : "1.0",
|
||||
"major" : "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Samsung Internet for Smart-TV",
|
||||
"ua" : "Mozilla/5.0 (SMART-TV; Linux; Tizen 2.3) AppleWebkit/538.1 (KHTML, like Gecko) SamsungBrowser/1.0 TV Safari/538.1",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Samsung Internet",
|
||||
"version" : "1.0",
|
||||
"major" : "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Samsung Internet for Gear VR",
|
||||
"ua" : "Mozilla/5.0 (Linux; Android 5.0.2; SAMSUNG SM-G925K Build/LRX22G) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/4.0 Chrome/44.0.2403.133 Mobile VR Safari/537.36",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Samsung Internet",
|
||||
"version" : "4.0",
|
||||
"major" : "4"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Samsung Internet in Redmi 8A",
|
||||
"ua" : "Mozilla/5.0 (Linux; Android 10; Redmi 8A) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/23.0 Chrome/115.0.0.0 Mobile Safari/537.36",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Samsung Internet",
|
||||
"version" : "23.0",
|
||||
"major" : "23"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "SeaMonkey",
|
||||
"ua" : "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1b4pre) Gecko/20090405 SeaMonkey/2.0b1pre",
|
||||
@@ -1177,6 +1537,37 @@
|
||||
"version" : "2.0",
|
||||
"major" : "2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Sleipnir",
|
||||
"ua" : "Mozilla/5.0 (Linux; Android 10; SOV37 Build/52.1.C.0.220; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/123.0.6312.120 Mobile Safari/537.36 Sleipnir/3.7.5",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Sleipnir",
|
||||
"version" : "3.7.5",
|
||||
"major" : "3"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"desc" : "Sleipnir",
|
||||
"ua" : "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Sleipnir 2.8.4)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Sleipnir",
|
||||
"version" : "2.8.4",
|
||||
"major" : "2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Sleipnir",
|
||||
"ua" : "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.1; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022) Sleipnir/2.8.4",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Sleipnir",
|
||||
"version" : "2.8.4",
|
||||
"major" : "2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "SlimBrowser",
|
||||
@@ -1289,7 +1680,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "UPBrowser",
|
||||
"desc" : "UP.Browser",
|
||||
"ua" : "BenQ-CF61/1.00/WAP2.0/MIDP2.0/CLDC1.0 UP.Browser/6.3.0.4.c.1.102 (GUI) MMP/2.0",
|
||||
"expect" :
|
||||
{
|
||||
@@ -1339,13 +1730,43 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Viera",
|
||||
"ua" : "HbbTV/1.2.1 (;Panasonic;VIERA 2015;3.014;a001-003 4000-0000;)",
|
||||
"desc" : "Vivaldi on Mac",
|
||||
"ua" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.88 Safari/537.36 Vivaldi/2.4.1488.36",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "VIERA",
|
||||
"version" : "undefined",
|
||||
"major" : "undefined"
|
||||
"name" : "Vivaldi",
|
||||
"version" : "2.4.1488.36",
|
||||
"major" : "2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Vivo Browser",
|
||||
"ua" : "Mozilla/5.0 (Linux; Android 13; 23049RAD8C; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/87.0.4280.141 Mobile Safari/537.36 VivoBrowser/16.7.1.1",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Vivo Browser",
|
||||
"version" : "16.7.1.1",
|
||||
"major" : "16"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "w3m",
|
||||
"ua" : "w3m/0.5.1",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "w3m",
|
||||
"version" : "0.5.1",
|
||||
"major" : "0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Wolvic",
|
||||
"ua" : "Mozilla/5.0 (Android 12; Mobile VR; rv:121.0) Gecko/121.0 Firefox/121.0 Wolvic/1.6.1",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Wolvic",
|
||||
"version" : "1.6.1",
|
||||
"major" : "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -1428,6 +1849,16 @@
|
||||
"major" : "6"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Puffin",
|
||||
"ua" : "Mozilla/5.0 (Linux; Android 7.1.1; ZTE BLADE A0620 Build/NMF26F; ru-ru) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.136 Mobile Safari/537.36 Puffin/9.2.0.50586AP",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Puffin",
|
||||
"version" : "9.2.0.50586AP",
|
||||
"major" : "9"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Microsoft Edge 0.1",
|
||||
"ua" : "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36 Edge/12.0",
|
||||
@@ -1543,7 +1974,7 @@
|
||||
"ua" : "Mozilla/5.0 (iPhone; CPU iPhone OS 10_0_2 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) Mobile/14A456 QQ/6.5.3.410 V1_IPH_SQ_6.5.3_1_APP_A Pixel/1080 Core/UIWebView NetType/WIFI Mem/26",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "QQ",
|
||||
"name" : "QQBrowser",
|
||||
"version" : "6.5.3.410",
|
||||
"major" : "6"
|
||||
}
|
||||
@@ -1553,37 +1984,17 @@
|
||||
"ua" : "Mozilla/5.0 (Linux; Android 6.0; PRO 6 Build/MRA58K) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/37.0.0.0 Mobile MQQBrowser/6.8 TBS/036824 Safari/537.36 V1_AND_SQ_6.5.8_422_YYB_D PA QQ/6.5.8.2910 NetType/WIFI WebP/0.3.0 Pixel/1080",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "QQ",
|
||||
"name" : "QQBrowser",
|
||||
"version" : "6.5.8.2910",
|
||||
"major" : "6"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "baidu app on iOS",
|
||||
"ua" : "Mozilla/5.0 (iPhone; CPU iPhone OS 12_1_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/16C101 main%2F1.0 baiduboxapp/11.12.0.18 (Baidu; P2 12.1.2)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "baiduboxapp",
|
||||
"version" : "11.12.0.18",
|
||||
"major" : "11"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "baidu app on Android",
|
||||
"ua" : "Mozilla/5.0 (Linux; Android 8.1.0; BKK-AL10 Build/HONORBKK-AL10; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/63.0.3239.83 Mobile Safari/537.36 T7/11.11 baiduboxapp/11.11.0.0 (Baidu; P1 8.1.0)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "baiduboxapp",
|
||||
"version" : "11.11.0.0",
|
||||
"major" : "11"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "WeChat Desktop for Windows Built-in Browser",
|
||||
"ua" : "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 MicroMessenger/6.5.2.501 NetType/WIFI WindowsWechat QBCore/3.43.901.400 QQBrowser/9.0.2524.400",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "WeChat(Win) Desktop",
|
||||
"name" : "WeChat",
|
||||
"version" : "3.43.901.400",
|
||||
"major" : "3"
|
||||
}
|
||||
@@ -1593,7 +2004,7 @@
|
||||
"ua" : "mozilla/5.0 (windows nt 10.0; wow64) applewebkit/537.36 (khtml, like gecko) chrome/53.0.2785.116 safari/537.36 qbcore/4.0.1301.400 qqbrowser/9.0.2524.400 mozilla/5.0 (windows nt 6.1; wow64) applewebkit/537.36 (khtml, like gecko) chrome/81.0.4044.138 safari/537.36 nettype/wifi micromessenger/7.0.20.1781(0x6700143b) windowswechat",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "WeChat(Win) Desktop",
|
||||
"name" : "WeChat",
|
||||
"version" : "4.0.1301.400",
|
||||
"major" : "4"
|
||||
}
|
||||
@@ -1623,7 +2034,19 @@
|
||||
"ua" : "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.221 Safari/537.36 SE 2.X MetaSr 1.0",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "MetaSr"
|
||||
"name" : "Sogou Explorer",
|
||||
"version" : "1.0",
|
||||
"major" : "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Sogou Mobile Browser",
|
||||
"ua" : "Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_2 like Mac OS X) AppleWebKit/603.2.4 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30 SogouMSE,SogouMobileBrowser/3.7.4",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Sogou Mobile",
|
||||
"version" : "3.7.4",
|
||||
"major" : "3"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -1634,16 +2057,6 @@
|
||||
"name" : "LBBROWSER"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "BaiDu Browser",
|
||||
"ua" : "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 BIDUBrowser/8.7 Safari/537.36",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "BIDUBrowser",
|
||||
"version" : "8.7",
|
||||
"major" : "8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "2345 Browser",
|
||||
"ua" : "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.90 Safari/537.36 2345Explorer/9.2.1.17116",
|
||||
@@ -1712,6 +2125,46 @@
|
||||
"name" : "LinkedIn"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Links in Linux",
|
||||
"ua" : "Links (2.xpre7; Linux 2.4.18 i586; x)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Links",
|
||||
"version" : "2.xpre7",
|
||||
"major" : "2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Links in Mac",
|
||||
"ua" : "Links (2.1pre33; Darwin 8.11.0 Power Macintosh; 169x55)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Links",
|
||||
"version" : "2.1pre33",
|
||||
"major" : "2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Links in NetBSD",
|
||||
"ua" : "Links (2.29; NetBSD 10.0 i386; GNU C 10.5; x)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Links",
|
||||
"version" : "2.29",
|
||||
"major" : "2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Links in FreeBSD",
|
||||
"ua" : "Links (2.1pre15; FreeBSD 5.3-RELEASE i386; 196x84)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Links",
|
||||
"version" : "2.1pre15",
|
||||
"major" : "2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Safari including comma in minor version number",
|
||||
"ua" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.6,2 Safari/605.1.15",
|
||||
@@ -1879,5 +2332,25 @@
|
||||
"version" : "12.33.0.36",
|
||||
"major" : "12"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Twitter",
|
||||
"ua" : "Mozilla/5.0 (Linux; Android 13; CPH2531 Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/123.0.6312.120 Mobile Safari/537.36 TwitterAndroid",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Twitter",
|
||||
"version" : "undefined",
|
||||
"major" : "undefined"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Twitter",
|
||||
"ua" : "Mozilla/5.0 (iPad; CPU OS 15_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/19H12 Twitter for iPhone/10.34",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Twitter",
|
||||
"version" : "10.34",
|
||||
"major" : "10"
|
||||
}
|
||||
}
|
||||
]
|
||||
42
test/specs/browser-clis.json
Normal file
42
test/specs/browser-clis.json
Normal file
@@ -0,0 +1,42 @@
|
||||
[
|
||||
{
|
||||
"desc" : "curl",
|
||||
"ua" : "curl/7.38.0",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "curl",
|
||||
"version" : "7.38.0",
|
||||
"type" : "cli"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "lynx",
|
||||
"ua" : "Lynx 2.8.8dev.3",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Lynx",
|
||||
"version" : "2.8.8dev.3",
|
||||
"type" : "cli"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "lynx",
|
||||
"ua" : "Lynx/2.6",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Lynx",
|
||||
"version" : "2.6",
|
||||
"type" : "cli"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "wget",
|
||||
"ua" : "Wget/1.21.1",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Wget",
|
||||
"version" : "1.21.1",
|
||||
"type" : "cli"
|
||||
}
|
||||
}
|
||||
]
|
||||
92
test/specs/browser-crawlers.json
Normal file
92
test/specs/browser-crawlers.json
Normal file
@@ -0,0 +1,92 @@
|
||||
[
|
||||
{
|
||||
"desc" : "Applebot",
|
||||
"ua" : "Mozilla/5.0 (iPhone; CPU iPhone OS 8_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12B410 Safari/600.1.4 (Applebot/0.1;+http://www.apple.com/go/applebot)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Applebot",
|
||||
"version" : "0.1",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Amazonbot",
|
||||
"ua" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/600.2.5 (KHTML, like Gecko) Version/8.0.2 Safari/600.2.5 (Amazonbot/0.1; +https://developer.amazon.com/support/amazonbot)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Amazonbot",
|
||||
"version" : "0.1",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Bytespider",
|
||||
"ua" : "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.1511.1269 Mobile Safari/537.36; Bytespider",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Bytespider",
|
||||
"version" : "undefined",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "ClaudeBot",
|
||||
"ua" : "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; +claudebot@anthropic.com)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "ClaudeBot",
|
||||
"version" : "1.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "ClaudeWeb",
|
||||
"ua" : "Claude-Web/1.0 (web crawler; +https://www.anthropic.com/; bots@anthropic.com)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Claude-Web",
|
||||
"version" : "1.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "FacebookBot",
|
||||
"ua" : "Mozilla/5.0 (compatible; FacebookBot/1.0; +https://developers.facebook.com/docs/sharing/webmasters/facebookbot/",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "FacebookBot",
|
||||
"version" : "1.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Googlebot-Video",
|
||||
"ua" : "Googlebot-Video/1.0",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Googlebot-Video",
|
||||
"version" : "1.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "GPTBot",
|
||||
"ua" : "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; GPTBot/1.0; +https://openai.com/gptbot)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "GPTBot",
|
||||
"version" : "1.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "YandexBot",
|
||||
"ua" : "Mozilla/5.0 (compatible; YandexBot/3.0; +http://yandex.com/bots)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "YandexBot",
|
||||
"version" : "3.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
}
|
||||
]
|
||||
12
test/specs/browser-emails.json
Normal file
12
test/specs/browser-emails.json
Normal file
@@ -0,0 +1,12 @@
|
||||
[
|
||||
{
|
||||
"desc" : "Thunderbird",
|
||||
"ua" : "Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.13.0",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Thunderbird",
|
||||
"version" : "78.13.0",
|
||||
"type" : "email"
|
||||
}
|
||||
}
|
||||
]
|
||||
12
test/specs/browser-fetchers.json
Normal file
12
test/specs/browser-fetchers.json
Normal file
@@ -0,0 +1,12 @@
|
||||
[
|
||||
{
|
||||
"desc" : "BingPreview",
|
||||
"ua" : "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534+ (KHTML, like Gecko) BingPreview/1.0b",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "BingPreview",
|
||||
"version" : "1.0b",
|
||||
"type" : "fetcher"
|
||||
}
|
||||
}
|
||||
]
|
||||
12
test/specs/browser-modules.json
Normal file
12
test/specs/browser-modules.json
Normal file
@@ -0,0 +1,12 @@
|
||||
[
|
||||
{
|
||||
"desc" : "Scrapy",
|
||||
"ua" : "Scrapy/1.5.0 (+https://scrapy.org)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Scrapy",
|
||||
"version" : "1.5.0",
|
||||
"type" : "module"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -167,6 +167,14 @@
|
||||
"architecture" : "arm64"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Google Search App",
|
||||
"ua" : "Mozilla/5.0 (Linux; Android 6.0; M5s Build/MRA58K; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/44.0.2403.147 Mobile Safari/537.36 GSA/12.40.17.23.arm64",
|
||||
"expect" :
|
||||
{
|
||||
"architecture" : "arm64"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Pocket PC",
|
||||
"ua" : "Opera/9.7 (Windows Mobile; PPC; Opera Mobi/35166; U; en) Presto/2.2.1",
|
||||
|
||||
@@ -152,6 +152,15 @@
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "ASUS Zenfone 2 Laser",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 6.0.1; ASUS_Z00ED) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Mobile Safari/537.36",
|
||||
"expect": {
|
||||
"vendor": "ASUS",
|
||||
"model": "Z00ED",
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Acer Iconia A1-810",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 4.2.2; A1-810 Build/JDQ39) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.109 Safari/537.36",
|
||||
@@ -971,6 +980,15 @@
|
||||
"type": "tablet"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Lenovo IdeaTab S6000",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 4.2.2; IdeaTab S6000-H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 YaBrowser/18.11.1.1011.01 Safari/537.36",
|
||||
"expect": {
|
||||
"vendor": "Lenovo",
|
||||
"model": "IdeaTab S6000-H",
|
||||
"type": "tablet"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "LG V40 ThinQ",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 9; LM-V405) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.136 Mobile Safari/537.36",
|
||||
@@ -1355,7 +1373,7 @@
|
||||
"expect": {
|
||||
"vendor": "Facebook",
|
||||
"model": "Quest",
|
||||
"type": "wearable"
|
||||
"type": "xr"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -1364,7 +1382,16 @@
|
||||
"expect": {
|
||||
"vendor": "Facebook",
|
||||
"model": "Quest 2",
|
||||
"type": "wearable"
|
||||
"type": "xr"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Oculus Quest 3",
|
||||
"ua": "Mozilla/5.0 (X11; Linux x86_64; Quest 3) AppleWebKit/537.36 (KHTML, like Gecko) OculusBrowser/31.4.0.6.51.566757996 Chrome/120.0.6099.283 VR Safari/537.36",
|
||||
"expect": {
|
||||
"vendor": "Facebook",
|
||||
"model": "Quest 3",
|
||||
"type": "xr"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -1373,7 +1400,7 @@
|
||||
"expect": {
|
||||
"vendor": "Facebook",
|
||||
"model": "Quest Pro",
|
||||
"type": "wearable"
|
||||
"type": "xr"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -1484,6 +1511,15 @@
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "OPPO Pad",
|
||||
"ua": "Mozilla/5.0 (Linux; U; Android 13; zh-CN; OPD2101 Build/TP1A.220905.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/100.0.4896.58 UCBrowser/16.3.9.1290 Mobile Safari/537.36",
|
||||
"expect": {
|
||||
"vendor": "OPPO",
|
||||
"model": "OPD2101",
|
||||
"type": "tablet"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "OPPO Neo",
|
||||
"ua": "Mozilla/5.0 (Linux; U; Android 4.2.2; zh-cn; R831T Build/JDQ39) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 OppoBrowser/3.3.2 Mobile Safari/534.30",
|
||||
@@ -1592,6 +1628,15 @@
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "OPPO F5",
|
||||
"ua": "ozilla/5.0 (Linux; Android 7.1.1; CPH1723) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Mobile Safari/537.36",
|
||||
"expect": {
|
||||
"vendor": "OPPO",
|
||||
"model": "CPH1723",
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Realme C1",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 8.1; RMX1811 Build/OPM1.171019.026) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.126 Mobile Safari/537.36",
|
||||
@@ -1637,11 +1682,20 @@
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Realme 8",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 12; RMX3085) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Mobile Safari/537.36",
|
||||
"expect": {
|
||||
"vendor": "Realme",
|
||||
"model": "RMX3085",
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Realme 9 Pro",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 13; RMX3471) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Mobile Safari/537.36",
|
||||
"expect": {
|
||||
"vendor": "undefined",
|
||||
"vendor": "Realme",
|
||||
"model": "RMX3471",
|
||||
"type": "mobile"
|
||||
}
|
||||
@@ -1650,7 +1704,7 @@
|
||||
"desc": "Realme GT Master",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 13; RMX3363) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Mobile Safari/537.36",
|
||||
"expect": {
|
||||
"vendor": "undefined",
|
||||
"vendor": "Realme",
|
||||
"model": "RMX3363",
|
||||
"type": "mobile"
|
||||
}
|
||||
@@ -2321,6 +2375,15 @@
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Tecno Spark 8C",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 11; TECNO KG5n) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Mobile Safari/537.36",
|
||||
"expect": {
|
||||
"vendor": "TECNO",
|
||||
"model": "KG5n",
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Tesla",
|
||||
"ua": "Mozilla/5.0 (X11; GNU/Linux) AppleWebKit/601.1 (KHTML, like Gecko) Tesla QtCarBrowser Safari/601.1",
|
||||
@@ -2357,6 +2420,132 @@
|
||||
"type": "smarttv"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Ulefone Armor",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 6.0; Armor Build/MRA58K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.107 Mobile Safari/537.36",
|
||||
"expect": {
|
||||
"vendor": "Ulefone",
|
||||
"model": "Armor",
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Ulefone Armor",
|
||||
"ua": "Mozilla/5.0 (Linux; arm_64; Android 6.0; Armor) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 YaBrowser/20.4.2.101.00 SA/1 Mobile Safari/537.36",
|
||||
"expect": {
|
||||
"vendor": "Ulefone",
|
||||
"model": "Armor",
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Ulefone Armor 8 Pro",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 11; Armor 8 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.5481.192 Mobile Safari/537.36 OPR/74.1.3922.71199",
|
||||
"expect": {
|
||||
"vendor": "Ulefone",
|
||||
"model": "Armor 8 Pro",
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Ulefone Armor 12 5G",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 11; Armor 12 5G Build/RP1A.200720.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/115.0.5790.166 Mobile Safari/537.36",
|
||||
"expect": {
|
||||
"vendor": "Ulefone",
|
||||
"model": "Armor 12 5G",
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Ulefone Armor 20WT",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 12; Armor 20WT) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/22.0 Chrome/111.0.5563.116 Mobile Safari/537.36",
|
||||
"expect": {
|
||||
"vendor": "Ulefone",
|
||||
"model": "Armor 20WT",
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Ulefone Armor Pad",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 12; Armor Pad Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/116.0.0.0 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/431.0.0.30.108;]",
|
||||
"expect": {
|
||||
"vendor": "Ulefone",
|
||||
"model": "Armor Pad",
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Ulefone Armor X5 Pro",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 10; Armor X5 Pro Build/QP1A.190711.020; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/116.0.0.0 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/430.0.0.23.113;]",
|
||||
"expect": {
|
||||
"vendor": "Ulefone",
|
||||
"model": "Armor X5 Pro",
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Ulefone Power Armor 14 Pro",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 12; Power Armor14 Pro Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/115.0.5790.138 Mobile Safari/537.36",
|
||||
"expect": {
|
||||
"vendor": "Ulefone",
|
||||
"model": "Power Armor14 Pro",
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Ulefone Power Armor 18T",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 12; Power Armor 18T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Mobile Safari/537.36",
|
||||
"expect": {
|
||||
"vendor": "Ulefone",
|
||||
"model": "Power Armor 18T",
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Ulefone Power Armor 19T",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 12; Power Armor 19T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.5481.192 Mobile Safari/537.36 OPR/74.3.3922.71982",
|
||||
"expect": {
|
||||
"vendor": "Ulefone",
|
||||
"model": "Power Armor 19T",
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Xiaomi 2201117TG",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 11; 2201117TG) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.98 Mobile Safari/537.36",
|
||||
"expect": {
|
||||
"vendor": "Xiaomi",
|
||||
"model": "2201117TG",
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Xiaomi M2004J19C",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 11; M2004J19C Build/RP1A.200720.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/113.0.5672.77 Mobile Safari/537.36",
|
||||
"expect": {
|
||||
"vendor": "Xiaomi",
|
||||
"model": "M2004J19C",
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Xiaomi M2006C3MNG",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 11; M2006C3MNG) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.85 Mobile Safari/537.36",
|
||||
"expect": {
|
||||
"vendor": "Xiaomi",
|
||||
"model": "M2006C3MNG",
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Xiaomi 21061119DG",
|
||||
"ua": "Mozilla/5.0 (Linux; arm_64; Android 11; 21061119DG) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 YaBrowser/23.3.7.24.00 SA/3 Mobile Safari/537.36",
|
||||
"expect": {
|
||||
"vendor": "Xiaomi",
|
||||
"model": "21061119DG",
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Xiaomi 2013023",
|
||||
"ua": "Mozilla/5.0 (Linux; U; Android 4.2.2; en-US; 2013023 Build/HM2013023) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 UCBrowser/10.0.1.512 U3/0.8.0 Mobile Safari/533.1",
|
||||
@@ -2564,6 +2753,15 @@
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Xiaomi POCOPHONE F1",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 10; POCOPHONE F1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Mobile Safari/537.36",
|
||||
"expect": {
|
||||
"vendor": "Xiaomi",
|
||||
"model": "POCOPHONE F1",
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Xiaomi Redmi 4A",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 6.0; Redmi 4A Build/MMB29M; xx-xx) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/56.0.2924.87 Mobile Safari/537.36",
|
||||
@@ -2577,7 +2775,7 @@
|
||||
"desc": "Xiaomi Redmi 10C",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 12; 220333QAG) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Mobile Safari/537.36",
|
||||
"expect": {
|
||||
"vendor": "undefined",
|
||||
"vendor": "Xiaomi",
|
||||
"model": "220333QAG",
|
||||
"type": "mobile"
|
||||
}
|
||||
@@ -2631,7 +2829,7 @@
|
||||
"desc": "XiaoMi Redmi Note 10 5G",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 12; M2103K19C) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.88 Mobile Safari/537.36",
|
||||
"expect": {
|
||||
"vendor": "undefined",
|
||||
"vendor": "Xiaomi",
|
||||
"model": "M2103K19C",
|
||||
"type": "mobile"
|
||||
}
|
||||
@@ -2640,7 +2838,7 @@
|
||||
"desc": "XiaoMi Redmi Note 10 Pro",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 13; M2101K6P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Mobile Safari/537.36",
|
||||
"expect": {
|
||||
"vendor": "undefined",
|
||||
"vendor": "Xiaomi",
|
||||
"model": "M2101K6P",
|
||||
"type": "mobile"
|
||||
}
|
||||
@@ -2649,7 +2847,7 @@
|
||||
"desc": "XiaoMi Redmi Note 10 Pro",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 12; M2101K6G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Mobile Safari/537.36",
|
||||
"expect": {
|
||||
"vendor": "undefined",
|
||||
"vendor": "Xiaomi",
|
||||
"model": "M2101K6G",
|
||||
"type": "mobile"
|
||||
}
|
||||
@@ -2663,6 +2861,24 @@
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "XiaoMi Redmi Note 12 Turbo",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 13; 23049RAD8C; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/87.0.4280.141 Mobile Safari/537.36 VivoBrowser/16.7.1.1",
|
||||
"expect": {
|
||||
"vendor": "Xiaomi",
|
||||
"model": "23049RAD8C",
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "ZTE Blade A6",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 7.1.1; ZTE BLADE A0620 Build/NMF26F; ru-ru) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.136 Mobile Safari/537.36 Puffin/9.2.0.50586AP",
|
||||
"expect": {
|
||||
"vendor": "ZTE",
|
||||
"model": "BLADE A0620",
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "PlayStation 4",
|
||||
"ua": "Mozilla/5.0 (PlayStation 4 3.00) AppleWebKit/537.73 (KHTML, like Gecko)",
|
||||
@@ -2969,6 +3185,15 @@
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Google Pixel 7",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 13; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Mobile Safari/537.36",
|
||||
"expect": {
|
||||
"vendor": "Google",
|
||||
"model": "Pixel 7",
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Generic Android Device",
|
||||
"ua": "Mozilla/5.0 (Linux; U; Android 6.0.1; i980 Build/MRA58K)",
|
||||
@@ -3199,6 +3424,15 @@
|
||||
"type": "console"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Vivo S1 Pro",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 11; vivo 1920) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Mobile Safari/537.36",
|
||||
"expect": {
|
||||
"vendor": "Vivo",
|
||||
"model": "1920",
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Vivo Y52s",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 10; V2057A Build/QP1A.190711.020; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/76.0.3809.89 Mobile Safari/537.36 T7/12.10 SP-engine/2.28.0 baiduboxapp/12.10.0.10 (Baidu; P1 10) NABar/1.0",
|
||||
|
||||
@@ -80,6 +80,24 @@
|
||||
"version" : "10"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "WeChat Desktop for Windows Built-in Browser",
|
||||
"ua" : "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 MicroMessenger/6.5.2.501 NetType/WIFI WindowsWechat QBCore/3.43.901.400 QQBrowser/9.0.2524.400",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Windows",
|
||||
"version" : "7"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "WeChat Desktop for Windows Built-in Browser major version in 4",
|
||||
"ua" : "mozilla/5.0 (windows nt 6.1; wow64) applewebkit/537.36 (khtml, like gecko) chrome/81.0.4044.138 safari/537.36 nettype/wifi micromessenger/7.0.20.1781(0x6700143b) windowswechat",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Windows",
|
||||
"version" : "7"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Windows RT",
|
||||
"ua" : "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; ARM; Trident/6.0)",
|
||||
|
||||
Reference in New Issue
Block a user