Bump version 2.0.6

This commit is contained in:
Faisal Salman
2025-10-10 09:58:40 +07:00
parent 2882014f0e
commit 061cf0e90f
19 changed files with 247 additions and 189 deletions

View File

@@ -69,6 +69,20 @@
--- ---
## Version 2.0.6
- Add new CLI feature: processing batch user-agent data from file and output as JSON
- Fix `setUA()`: trim leading space from user-agent string input
- Replace `undici` dependency with node's internal `Headers`
- Add new browser: Bing, Qwant
- Add new device vendor: Hisense, Wiko
- Improve browser detection: Mozilla, Pale Moon
- Improve CPU detection: 68k
- Improve device detection: Apple, BlackBerry, Huawei, Nokia, Xiaomi
- Improve OS detection: iOS 26
- `extensions` submodule:
- Add new fetcher: Discordbot, KeybaseBot, Slackbot, Slackbot-LinkExpanding, Slack-ImgProxy, Twitterbot
- Add new crawler: Qwantbot-news, SurdotlyBot, SwiftBot
## Version 2.0.5 ## Version 2.0.5
- Add new browser: Zalo - Add new browser: Zalo

View File

@@ -18,7 +18,7 @@
<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://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> <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"> <img src="https://img.shields.io/ossf-scorecard/github.com/faisalman/ua-parser-js?label=openssf%20scorecard&style=for-the-badge">
<a target="_blank" href="https://discord.gg/stt86vmr"><img alt="Discord invite" src="https://dcbadge.limes.pink/api/server/https://discord.gg/stt86vmr"></a> <a target="_blank" href="https://discord.com/channels/1406959509087453236/1406959509930381375"><img alt="Discord invite" src="https://dcbadge.limes.pink/api/server/https://discord.com/channels/1406959509087453236/1406959509930381375"></a>
</p> </p>
# UAParser.js # UAParser.js
@@ -58,7 +58,7 @@ see what's new & breaking.
<td>PRO Enterprise</td> <td>PRO Enterprise</td>
</tr> </tr>
<tr> <tr>
<td>Browser detection</td> <td>Browser Detection</td>
<td><a href="#demo" title="Basic detection">⚠️</a></td> <td><a href="#demo" title="Basic detection">⚠️</a></td>
<td></td> <td></td>
<td></td> <td></td>
@@ -66,7 +66,7 @@ see what's new & breaking.
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>CPU detection</td> <td>CPU Detection</td>
<td><a href="#demo" title="Basic detection">⚠️</a></td> <td><a href="#demo" title="Basic detection">⚠️</a></td>
<td></td> <td></td>
<td></td> <td></td>
@@ -74,7 +74,7 @@ see what's new & breaking.
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>Device detection</td> <td>Device Detection</td>
<td><a href="#demo" title="Basic detection">⚠️</a></td> <td><a href="#demo" title="Basic detection">⚠️</a></td>
<td></td> <td></td>
<td></td> <td></td>
@@ -82,7 +82,7 @@ see what's new & breaking.
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>Engine detection</td> <td>Rendering Engine Detection</td>
<td><a href="#demo" title="Basic detection">⚠️</a></td> <td><a href="#demo" title="Basic detection">⚠️</a></td>
<td></td> <td></td>
<td></td> <td></td>
@@ -98,7 +98,7 @@ see what's new & breaking.
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>Bot detection</td> <td>Enhanced+ Accuracy</td>
<td></td> <td></td>
<td></td> <td></td>
<td></td> <td></td>
@@ -106,7 +106,7 @@ see what's new & breaking.
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>AI Bot detection</td> <td>Bot Detection</td>
<td></td> <td></td>
<td></td> <td></td>
<td></td> <td></td>
@@ -114,7 +114,7 @@ see what's new & breaking.
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>Extras (Apps, Libs, Emails, Media Players, etc) detection</td> <td>AI Detection</td>
<td></td> <td></td>
<td></td> <td></td>
<td></td> <td></td>
@@ -122,7 +122,7 @@ see what's new & breaking.
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>Enhanced detection result</td> <td>Extra Detections (Apps, Libs, Emails, Media Players, Crawlers, and more)</td>
<td></td> <td></td>
<td></td> <td></td>
<td></td> <td></td>
@@ -130,7 +130,7 @@ see what's new & breaking.
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>Client Hints support</td> <td>Client Hints Support</td>
<td></td> <td></td>
<td></td> <td></td>
<td></td> <td></td>
@@ -138,7 +138,7 @@ see what's new & breaking.
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>CommonJS support</td> <td>CommonJS Support</td>
<td></td> <td></td>
<td></td> <td></td>
<td></td> <td></td>
@@ -146,7 +146,7 @@ see what's new & breaking.
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>ES modules support</td> <td>ESM Support</td>
<td></td> <td></td>
<td></td> <td></td>
<td></td> <td></td>
@@ -154,15 +154,15 @@ see what's new & breaking.
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>TypeScript declarations</td> <td>TypeScript Definitions</td>
<td><a href="#demo" title="Community version">⚠️</a></td> <td><a href="#demo" title="Community version"></a></td>
<td></td> <td></td>
<td></td> <td></td>
<td></td> <td></td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>npm module available</td> <td>npm Module Available</td>
<td></td> <td></td>
<td></td> <td></td>
<td></td> <td></td>
@@ -170,7 +170,7 @@ see what's new & breaking.
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>Direct downloads available</td> <td>Direct Downloads Available</td>
<td></td> <td></td>
<td></td> <td></td>
<td></td> <td></td>
@@ -178,7 +178,7 @@ see what's new & breaking.
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>Allows commercial usage</td> <td>Commercial Use Allowed</td>
<td></td> <td></td>
<td></td> <td></td>
<td></td> <td></td>
@@ -186,7 +186,7 @@ see what's new & breaking.
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>Permissive (non-copyleft) license</td> <td>Permissive (non-Copyleft) License</td>
<td></td> <td></td>
<td><strong title="Copyleft license"></strong></td> <td><strong title="Copyleft license"></strong></td>
<td></td> <td></td>
@@ -194,7 +194,7 @@ see what's new & breaking.
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>No open-source obligations</td> <td>No Open-Source Obligations</td>
<td></td> <td></td>
<td><strong title="Copyleft license"></strong></td> <td><strong title="Copyleft license"></strong></td>
<td></td> <td></td>
@@ -202,7 +202,7 @@ see what's new & breaking.
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>Unlimited end-products</td> <td>Unlimited End-Products</td>
<td></td> <td></td>
<td></td> <td></td>
<td></td> <td></td>
@@ -210,7 +210,7 @@ see what's new & breaking.
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>Unlimited deployments</td> <td>Unlimited Deployments</td>
<td></td> <td></td>
<td></td> <td></td>
<td></td> <td></td>
@@ -218,7 +218,7 @@ see what's new & breaking.
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>1-year product support</td> <td>1-year Product Support</td>
<td></td> <td></td>
<td></td> <td></td>
<td></td> <td></td>
@@ -226,7 +226,7 @@ see what's new & breaking.
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>Lifetime updates</td> <td>Lifetime Updates</td>
<td></td> <td></td>
<td></td> <td></td>
<td></td> <td></td>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "ua-parser-js", "name": "ua-parser-js",
"version": "2.0.5", "version": "2.0.6",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "ua-parser-js", "name": "ua-parser-js",
"version": "2.0.5", "version": "2.0.6",
"funding": [ "funding": [
{ {
"type": "opencollective", "type": "opencollective",

View File

@@ -1,25 +1,25 @@
{ {
"title": "UAParser.js", "title": "UAParser.js",
"name": "ua-parser-js", "name": "ua-parser-js",
"version": "2.0.5", "version": "2.0.6",
"author": "Faisal Salman <f@faisalman.com> (http://faisalman.com)", "author": "Faisal Salman <f@faisalman.com> (http://faisalman.com)",
"description": "Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent & Client Hints data. Supports browser & node.js environment", "description": "Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent & Client Hints data. Supports browser & node.js environment",
"keywords": [ "keywords": [
"user-agent", "user-agent",
"client-hints", "client-hints",
"parser",
"browser", "browser",
"engine", "engine",
"os", "os",
"device", "device",
"cpu", "cpu",
"jquery-plugin",
"ecosystem:jquery",
"ua-parser-js", "ua-parser-js",
"browser-detection", "browser-detection",
"device-detection", "device-detection",
"os-detection", "os-detection",
"bot-detection" "bot-detection",
"ai-detection",
"app-detection",
"crawler-detection"
], ],
"homepage": "https://uaparser.dev", "homepage": "https://uaparser.dev",
"contributors": [ "contributors": [

View File

@@ -3,7 +3,7 @@
// Source: /src/enums/ua-parser-enums.js // Source: /src/enums/ua-parser-enums.js
/////////////////////////////////////////////// ///////////////////////////////////////////////
/* Enums for UAParser.js v2.0.5 /* Enums for UAParser.js v2.0.6
https://github.com/faisalman/ua-parser-js https://github.com/faisalman/ua-parser-js
Author: Faisal Salman <f@faisalman.com> Author: Faisal Salman <f@faisalman.com>
AGPLv3 License */ AGPLv3 License */
@@ -24,6 +24,7 @@ export const BrowserName: Readonly<{
AVG: 'AVG Secure Browser', AVG: 'AVG Secure Browser',
BAIDU: 'Baidu Browser', BAIDU: 'Baidu Browser',
BASILISK: 'Basilisk', BASILISK: 'Basilisk',
BING: 'Bing',
BLAZER: 'Blazer', BLAZER: 'Blazer',
BOLT: 'Bolt', BOLT: 'Bolt',
BOWSER: 'Bowser', BOWSER: 'Bowser',
@@ -129,6 +130,7 @@ export const BrowserName: Readonly<{
QUARK: 'Quark', QUARK: 'Quark',
QUPZILLA: 'QupZilla', QUPZILLA: 'QupZilla',
QUTEBROWSER: 'qutebrowser', QUTEBROWSER: 'qutebrowser',
QWANT: 'Qwant',
REKONQ: 'rekonq', REKONQ: 'rekonq',
ROCKMELT: 'Rockmelt', ROCKMELT: 'Rockmelt',
SAFARI: 'Safari', SAFARI: 'Safari',
@@ -243,6 +245,7 @@ export const DeviceVendor: Readonly<{
GEEKSPHONE: 'GeeksPhone', GEEKSPHONE: 'GeeksPhone',
GENERIC: 'Generic', GENERIC: 'Generic',
GOOGLE: 'Google', GOOGLE: 'Google',
HISENSE: 'Hisense',
HMD: 'HMD', HMD: 'HMD',
HP: 'HP', HP: 'HP',
HTC: 'HTC', HTC: 'HTC',
@@ -291,6 +294,7 @@ export const DeviceVendor: Readonly<{
VIVO: 'Vivo', VIVO: 'Vivo',
VIZIO: 'Vizio', VIZIO: 'Vizio',
VODAFONE: 'Vodafone', VODAFONE: 'Vodafone',
WIKO: 'Wiko',
XBOX: 'Xbox', XBOX: 'Xbox',
XIAOMI: 'Xiaomi', XIAOMI: 'Xiaomi',
ZEBRA: 'Zebra', ZEBRA: 'Zebra',
@@ -489,6 +493,7 @@ export const Extension: Readonly<{
DUCKDUCKGO_BOT: 'DuckDuckBot', DUCKDUCKGO_BOT: 'DuckDuckBot',
DUCKDUCKGO_FAVICONS_BOT: 'DuckDuckGo-Favicons-Bot', DUCKDUCKGO_FAVICONS_BOT: 'DuckDuckGo-Favicons-Bot',
ELASTIC: 'Elastic', ELASTIC: 'Elastic',
ELASTIC_SWIFTYPE_BOT: 'Swiftbot',
EXALEAD_EXABOT: 'Exabot', EXALEAD_EXABOT: 'Exabot',
FIRECRAWL_AGENT: 'FirecrawlAgent', FIRECRAWL_AGENT: 'FirecrawlAgent',
FREESPOKE: 'Freespoke', FREESPOKE: 'Freespoke',
@@ -538,6 +543,7 @@ export const Extension: Readonly<{
PERPLEXITY_BOT: 'PerplexityBot', PERPLEXITY_BOT: 'PerplexityBot',
QIHOO_360_SPIDER: '360Spider', QIHOO_360_SPIDER: '360Spider',
QWANT_BOT: 'Qwantbot', QWANT_BOT: 'Qwantbot',
QWANT_BOT_NEWS: 'Qwantbot-news',
REPLICATE_BOT: 'Replicate-Bot', REPLICATE_BOT: 'Replicate-Bot',
RUNPOD_BOT: 'RunPod-Bot', RUNPOD_BOT: 'RunPod-Bot',
SB_INTUITIONS_BOT: 'SBIntuitionsBot', SB_INTUITIONS_BOT: 'SBIntuitionsBot',
@@ -551,6 +557,7 @@ export const Extension: Readonly<{
SOGOU_PIC_SPIDER: 'Sogou Pic Spider', SOGOU_PIC_SPIDER: 'Sogou Pic Spider',
SOGOU_WEB_SPIDER: 'Sogou web spider', SOGOU_WEB_SPIDER: 'Sogou web spider',
STARTPAGE: 'Startpage', STARTPAGE: 'Startpage',
SURLY_BOT: 'SurdotlyBot',
TIMPI_BOT: 'Timpibot', TIMPI_BOT: 'Timpibot',
TOGETHER_BOT: 'Together-Bot', TOGETHER_BOT: 'Together-Bot',
TURNITIN_BOT: 'TurnitinBot', TURNITIN_BOT: 'TurnitinBot',
@@ -631,6 +638,7 @@ export const Extension: Readonly<{
BLUESKY: 'Bluesky', BLUESKY: 'Bluesky',
BUFFER_LINKPREVIEWBOT: 'BufferLinkPreviewBot', BUFFER_LINKPREVIEWBOT: 'BufferLinkPreviewBot',
COHERE_AI: 'Cohere-AI', COHERE_AI: 'Cohere-AI',
DISCORD_BOT: 'Discordbot',
DUCKDUCKGO_ASSISTBOT: 'DuckAssistBot', DUCKDUCKGO_ASSISTBOT: 'DuckAssistBot',
GOOGLE_CHROME_LIGHTHOUSE: 'Chrome-Lighthouse', GOOGLE_CHROME_LIGHTHOUSE: 'Chrome-Lighthouse',
GOOGLE_FEEDFETCHER: 'FeedFetcher-Google', GOOGLE_FEEDFETCHER: 'FeedFetcher-Google',
@@ -643,6 +651,7 @@ export const Extension: Readonly<{
HUBSPOT_PAGE_FETCHER: 'HubSpot Page Fetcher', HUBSPOT_PAGE_FETCHER: 'HubSpot Page Fetcher',
IFRAMELY: 'Iframely', IFRAMELY: 'Iframely',
KAKAOTALK_SCRAP: 'kakaotalk-scrap', KAKAOTALK_SCRAP: 'kakaotalk-scrap',
KEYBASE_BOT: 'KeybaseBot',
META_EXTERNALFETCHER: 'meta-externalfetcher', META_EXTERNALFETCHER: 'meta-externalfetcher',
META_WHATSAPP: 'WhatsApp', META_WHATSAPP: 'WhatsApp',
MICROSOFT_BINGPREVIEW: 'BingPreview', MICROSOFT_BINGPREVIEW: 'BingPreview',
@@ -654,6 +663,9 @@ export const Extension: Readonly<{
PERPLEXITY_USER: 'Perplexity-User', PERPLEXITY_USER: 'Perplexity-User',
PINTEREST_BOT: 'Pinterestbot', PINTEREST_BOT: 'Pinterestbot',
SEMRUSH_SITEAUDITBOT: 'SiteAuditBot', SEMRUSH_SITEAUDITBOT: 'SiteAuditBot',
SLACK_BOT: 'Slackbot',
SLACK_BOT_LINKEXPANDING: 'Slackbot-LinkExpanding',
SLACK_IMGPROXY: 'Slack-ImgProxy',
SNAP_URL_PREVIEW: 'Snap URL Preview', SNAP_URL_PREVIEW: 'Snap URL Preview',
SKYPE_URIPREVIEW: 'SkypeUriPreview', SKYPE_URIPREVIEW: 'SkypeUriPreview',
TELEGRAM_BOT: 'TelegramBot', TELEGRAM_BOT: 'TelegramBot',
@@ -663,6 +675,7 @@ export const Extension: Readonly<{
VERCEL_BOT: 'Vercelbot', VERCEL_BOT: 'Vercelbot',
VERCEL_FLAGS: 'vercelflags', VERCEL_FLAGS: 'vercelflags',
VERCEL_TRACING: 'verceltracing', VERCEL_TRACING: 'verceltracing',
X_TWITTERBOT: 'Twitterbot',
YANDEX_CALENDAR: 'YandexCalendar', YANDEX_CALENDAR: 'YandexCalendar',
YANDEX_DIRECT: 'YandexDirect', YANDEX_DIRECT: 'YandexDirect',
YANDEX_DIRECTDYN: 'YandexDirectDyn', YANDEX_DIRECTDYN: 'YandexDirectDyn',

View File

@@ -1,5 +1,5 @@
/////////////////////////////////////////////// ///////////////////////////////////////////////
/* Enums for UAParser.js v2.0.5 /* Enums for UAParser.js v2.0.6
https://github.com/faisalman/ua-parser-js https://github.com/faisalman/ua-parser-js
Author: Faisal Salman <f@faisalman.com> Author: Faisal Salman <f@faisalman.com>
AGPLv3 License */ AGPLv3 License */

View File

@@ -3,7 +3,7 @@
// Source: /src/enums/ua-parser-enums.js // Source: /src/enums/ua-parser-enums.js
/////////////////////////////////////////////// ///////////////////////////////////////////////
/* Enums for UAParser.js v2.0.5 /* Enums for UAParser.js v2.0.6
https://github.com/faisalman/ua-parser-js https://github.com/faisalman/ua-parser-js
Author: Faisal Salman <f@faisalman.com> Author: Faisal Salman <f@faisalman.com>
AGPLv3 License */ AGPLv3 License */
@@ -24,6 +24,7 @@ const BrowserName = Object.freeze({
AVG: 'AVG Secure Browser', AVG: 'AVG Secure Browser',
BAIDU: 'Baidu Browser', BAIDU: 'Baidu Browser',
BASILISK: 'Basilisk', BASILISK: 'Basilisk',
BING: 'Bing',
BLAZER: 'Blazer', BLAZER: 'Blazer',
BOLT: 'Bolt', BOLT: 'Bolt',
BOWSER: 'Bowser', BOWSER: 'Bowser',
@@ -129,6 +130,7 @@ const BrowserName = Object.freeze({
QUARK: 'Quark', QUARK: 'Quark',
QUPZILLA: 'QupZilla', QUPZILLA: 'QupZilla',
QUTEBROWSER: 'qutebrowser', QUTEBROWSER: 'qutebrowser',
QWANT: 'Qwant',
REKONQ: 'rekonq', REKONQ: 'rekonq',
ROCKMELT: 'Rockmelt', ROCKMELT: 'Rockmelt',
SAFARI: 'Safari', SAFARI: 'Safari',
@@ -243,6 +245,7 @@ const DeviceVendor = Object.freeze({
GEEKSPHONE: 'GeeksPhone', GEEKSPHONE: 'GeeksPhone',
GENERIC: 'Generic', GENERIC: 'Generic',
GOOGLE: 'Google', GOOGLE: 'Google',
HISENSE: 'Hisense',
HMD: 'HMD', HMD: 'HMD',
HP: 'HP', HP: 'HP',
HTC: 'HTC', HTC: 'HTC',
@@ -291,6 +294,7 @@ const DeviceVendor = Object.freeze({
VIVO: 'Vivo', VIVO: 'Vivo',
VIZIO: 'Vizio', VIZIO: 'Vizio',
VODAFONE: 'Vodafone', VODAFONE: 'Vodafone',
WIKO: 'Wiko',
XBOX: 'Xbox', XBOX: 'Xbox',
XIAOMI: 'Xiaomi', XIAOMI: 'Xiaomi',
ZEBRA: 'Zebra', ZEBRA: 'Zebra',
@@ -489,6 +493,7 @@ const Extension = Object.freeze({
DUCKDUCKGO_BOT: 'DuckDuckBot', DUCKDUCKGO_BOT: 'DuckDuckBot',
DUCKDUCKGO_FAVICONS_BOT: 'DuckDuckGo-Favicons-Bot', DUCKDUCKGO_FAVICONS_BOT: 'DuckDuckGo-Favicons-Bot',
ELASTIC: 'Elastic', ELASTIC: 'Elastic',
ELASTIC_SWIFTYPE_BOT: 'Swiftbot',
EXALEAD_EXABOT: 'Exabot', EXALEAD_EXABOT: 'Exabot',
FIRECRAWL_AGENT: 'FirecrawlAgent', FIRECRAWL_AGENT: 'FirecrawlAgent',
FREESPOKE: 'Freespoke', FREESPOKE: 'Freespoke',
@@ -538,6 +543,7 @@ const Extension = Object.freeze({
PERPLEXITY_BOT: 'PerplexityBot', PERPLEXITY_BOT: 'PerplexityBot',
QIHOO_360_SPIDER: '360Spider', QIHOO_360_SPIDER: '360Spider',
QWANT_BOT: 'Qwantbot', QWANT_BOT: 'Qwantbot',
QWANT_BOT_NEWS: 'Qwantbot-news',
REPLICATE_BOT: 'Replicate-Bot', REPLICATE_BOT: 'Replicate-Bot',
RUNPOD_BOT: 'RunPod-Bot', RUNPOD_BOT: 'RunPod-Bot',
SB_INTUITIONS_BOT: 'SBIntuitionsBot', SB_INTUITIONS_BOT: 'SBIntuitionsBot',
@@ -551,6 +557,7 @@ const Extension = Object.freeze({
SOGOU_PIC_SPIDER: 'Sogou Pic Spider', SOGOU_PIC_SPIDER: 'Sogou Pic Spider',
SOGOU_WEB_SPIDER: 'Sogou web spider', SOGOU_WEB_SPIDER: 'Sogou web spider',
STARTPAGE: 'Startpage', STARTPAGE: 'Startpage',
SURLY_BOT: 'SurdotlyBot',
TIMPI_BOT: 'Timpibot', TIMPI_BOT: 'Timpibot',
TOGETHER_BOT: 'Together-Bot', TOGETHER_BOT: 'Together-Bot',
TURNITIN_BOT: 'TurnitinBot', TURNITIN_BOT: 'TurnitinBot',
@@ -631,6 +638,7 @@ const Extension = Object.freeze({
BLUESKY: 'Bluesky', BLUESKY: 'Bluesky',
BUFFER_LINKPREVIEWBOT: 'BufferLinkPreviewBot', BUFFER_LINKPREVIEWBOT: 'BufferLinkPreviewBot',
COHERE_AI: 'Cohere-AI', COHERE_AI: 'Cohere-AI',
DISCORD_BOT: 'Discordbot',
DUCKDUCKGO_ASSISTBOT: 'DuckAssistBot', DUCKDUCKGO_ASSISTBOT: 'DuckAssistBot',
GOOGLE_CHROME_LIGHTHOUSE: 'Chrome-Lighthouse', GOOGLE_CHROME_LIGHTHOUSE: 'Chrome-Lighthouse',
GOOGLE_FEEDFETCHER: 'FeedFetcher-Google', GOOGLE_FEEDFETCHER: 'FeedFetcher-Google',
@@ -643,6 +651,7 @@ const Extension = Object.freeze({
HUBSPOT_PAGE_FETCHER: 'HubSpot Page Fetcher', HUBSPOT_PAGE_FETCHER: 'HubSpot Page Fetcher',
IFRAMELY: 'Iframely', IFRAMELY: 'Iframely',
KAKAOTALK_SCRAP: 'kakaotalk-scrap', KAKAOTALK_SCRAP: 'kakaotalk-scrap',
KEYBASE_BOT: 'KeybaseBot',
META_EXTERNALFETCHER: 'meta-externalfetcher', META_EXTERNALFETCHER: 'meta-externalfetcher',
META_WHATSAPP: 'WhatsApp', META_WHATSAPP: 'WhatsApp',
MICROSOFT_BINGPREVIEW: 'BingPreview', MICROSOFT_BINGPREVIEW: 'BingPreview',
@@ -654,6 +663,9 @@ const Extension = Object.freeze({
PERPLEXITY_USER: 'Perplexity-User', PERPLEXITY_USER: 'Perplexity-User',
PINTEREST_BOT: 'Pinterestbot', PINTEREST_BOT: 'Pinterestbot',
SEMRUSH_SITEAUDITBOT: 'SiteAuditBot', SEMRUSH_SITEAUDITBOT: 'SiteAuditBot',
SLACK_BOT: 'Slackbot',
SLACK_BOT_LINKEXPANDING: 'Slackbot-LinkExpanding',
SLACK_IMGPROXY: 'Slack-ImgProxy',
SNAP_URL_PREVIEW: 'Snap URL Preview', SNAP_URL_PREVIEW: 'Snap URL Preview',
SKYPE_URIPREVIEW: 'SkypeUriPreview', SKYPE_URIPREVIEW: 'SkypeUriPreview',
TELEGRAM_BOT: 'TelegramBot', TELEGRAM_BOT: 'TelegramBot',
@@ -663,6 +675,7 @@ const Extension = Object.freeze({
VERCEL_BOT: 'Vercelbot', VERCEL_BOT: 'Vercelbot',
VERCEL_FLAGS: 'vercelflags', VERCEL_FLAGS: 'vercelflags',
VERCEL_TRACING: 'verceltracing', VERCEL_TRACING: 'verceltracing',
X_TWITTERBOT: 'Twitterbot',
YANDEX_CALENDAR: 'YandexCalendar', YANDEX_CALENDAR: 'YandexCalendar',
YANDEX_DIRECT: 'YandexDirect', YANDEX_DIRECT: 'YandexDirect',
YANDEX_DIRECTDYN: 'YandexDirectDyn', YANDEX_DIRECTDYN: 'YandexDirectDyn',

View File

@@ -1,5 +1,5 @@
/////////////////////////////////////////////// ///////////////////////////////////////////////
/* Extensions for UAParser.js v2.0.5 /* Extensions for UAParser.js v2.0.6
https://github.com/faisalman/ua-parser-js https://github.com/faisalman/ua-parser-js
Author: Faisal Salman <f@faisalman.com> Author: Faisal Salman <f@faisalman.com>
AGPLv3 License */ AGPLv3 License */

View File

@@ -3,7 +3,7 @@
// Source: /src/extensions/ua-parser-extensions.js // Source: /src/extensions/ua-parser-extensions.js
/////////////////////////////////////////////// ///////////////////////////////////////////////
/* Extensions for UAParser.js v2.0.5 /* Extensions for UAParser.js v2.0.6
https://github.com/faisalman/ua-parser-js https://github.com/faisalman/ua-parser-js
Author: Faisal Salman <f@faisalman.com> Author: Faisal Salman <f@faisalman.com>
AGPLv3 License */ AGPLv3 License */
@@ -67,8 +67,10 @@ const Crawlers = Object.freeze({
// PerplexityBot - https://perplexity.ai/perplexitybot // PerplexityBot - https://perplexity.ai/perplexitybot
// SBIntuitionsBot - https://www.sbintuitions.co.jp/bot/ // SBIntuitionsBot - https://www.sbintuitions.co.jp/bot/
// SeznamBot - http://napoveda.seznam.cz/seznambot-intro // SeznamBot - http://napoveda.seznam.cz/seznambot-intro
// SurdotlyBot - http://sur.ly/bot.html
// Swiftbot - https://swiftype.com/swiftbot
// YepBot - https://yep.com/yepbot/ // YepBot - https://yep.com/yepbot/
/((?:adidx|ahrefs|amazon|bing|brave|cc|contx|coveo|criteo|dot|duckduck(?:go-favicons-)?|exa|facebook|gpt|iask|kagi|kangaroo |linkedin|mj12|mojeek|oai-search|onespot-scraper|perplexity|sbintuitions|semrush|seznam|yep)bot)\/([\w\.-]+)/i, /((?:adidx|ahrefs|amazon|bing|brave|cc|contx|coveo|criteo|dot|duckduck(?:go-favicons-)?|exa|facebook|gpt|iask|kagi|kangaroo |linkedin|mj12|mojeek|oai-search|onespot-scraper|perplexity|sbintuitions|semrush|seznam|surdotly|swift|yep)bot)\/([\w\.-]+)/i,
// Algolia Crawler // Algolia Crawler
/(algolia crawler(?: renderscript)?)\/?([\w\.]*)/i, /(algolia crawler(?: renderscript)?)\/?([\w\.]*)/i,
@@ -102,7 +104,7 @@ const Crawlers = Object.freeze({
/(oncrawl) mobile\/([\w\.]+)/i, /(oncrawl) mobile\/([\w\.]+)/i,
// Qwantbot - https://help.qwant.com/bot // Qwantbot - https://help.qwant.com/bot
/(qwantbot)[-\w]*\/?([\w\.]*)/i, /(qwantbot(?:-news)?)[-\w]*\/?([\w\.]*)/i,
// SemrushBot - http://www.semrush.com/bot.html // SemrushBot - http://www.semrush.com/bot.html
/((?:semrush|splitsignal)bot[-abcfimostw]*)\/?([\w\.-]*)/i, /((?:semrush|splitsignal)bot[-abcfimostw]*)\/?([\w\.-]*)/i,
@@ -287,8 +289,8 @@ const Fetchers = Object.freeze({
[NAME, VERSION, [TYPE, FETCHER]], [NAME, VERSION, [TYPE, FETCHER]],
[ [
// Google Bots / Chrome-Lighthouse / Gemini-Deep-Research / Snapchat / Vercelbot / Yandex Bots // Google Bots / Chrome-Lighthouse / Gemini-Deep-Research / KeybaseBot / Snapchat / Vercelbot / Yandex Bots
/((?:better uptime |telegram|vercel)bot|chrome-lighthouse|feedfetcher-google|gemini-deep-research|google(?:imageproxy|-read-aloud|-pagerenderer|producer)|snap url preview|vercel(flags|tracing|-(favicon|screenshot)-bot)|yandex(?:sitelinks|userproxy))/i /((?:better uptime |keybase|telegram|vercel)bot|chrome-lighthouse|feedfetcher-google|gemini-deep-research|google(?:imageproxy|-read-aloud|-pagerenderer|producer)|snap url preview|vercel(flags|tracing|-(favicon|screenshot)-bot)|yandex(?:sitelinks|userproxy))/i
], ],
[NAME, [TYPE, FETCHER]], [NAME, [TYPE, FETCHER]],
], ],

View File

@@ -1,5 +1,5 @@
/////////////////////////////////////////////// ///////////////////////////////////////////////
/* Helpers for UAParser.js v2.0.5 /* Helpers for UAParser.js v2.0.6
https://github.com/faisalman/ua-parser-js https://github.com/faisalman/ua-parser-js
Author: Faisal Salman <f@faisalman.com> Author: Faisal Salman <f@faisalman.com>
AGPLv3 License */ AGPLv3 License */

View File

@@ -3,7 +3,7 @@
// Source: /src/helpers/ua-parser-helpers.js // Source: /src/helpers/ua-parser-helpers.js
/////////////////////////////////////////////// ///////////////////////////////////////////////
/* Helpers for UAParser.js v2.0.5 /* Helpers for UAParser.js v2.0.6
https://github.com/faisalman/ua-parser-js https://github.com/faisalman/ua-parser-js
Author: Faisal Salman <f@faisalman.com> Author: Faisal Salman <f@faisalman.com>
AGPLv3 License */ AGPLv3 License */

View File

@@ -1,4 +1,4 @@
// Type definitions for UAParser.js v2.0.5 // Type definitions for UAParser.js v2.0.6
// Project: https://github.com/faisalman/ua-parser-js // Project: https://github.com/faisalman/ua-parser-js
// Definitions by: Faisal Salman <https://github.com/faisalman> // Definitions by: Faisal Salman <https://github.com/faisalman>

View File

@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
/* UAParser.js v2.0.5 /* UAParser.js v2.0.6
Copyright © 2012-2025 Faisal Salman <f@faisalman.com> Copyright © 2012-2025 Faisal Salman <f@faisalman.com>
AGPLv3 License *//* AGPLv3 License *//*
Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data. Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data.
@@ -19,7 +19,7 @@
// Constants // Constants
///////////// /////////////
var LIBVERSION = '2.0.5', var LIBVERSION = '2.0.6',
UA_MAX_LENGTH = 500, UA_MAX_LENGTH = 500,
USER_AGENT = 'user-agent', USER_AGENT = 'user-agent',
EMPTY = '', EMPTY = '',

View File

@@ -3,7 +3,7 @@
// Source: /src/main/ua-parser.js // Source: /src/main/ua-parser.js
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
/* UAParser.js v2.0.5 /* UAParser.js v2.0.6
Copyright © 2012-2025 Faisal Salman <f@faisalman.com> Copyright © 2012-2025 Faisal Salman <f@faisalman.com>
AGPLv3 License *//* AGPLv3 License *//*
Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data. Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data.
@@ -21,26 +21,26 @@
// Constants // Constants
///////////// /////////////
var LIBVERSION = '2.0.5', var LIBVERSION = '2.0.6',
UA_MAX_LENGTH = 500, UA_MAX_LENGTH = 500,
USER_AGENT = 'user-agent', USER_AGENT = 'user-agent',
EMPTY = '', EMPTY = '',
UNKNOWN = '?', UNKNOWN = '?',
TYPEOF = {
// typeof FUNCTION : 'function',
FUNC_TYPE = 'function', OBJECT : 'object',
UNDEF_TYPE = 'undefined', STRING : 'string',
OBJ_TYPE = 'object', UNDEFINED : 'undefined'
STR_TYPE = 'string', },
// properties // properties
UA_BROWSER = 'browser', BROWSER = 'browser',
UA_CPU = 'cpu', CPU = 'cpu',
UA_DEVICE = 'device', DEVICE = 'device',
UA_ENGINE = 'engine', ENGINE = 'engine',
UA_OS = 'os', OS = 'os',
UA_RESULT = 'result', RESULT = 'result',
NAME = 'name', NAME = 'name',
TYPE = 'type', TYPE = 'type',
VENDOR = 'vendor', VENDOR = 'vendor',
@@ -68,16 +68,16 @@
PLATFORM = 'platform', PLATFORM = 'platform',
PLATFORMVER = 'platformVersion', PLATFORMVER = 'platformVersion',
BITNESS = 'bitness', BITNESS = 'bitness',
CH_HEADER = 'sec-ch-ua', CH = 'sec-ch-ua',
CH_HEADER_FULL_VER_LIST = CH_HEADER + '-full-version-list', CH_FULL_VER_LIST= CH + '-full-version-list',
CH_HEADER_ARCH = CH_HEADER + '-arch', CH_ARCH = CH + '-arch',
CH_HEADER_BITNESS = CH_HEADER + '-' + BITNESS, CH_BITNESS = CH + '-' + BITNESS,
CH_HEADER_FORM_FACTORS = CH_HEADER + '-form-factors', CH_FORM_FACTORS = CH + '-form-factors',
CH_HEADER_MOBILE = CH_HEADER + '-' + MOBILE, CH_MOBILE = CH + '-' + MOBILE,
CH_HEADER_MODEL = CH_HEADER + '-' + MODEL, CH_MODEL = CH + '-' + MODEL,
CH_HEADER_PLATFORM = CH_HEADER + '-' + PLATFORM, CH_PLATFORM = CH + '-' + PLATFORM,
CH_HEADER_PLATFORM_VER = CH_HEADER_PLATFORM + '-version', CH_PLATFORM_VER = CH_PLATFORM + '-version',
CH_ALL_VALUES = [BRANDS, FULLVERLIST, MOBILE, MODEL, PLATFORM, PLATFORMVER, ARCHITECTURE, FORMFACTORS, BITNESS], CH_ALL_VALUES = [BRANDS, FULLVERLIST, MOBILE, MODEL, PLATFORM, PLATFORMVER, ARCHITECTURE, FORMFACTORS, BITNESS],
// device vendors // device vendors
AMAZON = 'Amazon', AMAZON = 'Amazon',
@@ -116,7 +116,7 @@
// os // os
WINDOWS = 'Windows'; WINDOWS = 'Windows';
var isWindow = typeof window !== UNDEF_TYPE, var isWindow = typeof window !== TYPEOF.UNDEFINED,
NAVIGATOR = (isWindow && window.navigator) ? NAVIGATOR = (isWindow && window.navigator) ?
window.navigator : window.navigator :
undefined, undefined,
@@ -152,7 +152,7 @@
return enums; return enums;
}, },
has = function (str1, str2) { has = function (str1, str2) {
if (typeof str1 === OBJ_TYPE && str1.length > 0) { if (typeof str1 === TYPEOF.OBJECT && str1.length > 0) {
for (var i in str1) { for (var i in str1) {
if (lowerize(str2) == lowerize(str1[i])) return true; if (lowerize(str2) == lowerize(str1[i])) return true;
} }
@@ -166,7 +166,7 @@
} }
}, },
isString = function (val) { isString = function (val) {
return typeof val === STR_TYPE; return typeof val === TYPEOF.STRING;
}, },
itemListToArray = function (header) { itemListToArray = function (header) {
if (!header) return undefined; if (!header) return undefined;
@@ -193,7 +193,7 @@
if (!arr.hasOwnProperty(i)) continue; if (!arr.hasOwnProperty(i)) continue;
var propName = arr[i]; var propName = arr[i];
if (typeof propName == OBJ_TYPE && propName.length == 2) { if (typeof propName == TYPEOF.OBJECT && propName.length == 2) {
this[propName[0]] = propName[1]; this[propName[0]] = propName[1];
} else { } else {
this[propName] = undefined; this[propName] = undefined;
@@ -208,10 +208,8 @@
return strip(/\\?\"/g, str); return strip(/\\?\"/g, str);
}, },
trim = function (str, len) { trim = function (str, len) {
if (isString(str)) { str = strip(/^\s\s*/, String(str));
str = strip(/^\s\s*/, str); return typeof len === TYPEOF.UNDEFINED ? str : str.substring(0, len);
return typeof len === UNDEF_TYPE ? str : str.substring(0, UA_MAX_LENGTH);
}
}; };
/////////////// ///////////////
@@ -242,9 +240,9 @@
match = matches[++k]; match = matches[++k];
q = props[p]; q = props[p];
// check if given property is actually array // check if given property is actually array
if (typeof q === OBJ_TYPE && q.length > 0) { if (typeof q === TYPEOF.OBJECT && q.length > 0) {
if (q.length === 2) { if (q.length === 2) {
if (typeof q[1] == FUNC_TYPE) { if (typeof q[1] == TYPEOF.FUNCTION) {
// assign modified match // assign modified match
this[q[0]] = q[1].call(this, match); this[q[0]] = q[1].call(this, match);
} else { } else {
@@ -253,7 +251,7 @@
} }
} else if (q.length >= 3) { } else if (q.length >= 3) {
// Check whether q[1] FUNCTION or REGEX // Check whether q[1] FUNCTION or REGEX
if (typeof q[1] === FUNC_TYPE && !(q[1].exec && q[1].test)) { if (typeof q[1] === TYPEOF.FUNCTION && !(q[1].exec && q[1].test)) {
if (q.length > 3) { if (q.length > 3) {
this[q[0]] = match ? q[1].apply(this, q.slice(2)) : undefined; this[q[0]] = match ? q[1].apply(this, q.slice(2)) : undefined;
} else { } else {
@@ -285,7 +283,7 @@
for (var i in map) { for (var i in map) {
// check if current value is array // check if current value is array
if (typeof map[i] === OBJ_TYPE && map[i].length > 0) { if (typeof map[i] === TYPEOF.OBJECT && map[i].length > 0) {
for (var j = 0; j < map[i].length; j++) { for (var j = 0; j < map[i].length; j++) {
if (has(map[i][j], str)) { if (has(map[i][j], str)) {
return (i === UNKNOWN) ? undefined : i; return (i === UNKNOWN) ? undefined : i;
@@ -379,10 +377,11 @@
/(avant|iemobile|slim(?:browser|boat|jet))[\/ ]?([\d\.]*)/i, // Avant/IEMobile/SlimBrowser/SlimBoat/Slimjet /(avant|iemobile|slim(?:browser|boat|jet))[\/ ]?([\d\.]*)/i, // Avant/IEMobile/SlimBrowser/SlimBoat/Slimjet
/(?:ms|\()(ie) ([\w\.]+)/i, // Internet Explorer /(?:ms|\()(ie) ([\w\.]+)/i, // Internet Explorer
// Blink/Webkit/KHTML based // Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS/Bowser/QupZilla/Falkon/LG Browser/Otter/qutebrowser/Dooble // Blink/Webkit/KHTML based // Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS/Bowser/QupZilla/Falkon/LG Browser/Otter/qutebrowser/Dooble/Palemoon
/(flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi|iridium|phantomjs|bowser|qupzilla|falkon|rekonq|puffin|brave|whale(?!.+naver)|qqbrowserlite|duckduckgo|klar|helio|(?=comodo_)?dragon|otter|dooble|(?:lg |qute)browser)\/([-\w\.]+)/i, /(flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi|iridium|phantomjs|bowser|qupzilla|falkon|rekonq|puffin|brave|whale(?!.+naver)|qqbrowserlite|duckduckgo|klar|helio|(?=comodo_)?dragon|otter|dooble|(?:lg |qute)browser|palemoon)\/([-\w\.]+)/i,
// Rekonq/Puffin/Brave/Whale/QQBrowserLite/QQ//Vivaldi/DuckDuckGo/Klar/Helio/Dragon // Rekonq/Puffin/Brave/Whale/QQBrowserLite/QQ//Vivaldi/DuckDuckGo/Klar/Helio/Dragon
/(heytap|ovi|115|surf)browser\/([\d\.]+)/i, // HeyTap/Ovi/115/Surf /(heytap|ovi|115|surf|qwant)browser\/([\d\.]+)/i, // HeyTap/Ovi/115/Surf
/(qwant)(?:ios|mobile)\/([\d\.]+)/i, // Qwant
/(ecosia|weibo)(?:__| \w+@)([\d\.]+)/i // Ecosia/Weibo /(ecosia|weibo)(?:__| \w+@)([\d\.]+)/i // Ecosia/Weibo
], [NAME, VERSION], [ ], [NAME, VERSION], [
/quark(?:pc)?\/([-\w\.]+)/i // Quark /quark(?:pc)?\/([-\w\.]+)/i // Quark
@@ -451,6 +450,7 @@
/\b(line)\/([\w\.]+)\/iab/i, // Line App for Android /\b(line)\/([\w\.]+)\/iab/i, // Line App for Android
/(alipay)client\/([\w\.]+)/i, // Alipay /(alipay)client\/([\w\.]+)/i, // Alipay
/(twitter)(?:and| f.+e\/([\w\.]+))/i, // Twitter /(twitter)(?:and| f.+e\/([\w\.]+))/i, // Twitter
/(bing)(?:web|sapphire)\/([\w\.]+)/i, // Bing
/(instagram|snapchat|klarna)[\/ ]([-\w\.]+)/i // Instagram/Snapchat/Klarna /(instagram|snapchat|klarna)[\/ ]([-\w\.]+)/i // Instagram/Snapchat/Klarna
], [NAME, VERSION, [TYPE, INAPP]], [ ], [NAME, VERSION, [TYPE, INAPP]], [
/\bgsa\/([\w\.]+) .*safari\//i // Google Search Appliance on iOS /\bgsa\/([\w\.]+) .*safari\//i // Google Search Appliance on iOS
@@ -508,10 +508,10 @@
/(swiftfox)/i, // Swiftfox /(swiftfox)/i, // Swiftfox
/(icedragon|iceweasel|camino|chimera|fennec|maemo browser|minimo|conkeror)[\/ ]?([\w\.\+]+)/i, /(icedragon|iceweasel|camino|chimera|fennec|maemo browser|minimo|conkeror)[\/ ]?([\w\.\+]+)/i,
// IceDragon/Iceweasel/Camino/Chimera/Fennec/Maemo/Minimo/Conkeror // IceDragon/Iceweasel/Camino/Chimera/Fennec/Maemo/Minimo/Conkeror
/(seamonkey|k-meleon|icecat|iceape|firebird|phoenix|palemoon|basilisk|waterfox)\/([-\w\.]+)$/i, /(seamonkey|k-meleon|icecat|iceape|firebird|phoenix|basilisk|waterfox)\/([-\w\.]+)$/i,
// Firefox/SeaMonkey/K-Meleon/IceCat/IceApe/Firebird/Phoenix // Firefox/SeaMonkey/K-Meleon/IceCat/IceApe/Firebird/Phoenix
/(firefox)\/([\w\.]+)/i, // Other Firefox-based /(firefox)\/([\w\.]+)/i, // Other Firefox-based
/(mozilla)\/([\w\.]+) .+rv\:.+gecko\/\d+/i, // Mozilla /(mozilla)\/([\w\.]+(?= .+rv\:.+gecko\/\d+)|[0-4][\w\.]+(?!.+compatible))/i, // Mozilla
// Other // Other
/(amaya|dillo|doris|icab|ladybird|lynx|mosaic|netsurf|obigo|polaris|w3m|(?:go|ice|up)[\. ]?browser)[-\/ ]?v?([\w\.]+)/i, /(amaya|dillo|doris|icab|ladybird|lynx|mosaic|netsurf|obigo|polaris|w3m|(?:go|ice|up)[\. ]?browser)[-\/ ]?v?([\w\.]+)/i,
@@ -549,6 +549,8 @@
/((ppc|powerpc)(64)?)( mac|;|\))/i, // PowerPC /((ppc|powerpc)(64)?)( mac|;|\))/i, // PowerPC
/(?:osf1|[freopnt]{3,4}bsd) (alpha)/i // Alpha /(?:osf1|[freopnt]{3,4}bsd) (alpha)/i // Alpha
], [[ARCHITECTURE, /ower/, EMPTY, lowerize]], [ ], [[ARCHITECTURE, /ower/, EMPTY, lowerize]], [
/mc680.0/i
], [[ARCHITECTURE, '68k']], [
/winnt.+\[axp/i /winnt.+\[axp/i
], [[ARCHITECTURE, 'alpha']] ], [[ARCHITECTURE, 'alpha']]
], ],
@@ -568,11 +570,10 @@
], [MODEL, [VENDOR, SAMSUNG], [TYPE, MOBILE]], [ ], [MODEL, [VENDOR, SAMSUNG], [TYPE, MOBILE]], [
// Apple // Apple
/(?:\/|\()(ip(?:hone|od)[\w, ]*)(?:\/|;)/i // iPod/iPhone /(?:\/|\()(ip(?:hone|od)[\w, ]*)[\/\);]/i // iPod/iPhone
], [MODEL, [VENDOR, APPLE], [TYPE, MOBILE]], [ ], [MODEL, [VENDOR, APPLE], [TYPE, MOBILE]], [
/\((ipad);[-\w\),; ]+apple/i, // iPad /\b(?:ios|apple\w+)\/.+[\(\/](ipad)/i, // iPad
/applecoremedia\/[\w\.]+ \((ipad)/i, /\b(ipad)[\d,]*[;\] ].+(mac |i(pad)?)os/i
/\b(ipad)\d\d?,\d\d?[;\]].+ios/i
], [MODEL, [VENDOR, APPLE], [TYPE, TABLET]], [ ], [MODEL, [VENDOR, APPLE], [TYPE, TABLET]], [
/(macintosh);/i /(macintosh);/i
], [MODEL, [VENDOR, APPLE]], [ ], [MODEL, [VENDOR, APPLE]], [
@@ -590,13 +591,13 @@
// Huawei // Huawei
/\b((?:ag[rs][2356]?k?|bah[234]?|bg[2o]|bt[kv]|cmr|cpn|db[ry]2?|jdn2|got|kob2?k?|mon|pce|scm|sht?|[tw]gr|vrd)-[ad]?[lw][0125][09]b?|605hw|bg2-u03|(?:gem|fdr|m2|ple|t1)-[7a]0[1-4][lu]|t1-a2[13][lw]|mediapad[\w\. ]*(?= bui|\)))\b(?!.+d\/s)/i /\b((?:ag[rs][2356]?k?|bah[234]?|bg[2o]|bt[kv]|cmr|cpn|db[ry]2?|jdn2|got|kob2?k?|mon|pce|scm|sht?|[tw]gr|vrd)-[ad]?[lw][0125][09]b?|605hw|bg2-u03|(?:gem|fdr|m2|ple|t1)-[7a]0[1-4][lu]|t1-a2[13][lw]|mediapad[\w\. ]*(?= bui|\)))\b(?!.+d\/s)/i
], [MODEL, [VENDOR, HUAWEI], [TYPE, TABLET]], [ ], [MODEL, [VENDOR, HUAWEI], [TYPE, TABLET]], [
/(?:huawei)([-\w ]+)[;\)]/i, /(?:huawei) ?([-\w ]+)[;\)]/i,
/\b(nexus 6p|\w{2,4}e?-[atu]?[ln][\dx][012359c][adn]?)\b(?!.+d\/s)/i /\b(nexus 6p|\w{2,4}e?-[atu]?[ln][\dx][\dc][adnt]?)\b(?!.+d\/s)/i
], [MODEL, [VENDOR, HUAWEI], [TYPE, MOBILE]], [ ], [MODEL, [VENDOR, HUAWEI], [TYPE, MOBILE]], [
// Xiaomi // Xiaomi
/oid[^\)]+; (2[\dbc]{4}(182|283|rp\w{2})[cgl]|m2105k81a?c)(?: bui|\))/i, /oid[^\)]+; (2[\dbc]{4}(182|283|rp\w{2})[cgl]|m2105k81a?c)(?: bui|\))/i,
/\b((?:red)?mi[-_ ]?pad[\w- ]*)(?: bui|\))/i // Mi Pad tablets /\b(?:xiao)?((?:red)?mi[-_ ]?pad[\w- ]*)(?: bui|\))/i // Mi Pad tablets
],[[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, TABLET]], [ ],[[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, TABLET]], [
/\b(poco[\w ]+|m2\d{3}j\d\d[a-z]{2})(?: bui|\))/i, // Xiaomi POCO /\b(poco[\w ]+|m2\d{3}j\d\d[a-z]{2})(?: bui|\))/i, // Xiaomi POCO
@@ -604,7 +605,7 @@
/\b(hm[-_ ]?note?[_ ]?(?:\d\w)?) bui/i, // Xiaomi Hongmi /\b(hm[-_ ]?note?[_ ]?(?:\d\w)?) bui/i, // Xiaomi Hongmi
/\b(redmi[\-_ ]?(?:note|k)?[\w_ ]+)(?: bui|\))/i, // Xiaomi Redmi /\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 /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|pro)?)(?: bui|\))/i, // Xiaomi Mi /\b(mi[-_ ]?(?:a\d|one|one[_ ]plus|note|max|cc)?[_ ]?(?:\d{0,2}\w?)[_ ]?(?:plus|se|lite|pro)?( 5g|lte)?)(?: bui|\))/i, // Xiaomi Mi
/ ([\w ]+) miui\/v?\d/i / ([\w ]+) miui\/v?\d/i
], [[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, MOBILE]], [ ], [[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, MOBILE]], [
@@ -660,7 +661,7 @@
/(nokia) (t[12][01])/i /(nokia) (t[12][01])/i
], [VENDOR, MODEL, [TYPE, TABLET]], [ ], [VENDOR, MODEL, [TYPE, TABLET]], [
/(?:maemo|nokia).*(n900|lumia \d+|rm-\d+)/i, /(?:maemo|nokia).*(n900|lumia \d+|rm-\d+)/i,
/nokia[-_ ]?(([-\w\. ]*))/i /nokia[-_ ]?(([-\w\. ]*?))( bui|\)|;|\/)/i
], [[MODEL, /_/g, ' '], [TYPE, MOBILE], [VENDOR, 'Nokia']], [ ], [[MODEL, /_/g, ' '], [TYPE, MOBILE], [VENDOR, 'Nokia']], [
// Google // Google
@@ -691,7 +692,7 @@
/(playbook);[-\w\),; ]+(rim)/i // BlackBerry PlayBook /(playbook);[-\w\),; ]+(rim)/i // BlackBerry PlayBook
], [MODEL, VENDOR, [TYPE, TABLET]], [ ], [MODEL, VENDOR, [TYPE, TABLET]], [
/\b((?:bb[a-f]|st[hv])100-\d)/i, /\b((?:bb[a-f]|st[hv])100-\d)/i,
/\(bb10; (\w+)/i // BlackBerry 10 /(?:blackberry|\(bb10;) (\w+)/i
], [MODEL, [VENDOR, BLACKBERRY], [TYPE, MOBILE]], [ ], [MODEL, [VENDOR, BLACKBERRY], [TYPE, MOBILE]], [
// Asus // Asus
@@ -771,10 +772,12 @@
/(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus(?! zenw)|dell|jolla|meizu|motorola|polytron|tecno|micromax|advan)[-_ ]?([-\w]*)/i, /(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus(?! zenw)|dell|jolla|meizu|motorola|polytron|tecno|micromax|advan)[-_ ]?([-\w]*)/i,
// BlackBerry/BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron/Tecno/Micromax/Advan // BlackBerry/BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron/Tecno/Micromax/Advan
/; (blu|hmd|imo|infinix|lava|oneplus|tcl)[_ ]([\w\+ ]+?)(?: bui|\)|; r)/i, // BLU/HMD/IMO/Infinix/Lava/OnePlus/TCL // BLU/HMD/IMO/Infinix/Lava/OnePlus/TCL/Wiko
/; (blu|hmd|imo|infinix|lava|oneplus|tcl|wiko)[_ ]([\w\+ ]+?)(?: bui|\)|; r)/i,
/(hp) ([\w ]+\w)/i, // HP iPAQ /(hp) ([\w ]+\w)/i, // HP iPAQ
/(microsoft); (lumia[\w ]+)/i, // Microsoft Lumia /(microsoft); (lumia[\w ]+)/i, // Microsoft Lumia
/(oppo) ?([\w ]+) bui/i, // OPPO /(oppo) ?([\w ]+) bui/i, // OPPO
/(hisense) ([ehv][\w ]+)\)/i, // Hisense
/droid[^;]+; (philips)[_ ]([sv-x][\d]{3,4}[xz]?)/i // Philips /droid[^;]+; (philips)[_ ]([sv-x][\d]{3,4}[xz]?)/i // Philips
], [VENDOR, MODEL, [TYPE, MOBILE]], [ ], [VENDOR, MODEL, [TYPE, MOBILE]], [
@@ -914,7 +917,7 @@
], [MODEL, [TYPE, SMARTTV]], [ ], [MODEL, [TYPE, SMARTTV]], [
/\b((4k|android|smart|opera)[- ]?tv|tv; rv:|large screen[\w ]+safari)\b/i /\b((4k|android|smart|opera)[- ]?tv|tv; rv:|large screen[\w ]+safari)\b/i
], [[TYPE, SMARTTV]], [ ], [[TYPE, SMARTTV]], [
/droid .+?; ([^;]+?)(?: bui|; wv\)|\) applew).+?(mobile|vr|\d) safari/i /droid .+?; ([^;]+?)(?: bui|; wv\)|\) applew|; hmsc).+?(mobile|vr|\d) safari/i
], [MODEL, [TYPE, strMapper, { 'mobile' : 'Mobile', 'xr' : 'VR', '*' : TABLET }]], [ ], [MODEL, [TYPE, strMapper, { 'mobile' : 'Mobile', 'xr' : 'VR', '*' : TABLET }]], [
/\b((tablet|tab)[;\/]|focus\/\d(?!.+mobile))/i // Unidentifiable Tablet /\b((tablet|tab)[;\/]|focus\/\d(?!.+mobile))/i // Unidentifiable Tablet
], [[TYPE, TABLET]], [ ], [[TYPE, TABLET]], [
@@ -967,7 +970,7 @@
// iOS/macOS // iOS/macOS
/[adehimnop]{4,7}\b(?:.*os ([\w]+) like mac|; opera)/i, // iOS /[adehimnop]{4,7}\b(?:.*os ([\w]+) like mac|; opera)/i, // iOS
/(?:ios;fbsv\/|iphone.+ios[\/ ])([\d\.]+)/i, /(?:ios;fbsv|ios(?=.+ip(?:ad|hone))|ip(?:ad|hone)(?: |.+i(?:pad)?)os)[\/ ]([\w\.]+)/i,
/cfnetwork\/.+darwin/i /cfnetwork\/.+darwin/i
], [[VERSION, /_/g, '.'], [NAME, 'iOS']], [ ], [[VERSION, /_/g, '.'], [NAME, 'iOS']], [
/(mac os x) ?([\w\. ]*)/i, /(mac os x) ?([\w\. ]*)/i,
@@ -1052,27 +1055,27 @@
var defaultProps = (function () { var defaultProps = (function () {
var props = { init : {}, isIgnore : {}, isIgnoreRgx : {}, toString : {}}; var props = { init : {}, isIgnore : {}, isIgnoreRgx : {}, toString : {}};
setProps.call(props.init, [ setProps.call(props.init, [
[UA_BROWSER, [NAME, VERSION, MAJOR, TYPE]], [BROWSER, [NAME, VERSION, MAJOR, TYPE]],
[UA_CPU, [ARCHITECTURE]], [CPU, [ARCHITECTURE]],
[UA_DEVICE, [TYPE, MODEL, VENDOR]], [DEVICE, [TYPE, MODEL, VENDOR]],
[UA_ENGINE, [NAME, VERSION]], [ENGINE, [NAME, VERSION]],
[UA_OS, [NAME, VERSION]] [OS, [NAME, VERSION]]
]); ]);
setProps.call(props.isIgnore, [ setProps.call(props.isIgnore, [
[UA_BROWSER, [VERSION, MAJOR]], [BROWSER, [VERSION, MAJOR]],
[UA_ENGINE, [VERSION]], [ENGINE, [VERSION]],
[UA_OS, [VERSION]] [OS, [VERSION]]
]); ]);
setProps.call(props.isIgnoreRgx, [ setProps.call(props.isIgnoreRgx, [
[UA_BROWSER, / ?browser$/i], [BROWSER, / ?browser$/i],
[UA_OS, / ?os$/i] [OS, / ?os$/i]
]); ]);
setProps.call(props.toString, [ setProps.call(props.toString, [
[UA_BROWSER, [NAME, VERSION]], [BROWSER, [NAME, VERSION]],
[UA_CPU, [ARCHITECTURE]], [CPU, [ARCHITECTURE]],
[UA_DEVICE, [VENDOR, MODEL]], [DEVICE, [VENDOR, MODEL]],
[UA_ENGINE, [NAME, VERSION]], [ENGINE, [NAME, VERSION]],
[UA_OS, [NAME, VERSION]] [OS, [NAME, VERSION]]
]); ]);
return props; return props;
})(); })();
@@ -1116,14 +1119,14 @@
return item.detectFeature().get(); return item.detectFeature().get();
}; };
if (itemType != UA_RESULT) { if (itemType != RESULT) {
IData.prototype.is = function (strToCheck) { IData.prototype.is = function (strToCheck) {
var is = false; var is = false;
for (var i in this) { for (var i in this) {
if (this.hasOwnProperty(i) && !has(is_ignoreProps, i) && lowerize(is_ignoreRgx ? strip(is_ignoreRgx, this[i]) : this[i]) == lowerize(is_ignoreRgx ? strip(is_ignoreRgx, strToCheck) : strToCheck)) { if (this.hasOwnProperty(i) && !has(is_ignoreProps, i) && lowerize(is_ignoreRgx ? strip(is_ignoreRgx, this[i]) : this[i]) == lowerize(is_ignoreRgx ? strip(is_ignoreRgx, strToCheck) : strToCheck)) {
is = true; is = true;
if (strToCheck != UNDEF_TYPE) break; if (strToCheck != TYPEOF.UNDEFINED) break;
} else if (strToCheck == UNDEF_TYPE && is) { } else if (strToCheck == TYPEOF.UNDEFINED && is) {
is = !is; is = !is;
break; break;
} }
@@ -1133,11 +1136,11 @@
IData.prototype.toString = function () { IData.prototype.toString = function () {
var str = EMPTY; var str = EMPTY;
for (var i in toString_props) { for (var i in toString_props) {
if (typeof(this[toString_props[i]]) !== UNDEF_TYPE) { if (typeof(this[toString_props[i]]) !== TYPEOF.UNDEFINED) {
str += (str ? ' ' : EMPTY) + this[toString_props[i]]; str += (str ? ' ' : EMPTY) + this[toString_props[i]];
} }
} }
return str || UNDEF_TYPE; return str || TYPEOF.UNDEFINED;
}; };
} }
@@ -1173,19 +1176,19 @@
setProps.call(this, CH_ALL_VALUES); setProps.call(this, CH_ALL_VALUES);
if (isHttpUACH) { if (isHttpUACH) {
setProps.call(this, [ setProps.call(this, [
[BRANDS, itemListToArray(uach[CH_HEADER])], [BRANDS, itemListToArray(uach[CH])],
[FULLVERLIST, itemListToArray(uach[CH_HEADER_FULL_VER_LIST])], [FULLVERLIST, itemListToArray(uach[CH_FULL_VER_LIST])],
[MOBILE, /\?1/.test(uach[CH_HEADER_MOBILE])], [MOBILE, /\?1/.test(uach[CH_MOBILE])],
[MODEL, stripQuotes(uach[CH_HEADER_MODEL])], [MODEL, stripQuotes(uach[CH_MODEL])],
[PLATFORM, stripQuotes(uach[CH_HEADER_PLATFORM])], [PLATFORM, stripQuotes(uach[CH_PLATFORM])],
[PLATFORMVER, stripQuotes(uach[CH_HEADER_PLATFORM_VER])], [PLATFORMVER, stripQuotes(uach[CH_PLATFORM_VER])],
[ARCHITECTURE, stripQuotes(uach[CH_HEADER_ARCH])], [ARCHITECTURE, stripQuotes(uach[CH_ARCH])],
[FORMFACTORS, itemListToArray(uach[CH_HEADER_FORM_FACTORS])], [FORMFACTORS, itemListToArray(uach[CH_FORM_FACTORS])],
[BITNESS, stripQuotes(uach[CH_HEADER_BITNESS])] [BITNESS, stripQuotes(uach[CH_BITNESS])]
]); ]);
} else { } else {
for (var prop in uach) { for (var prop in uach) {
if(this.hasOwnProperty(prop) && typeof uach[prop] !== UNDEF_TYPE) this[prop] = uach[prop]; if(this.hasOwnProperty(prop) && typeof uach[prop] !== TYPEOF.UNDEFINED) this[prop] = uach[prop];
} }
} }
} }
@@ -1210,30 +1213,30 @@
this.detectFeature = function () { this.detectFeature = function () {
if (NAVIGATOR && NAVIGATOR.userAgent == this.ua) { if (NAVIGATOR && NAVIGATOR.userAgent == this.ua) {
switch (this.itemType) { switch (this.itemType) {
case UA_BROWSER: case BROWSER:
// Brave-specific detection // Brave-specific detection
if (NAVIGATOR.brave && typeof NAVIGATOR.brave.isBrave == FUNC_TYPE) { if (NAVIGATOR.brave && typeof NAVIGATOR.brave.isBrave == TYPEOF.FUNCTION) {
this.set(NAME, 'Brave'); this.set(NAME, 'Brave');
} }
break; break;
case UA_DEVICE: case DEVICE:
// Chrome-specific detection: check for 'mobile' value of navigator.userAgentData // Chrome-specific detection: check for 'mobile' value of navigator.userAgentData
if (!this.get(TYPE) && NAVIGATOR_UADATA && NAVIGATOR_UADATA[MOBILE]) { if (!this.get(TYPE) && NAVIGATOR_UADATA && NAVIGATOR_UADATA[MOBILE]) {
this.set(TYPE, MOBILE); this.set(TYPE, MOBILE);
} }
// iPadOS-specific detection: identified as Mac, but has some iOS-only properties // iPadOS-specific detection: identified as Mac, but has some iOS-only properties
if (this.get(MODEL) == 'Macintosh' && NAVIGATOR && typeof NAVIGATOR.standalone !== UNDEF_TYPE && NAVIGATOR.maxTouchPoints && NAVIGATOR.maxTouchPoints > 2) { if (this.get(MODEL) == 'Macintosh' && NAVIGATOR && typeof NAVIGATOR.standalone !== TYPEOF.UNDEFINED && NAVIGATOR.maxTouchPoints && NAVIGATOR.maxTouchPoints > 2) {
this.set(MODEL, 'iPad') this.set(MODEL, 'iPad')
.set(TYPE, TABLET); .set(TYPE, TABLET);
} }
break; break;
case UA_OS: case OS:
// Chrome-specific detection: check for 'platform' value of navigator.userAgentData // Chrome-specific detection: check for 'platform' value of navigator.userAgentData
if (!this.get(NAME) && NAVIGATOR_UADATA && NAVIGATOR_UADATA[PLATFORM]) { if (!this.get(NAME) && NAVIGATOR_UADATA && NAVIGATOR_UADATA[PLATFORM]) {
this.set(NAME, NAVIGATOR_UADATA[PLATFORM]); this.set(NAME, NAVIGATOR_UADATA[PLATFORM]);
} }
break; break;
case UA_RESULT: case RESULT:
var data = this.data; var data = this.data;
var detect = function (itemType) { var detect = function (itemType) {
return data[itemType] return data[itemType]
@@ -1241,22 +1244,33 @@
.detectFeature() .detectFeature()
.get(); .get();
}; };
this.set(UA_BROWSER, detect(UA_BROWSER)) this.set(BROWSER, detect(BROWSER))
.set(UA_CPU, detect(UA_CPU)) .set(CPU, detect(CPU))
.set(UA_DEVICE, detect(UA_DEVICE)) .set(DEVICE, detect(DEVICE))
.set(UA_ENGINE, detect(UA_ENGINE)) .set(ENGINE, detect(ENGINE))
.set(UA_OS, detect(UA_OS)); .set(OS, detect(OS));
} }
} }
return this; return this;
}; };
this.parseUA = function () { this.parseUA = function () {
if (this.itemType != UA_RESULT) { if (this.itemType != RESULT) {
rgxMapper.call(this.data, this.ua, this.rgxMap); rgxMapper.call(this.data, this.ua, this.rgxMap);
} }
if (this.itemType == UA_BROWSER) { switch (this.itemType) {
this.set(MAJOR, majorize(this.get(VERSION))); case BROWSER:
this.set(MAJOR, majorize(this.get(VERSION)));
break;
case OS:
if (this.get(NAME) == 'iOS' && this.get(VERSION) == '18.6') {
// Based on the assumption that iOS version is tightly coupled with Safari version
var realVersion = /\) Version\/([\d\.]+)/.exec(this.ua); // Get Safari version
if (realVersion && parseInt(realVersion[1].substring(0,2), 10) >= 26) {
this.set(VERSION, realVersion[1]); // Set as iOS version
}
}
break;
} }
return this; return this;
}; };
@@ -1266,14 +1280,14 @@
rgxMap = this.rgxMap; rgxMap = this.rgxMap;
switch (this.itemType) { switch (this.itemType) {
case UA_BROWSER: case BROWSER:
case UA_ENGINE: case ENGINE:
var brands = uaCH[FULLVERLIST] || uaCH[BRANDS], prevName; var brands = uaCH[FULLVERLIST] || uaCH[BRANDS], prevName;
if (brands) { if (brands) {
for (var i=0; i<brands.length; i++) { for (var i=0; i<brands.length; i++) {
var brandName = brands[i].brand || brands[i], var brandName = brands[i].brand || brands[i],
brandVersion = brands[i].version; brandVersion = brands[i].version;
if (this.itemType == UA_BROWSER && if (this.itemType == BROWSER &&
!/not.a.brand/i.test(brandName) && !/not.a.brand/i.test(brandName) &&
(!prevName || (!prevName ||
(/Chrom/.test(prevName) && brandName != CHROMIUM) || (/Chrom/.test(prevName) && brandName != CHROMIUM) ||
@@ -1288,20 +1302,20 @@
} }
prevName = brandName; prevName = brandName;
} }
if (this.itemType == UA_ENGINE && brandName == CHROMIUM) { if (this.itemType == ENGINE && brandName == CHROMIUM) {
this.set(VERSION, brandVersion); this.set(VERSION, brandVersion);
} }
} }
} }
break; break;
case UA_CPU: case CPU:
var archName = uaCH[ARCHITECTURE]; var archName = uaCH[ARCHITECTURE];
if (archName) { if (archName) {
if (archName && uaCH[BITNESS] == '64') archName += '64'; if (archName && uaCH[BITNESS] == '64') archName += '64';
rgxMapper.call(this.data, archName + ';', rgxMap); rgxMapper.call(this.data, archName + ';', rgxMap);
} }
break; break;
case UA_DEVICE: case DEVICE:
if (uaCH[MOBILE]) { if (uaCH[MOBILE]) {
this.set(TYPE, MOBILE); this.set(TYPE, MOBILE);
} }
@@ -1331,7 +1345,7 @@
this.set(TYPE, ff); this.set(TYPE, ff);
} }
break; break;
case UA_OS: case OS:
var osName = uaCH[PLATFORM]; var osName = uaCH[PLATFORM];
if(osName) { if(osName) {
var osVersion = uaCH[PLATFORMVER]; var osVersion = uaCH[PLATFORMVER];
@@ -1345,7 +1359,7 @@
.set(VERSION, undefined); .set(VERSION, undefined);
} }
break; break;
case UA_RESULT: case RESULT:
var data = this.data; var data = this.data;
var parse = function (itemType) { var parse = function (itemType) {
return data[itemType] return data[itemType]
@@ -1354,11 +1368,11 @@
.parseCH() .parseCH()
.get(); .get();
}; };
this.set(UA_BROWSER, parse(UA_BROWSER)) this.set(BROWSER, parse(BROWSER))
.set(UA_CPU, parse(UA_CPU)) .set(CPU, parse(CPU))
.set(UA_DEVICE, parse(UA_DEVICE)) .set(DEVICE, parse(DEVICE))
.set(UA_ENGINE, parse(UA_ENGINE)) .set(ENGINE, parse(ENGINE))
.set(UA_OS, parse(UA_OS)); .set(OS, parse(OS));
} }
return this; return this;
}; };
@@ -1376,9 +1390,9 @@
function UAParser (ua, extensions, headers) { function UAParser (ua, extensions, headers) {
if (typeof ua === OBJ_TYPE) { if (typeof ua === TYPEOF.OBJECT) {
if (isExtensions(ua, true)) { if (isExtensions(ua, true)) {
if (typeof extensions === OBJ_TYPE) { if (typeof extensions === TYPEOF.OBJECT) {
headers = extensions; // case UAParser(extensions, headers) headers = extensions; // case UAParser(extensions, headers)
} }
extensions = ua; // case UAParser(extensions) extensions = ua; // case UAParser(extensions)
@@ -1387,13 +1401,13 @@
extensions = undefined; extensions = undefined;
} }
ua = undefined; ua = undefined;
} else if (typeof ua === STR_TYPE && !isExtensions(extensions, true)) { } else if (typeof ua === TYPEOF.STRING && !isExtensions(extensions, true)) {
headers = extensions; // case UAParser(ua, headers) headers = extensions; // case UAParser(ua, headers)
extensions = undefined; extensions = undefined;
} }
if (headers) { if (headers) {
if (typeof headers.append === FUNC_TYPE) { if (typeof headers.append === TYPEOF.FUNCTION) {
// Convert Headers object into a plain object // Convert Headers object into a plain object
var kv = {}; var kv = {};
headers.forEach(function (v, k) { kv[String(k).toLowerCase()] = v; }); headers.forEach(function (v, k) { kv[String(k).toLowerCase()] = v; });
@@ -1414,7 +1428,7 @@
return new UAParser(ua, extensions, headers).getResult(); return new UAParser(ua, extensions, headers).getResult();
} }
var userAgent = typeof ua === STR_TYPE ? ua : // Passed user-agent string var userAgent = typeof ua === TYPEOF.STRING ? ua : // Passed user-agent string
(headers && headers[USER_AGENT] ? headers[USER_AGENT] : // User-Agent from passed headers (headers && headers[USER_AGENT] ? headers[USER_AGENT] : // User-Agent from passed headers
((NAVIGATOR && NAVIGATOR.userAgent) ? NAVIGATOR.userAgent : // navigator.userAgent ((NAVIGATOR && NAVIGATOR.userAgent) ? NAVIGATOR.userAgent : // navigator.userAgent
EMPTY)), // empty string EMPTY)), // empty string
@@ -1425,15 +1439,15 @@
defaultRegexes, defaultRegexes,
createItemFunc = function (itemType) { createItemFunc = function (itemType) {
if (itemType == UA_RESULT) { if (itemType == RESULT) {
return function () { return function () {
return new UAItem(itemType, userAgent, regexMap, httpUACH) return new UAItem(itemType, userAgent, regexMap, httpUACH)
.set('ua', userAgent) .set('ua', userAgent)
.set(UA_BROWSER, this.getBrowser()) .set(BROWSER, this.getBrowser())
.set(UA_CPU, this.getCPU()) .set(CPU, this.getCPU())
.set(UA_DEVICE, this.getDevice()) .set(DEVICE, this.getDevice())
.set(UA_ENGINE, this.getEngine()) .set(ENGINE, this.getEngine())
.set(UA_OS, this.getOS()) .set(OS, this.getOS())
.get(); .get();
}; };
} else { } else {
@@ -1447,16 +1461,15 @@
// public methods // public methods
setProps.call(this, [ setProps.call(this, [
['getBrowser', createItemFunc(UA_BROWSER)], ['getBrowser', createItemFunc(BROWSER)],
['getCPU', createItemFunc(UA_CPU)], ['getCPU', createItemFunc(CPU)],
['getDevice', createItemFunc(UA_DEVICE)], ['getDevice', createItemFunc(DEVICE)],
['getEngine', createItemFunc(UA_ENGINE)], ['getEngine', createItemFunc(ENGINE)],
['getOS', createItemFunc(UA_OS)], ['getOS', createItemFunc(OS)],
['getResult', createItemFunc(UA_RESULT)], ['getResult', createItemFunc(RESULT)],
['getUA', function () { return userAgent; }], ['getUA', function () { return userAgent; }],
['setUA', function (ua) { ['setUA', function (ua) {
if (isString(ua)) if (isString(ua)) userAgent = trim(ua, UA_MAX_LENGTH);
userAgent = ua.length > UA_MAX_LENGTH ? trim(ua, UA_MAX_LENGTH) : ua;
return this; return this;
}] }]
]) ])

View File

@@ -382,12 +382,15 @@ describe('Read user-agent data from req.headers', function () {
assert.strictEqual(engine.name, "EdgeHTML"); assert.strictEqual(engine.name, "EdgeHTML");
}); });
it('Fetch API\'s Header can be passed directly into headers', () => { // Headers supported in node 18+ - https://developer.mozilla.org/en-US/docs/Web/API/Headers
const reqHeaders = new Headers(); if (typeof Headers !== 'undefined') {
reqHeaders.append('User-Agent', 'Midori/0.2.2 (X11; Linux i686; U; en-us) WebKit/531.2+'); it('Fetch API\'s Header can be passed directly into headers', () => {
const { browser } = UAParser(reqHeaders); const reqHeaders = new Headers();
assert.strictEqual(browser.is('Midori'), true); reqHeaders.append('User-Agent', 'Midori/0.2.2 (X11; Linux i686; U; en-us) WebKit/531.2+');
}); const { browser } = UAParser(reqHeaders);
assert.strictEqual(browser.is('Midori'), true);
});
}
it('Headers field name should be case insensitive', function () { it('Headers field name should be case insensitive', function () {
const hEaDeRs = { const hEaDeRs = {