From b20d09655cf01657d00e38e334a757c25b176175 Mon Sep 17 00:00:00 2001 From: Runar Heggset Date: Wed, 3 May 2023 11:28:54 +0200 Subject: [PATCH 01/64] Fix Amazon Fire TV device detection --- src/main/ua-parser.js | 2 +- test/specs/device-all.json | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/ua-parser.js b/src/main/ua-parser.js index 65bab0292..45dddb000 100755 --- a/src/main/ua-parser.js +++ b/src/main/ua-parser.js @@ -627,7 +627,7 @@ ], [VENDOR, [MODEL, APPLE+' TV'], [TYPE, SMARTTV]], [ /crkey/i // Google Chromecast ], [[MODEL, CHROME+'cast'], [VENDOR, GOOGLE], [TYPE, SMARTTV]], [ - /droid.+aft(\w)( bui|\))/i // Fire TV + /droid.+aft(\w+)( bui|\))/i // Fire TV ], [MODEL, [VENDOR, AMAZON], [TYPE, SMARTTV]], [ /\(dtv[\);].+(aquos)/i, /(aquos-tv[\w ]+)\)/i // Sharp diff --git a/test/specs/device-all.json b/test/specs/device-all.json index 1c54884c0..b43969c41 100644 --- a/test/specs/device-all.json +++ b/test/specs/device-all.json @@ -2772,6 +2772,15 @@ "type": "smarttv" } }, + { + "desc": "Amazon Fire TV", + "ua": "Mozilla/5.0 (Linux; Android 9; AFTKA Build/PS7633.3445N; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/108.0.5359.160 Mobile Safari/537.36", + "expect": { + "vendor": "Amazon", + "model": "KA", + "type": "smarttv" + } + }, { "desc": "Android TV", "ua": "Mozilla/5.0 (Linux; Android 10; 2020/2021 UHD Android TV Build/QTG3.201102.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) version/4.0 Chrome/83.0.4103.101 Mobile Safari/537.36", From 420bf1066c02bcf9d4243a9e0c9da8acf00b9811 Mon Sep 17 00:00:00 2001 From: chenyuan-new <53860479+chenyuan-new@users.noreply.github.com> Date: Tue, 8 Aug 2023 16:22:10 +0800 Subject: [PATCH 02/64] fix: remove duplicated BRANDS input when call setProps in UACHData func (#663) --- src/main/ua-parser.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/ua-parser.js b/src/main/ua-parser.js index 45dddb000..a8ed359e7 100755 --- a/src/main/ua-parser.js +++ b/src/main/ua-parser.js @@ -925,7 +925,6 @@ setProps.call(this, [ [BRANDS, itemListToArray(uach[CH_HEADER])], [FULLVERLIST, itemListToArray(uach[CH_HEADER_FULL_VER_LIST])], - [BRANDS, itemListToArray(uach[CH_HEADER])], [MOBILE, /\?1/.test(uach[CH_HEADER_MOBILE])], [MODEL, stripQuotes(uach[CH_HEADER_MODEL])], [PLATFORM, stripQuotes(uach[CH_HEADER_PLATFORM])], From 594806072930fa88966e02640f81b775fe57e71d Mon Sep 17 00:00:00 2001 From: Andreas Kogler Date: Sun, 20 Aug 2023 09:25:56 +0200 Subject: [PATCH 03/64] Implement PlayStation app `WebMAF` detection (#649) * Add support for `WebMAF` detection on Playstation * Extend `WebMAF` support for PlayStation 5 * Update changelog --- changelog.md | 1 + src/main/ua-parser.js | 1 + test/specs/browser-all.json | 20 ++++++++++++++++++++ 3 files changed, 22 insertions(+) diff --git a/changelog.md b/changelog.md index ac8e493be..3baed6c59 100644 --- a/changelog.md +++ b/changelog.md @@ -4,6 +4,7 @@ - What's breaking: - Browser detection on mobile device: `"Chrome" => "Mobile Chrome"`, `"Firefox" => "Mobile Firefox"` - OS detection: `"Mac OS" => "macOS"`, `"Chromium OS" => "Chrome OS"` + - Apps on PlayStation 4/5 now report `WebMAF` instead of `WebKit` for `browser.name` and the `WebMAF`-version in `browser.version` - What's new: - Add some new methods in result object: - Add support for client hints: `withClientHints()` diff --git a/src/main/ua-parser.js b/src/main/ua-parser.js index a8ed359e7..c2b736d4a 100755 --- a/src/main/ua-parser.js +++ b/src/main/ua-parser.js @@ -285,6 +285,7 @@ // Mixed /(kindle)\/([\w\.]+)/i, // Kindle /(lunascape|maxthon|netfront|jasmine|blazer)[\/ ]?([\w\.]*)/i, // Lunascape/Maxthon/Netfront/Jasmine/Blazer + /(webmaf)\/([a-z0-9\.-]+)/i, // Sony/Playstation WebMAF // Trident based /(avant |iemobile|slim)(?:browser)?[\/ ]?([\w\.]*)/i, // Avant/IEMobile/SlimBrowser /(ba?idubrowser)[\/ ]?([\w\.]+)/i, // Baidu Browser diff --git a/test/specs/browser-all.json b/test/specs/browser-all.json index 9ca190c61..d876d5508 100644 --- a/test/specs/browser-all.json +++ b/test/specs/browser-all.json @@ -1148,6 +1148,26 @@ "major" : "undefined" } }, + { + "desc" : "Sony WebMAF SDK (Playstation)", + "ua" : "Mozilla/5.0 (PlayStation 4 WebMAF) AppleWebKit/601.2 (KHTML, like Gecko) WebMAF/v3.1.0-0-ge5873ba4 SDK: (0x09508001u), Built: Nov 1 2022 14:36:14", + "expect" : + { + "name" : "WebMAF", + "version" : "v3.1.0-0-ge5873ba4", + "major" : "3" + } + }, + { + "desc" : "Sony WebMAF SDK (Playstation)", + "ua" : "Mozilla/5.0 (PlayStation 5; WebMAF/1.0.0) AppleWebKit/537.73 (KHTML, like Gecko)", + "expect" : + { + "name" : "WebMAF", + "version" : "1.0.0", + "major" : "1" + } + }, { "desc" : "Swiftfox", "ua" : "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1) Gecko/20061024 Firefox/2.0 (Swiftfox)", From 6b642e28389732d15432807b752ac6bc6090a81b Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Sat, 8 Jun 2024 20:18:56 +0700 Subject: [PATCH 04/64] [Extensions submodule] Add ChatGPT-User as fetcher --- src/extensions/ua-parser-extensions.js | 3 ++- test/specs/browser-fetchers.json | 12 +++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/extensions/ua-parser-extensions.js b/src/extensions/ua-parser-extensions.js index 55a0a0a86..5975ac9ed 100644 --- a/src/extensions/ua-parser-extensions.js +++ b/src/extensions/ua-parser-extensions.js @@ -175,8 +175,9 @@ const Emails = Object.freeze({ const Fetchers = Object.freeze({ browser : [ + // ChatGPT-User - https://platform.openai.com/docs/plugins/bot // BingPreview / Mastodon / Pinterestbot / Redditbot / Telegrambot / Twitterbot - [/(bingpreview|mastodon|(?:discord|linkedin|pinterest|reddit|telegram|twitter)bot)\/([\w\.]+)/i], + [/(bingpreview|chatgpt-user|mastodon|(?:discord|linkedin|pinterest|reddit|telegram|twitter)bot)\/([\w\.]+)/i], [NAME, VERSION, [TYPE, FETCHER]], // Google Bots / Snapchat diff --git a/test/specs/browser-fetchers.json b/test/specs/browser-fetchers.json index 646f07b2a..6b537728f 100644 --- a/test/specs/browser-fetchers.json +++ b/test/specs/browser-fetchers.json @@ -8,5 +8,15 @@ "version" : "1.0b", "type" : "fetcher" } + }, + { + "desc" : "ChatGPT-User", + "ua" : "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko); compatible; ChatGPT-User/1.0; +https://openai.com/bot", + "expect" : + { + "name" : "ChatGPT-User", + "version" : "1.0", + "type" : "fetcher" + } } -] +] \ No newline at end of file From b75e4493dc2903df10d12c151713bcf7e2b75325 Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Mon, 10 Jun 2024 11:43:37 +0700 Subject: [PATCH 05/64] Update changelog --- CHANGELOG.md | 53 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cc30afa4a..80dfe6423 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,27 +1,10 @@ # UAParser.js Changelog -# 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: - - 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()` - - 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()` @@ -29,6 +12,7 @@ - Improve browser detection: DuckDuckGo, ICEBrowser, Klar, QQ, Sleipnir - Improve device detection: Oculus Quest & Oppo Pad - Update latest client hints spec: `formFactor` -> `formFactors` +- In `ua-parser-js/extensions` submodule, `bots` divided into `crawler` / `fetcher` ## Version 2.0.0-beta.2 @@ -64,13 +48,36 @@ - Initial work on new major version +## Version 2.0 -# Version 0.7 / 1.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"` + - AR/VR devices moved to new device type: `xr` + - New property in `browser`: `type` +- What's new: + - 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()` + - Parse directly from command line using `npx ua-parser-js` + - Extensions can be passed as a list to `UAParser()` + - 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 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 +## Version 0.7.38 / 1.0.38 +- Fix error on getOS() when userAgentData.platform is undefined +- Add new browser: Opera GX, Twitter +- Improve browser detection: DuckDuckGo +- Improve device detection: OPPO Pad, Oculus Quest +## Version 0.7.37 / 1.0.37 - Fix misidentified WebView token as device model - Increase UA_MAX_LENGTH to 500 - Add new browser: Alipay, Klarna, Smart Lenovo Browser, Vivo Browser @@ -143,6 +150,10 @@ Version 1.0.x is basically the equivalent of version 0.7.x. See [#536](https://g - Fix trailing comma for ES3 compatibility - Some code refactor -# Version 0.8 +## Version 0.7 / 1.0 + +Version 1.0.x is basically the equivalent of version 0.7.x (mirror/duplicate). See [#536](https://github.com/faisalman/ua-parser-js/issues/536) for the reason behind this confusion. + +## Version 0.8 Version 0.8 was created by accident. This version is now deprecated and no longer maintained, please update to version 0.7 / 1.0. \ No newline at end of file From b52a7ea2682ab896e1ba521f9d07666413fa7db3 Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Tue, 11 Jun 2024 00:00:59 +0700 Subject: [PATCH 06/64] Add new XR device & OS: Pico - https://www.picoxr.com/global --- src/enums/ua-parser-enums.js | 2 ++ src/main/ua-parser.js | 3 +++ test/specs/browser-all.json | 10 +++++++++ test/specs/device-all.json | 27 +++++++++++++++++++++++ test/specs/os-all.json | 42 ++++++++++++++++++++++++++++++++++++ 5 files changed, 84 insertions(+) diff --git a/src/enums/ua-parser-enums.js b/src/enums/ua-parser-enums.js index e60c4826f..252053849 100644 --- a/src/enums/ua-parser-enums.js +++ b/src/enums/ua-parser-enums.js @@ -224,6 +224,7 @@ const Vendor = Object.freeze({ PALM: 'Palm', PANASONIC: 'Panasonic', PEBBLE: 'Pebble', + PICO: 'Pico', POLYTRON: 'Polytron', REALME: 'Realme', RIM: 'RIM', @@ -321,6 +322,7 @@ const OS = Object.freeze({ PALM: 'Palm', PC_BSD: 'PC-BSD', PCLINUXOS: 'PCLinuxOS', + PICO: 'Pico', PLAN9: 'Plan9', PLAYSTATION: 'PlayStation', QNX: 'QNX', diff --git a/src/main/ua-parser.js b/src/main/ua-parser.js index a92cb8624..c80286666 100755 --- a/src/main/ua-parser.js +++ b/src/main/ua-parser.js @@ -733,6 +733,8 @@ /droid.+; (glass) \d/i // Google Glass ], [MODEL, [VENDOR, GOOGLE], [TYPE, XR]], [ + /(pico) (4|neo3(?: link|pro)?)/i // Pico + ], [VENDOR, MODEL, [TYPE, XR]], [ /(quest( \d| pro)?)/i // Oculus Quest ], [MODEL, [VENDOR, FACEBOOK], [TYPE, XR]], [ @@ -836,6 +838,7 @@ // Console /(nintendo|playstation) (\w+)/i, // Nintendo/Playstation /(xbox); +xbox ([^\);]+)/i, // Microsoft Xbox (360, One, X, S, Series X, Series S) + /(pico) .+os([\w\.]+)/i, // Pico // Other /\b(joli|palm)\b ?(?:os)?\/?([\w\.]*)/i, // Joli/Palm diff --git a/test/specs/browser-all.json b/test/specs/browser-all.json index a9b22df50..880ba08e6 100644 --- a/test/specs/browser-all.json +++ b/test/specs/browser-all.json @@ -908,6 +908,16 @@ "major" : "3" } }, + { + "desc" : "PicoBrowser", + "ua" : "Mozilla/5.0 (X11; Linux x86_64; PICO 4 OS5.8.2 like Quest) AppleWebKit/537.36 (KHTML, like Gecko) PicoBrowser/3.3.38 Chrome/105.0.5195.68 VR Safari/537.36", + "expect" : + { + "name" : "Pico Browser", + "version" : "3.3.38", + "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", diff --git a/test/specs/device-all.json b/test/specs/device-all.json index 252782cdb..5e08f1361 100644 --- a/test/specs/device-all.json +++ b/test/specs/device-all.json @@ -1790,6 +1790,33 @@ "type": "smarttv" } }, + { + "desc": "Pico 4", + "ua": "Mozilla/5.0 (X11; Linux x86_64; PICO 4 OS5.8.2 like Quest) AppleWebKit/537.36 (KHTML, like Gecko) PicoBrowser/3.3.38 Chrome/105.0.5195.68 VR Safari/537.36", + "expect": { + "vendor": "PICO", + "model": "4", + "type": "xr" + } + }, + { + "desc": "Pico 4", + "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": { + "vendor": "PICO", + "model": "4", + "type": "xr" + } + }, + { + "desc": "Pico Neo3 Link", + "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": { + "vendor": "Pico", + "model": "Neo3 Link", + "type": "xr" + } + }, { "desc": "Roku", "ua": "Mozilla/5.0 (Roku) AppleWebKit/537.36 (KHTML, like Gecko) Web/1.1 Safari/537.36", diff --git a/test/specs/os-all.json b/test/specs/os-all.json index 9ad108cbb..5e9beb288 100644 --- a/test/specs/os-all.json +++ b/test/specs/os-all.json @@ -440,6 +440,39 @@ "version" : "4" } }, + { + "desc" : "PlayStation 5", + "ua" : "Mozilla/5.0 (PlayStation 5/SmartTV) AppleWebKit/605.1.15 (KHTML, like Gecko)", + "expect" : + { + "name" : "PlayStation", + "version" : "5" + } + }, + { + "desc": "Pico 4", + "ua": "Mozilla/5.0 (X11; Linux x86_64; PICO 4 OS5.8.2 like Quest) AppleWebKit/537.36 (KHTML, like Gecko) PicoBrowser/3.3.38 Chrome/105.0.5195.68 VR Safari/537.36", + "expect": { + "name" : "PICO", + "version" : "5.8.2" + } + }, + { + "desc": "Pico 4", + "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", + "version" : "5.4.0" + } + }, + { + "desc": "Pico Neo3 Link", + "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", + "version" : "5.8.4.0" + } + }, { "desc" : "Xbox 360", "ua" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64; Xbox; Xbox 360) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36", @@ -476,6 +509,15 @@ "version" : "Series X" } }, + { + "desc" : "Xbox Series S", + "ua" : "Mozilla/5.0 (Compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0; Xbox; Xbox Series S)", + "expect" : + { + "name" : "Xbox", + "version" : "Series S" + } + }, { "desc" : "Mint", "ua" : "Opera/9.80 (X11; Linux x86_64; Edition Linux Mint) Presto/2.12.388 Version/12.16", From de4978e8d92a94350ae575745b4e8ca1a7faf62b Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Tue, 11 Jun 2024 09:12:36 +0700 Subject: [PATCH 07/64] Add `mediaplayer` as a new `browser.type` --- src/enums/ua-parser-enums.js | 1 + src/enums/ua-parser-enums.mjs | 3 ++ src/extensions/ua-parser-extensions.js | 51 +++++++++++++------------- src/main/ua-parser.d.ts | 2 +- test/dts-test.ts | 2 +- 5 files changed, 32 insertions(+), 27 deletions(-) diff --git a/src/enums/ua-parser-enums.js b/src/enums/ua-parser-enums.js index 252053849..9d93f23b0 100644 --- a/src/enums/ua-parser-enums.js +++ b/src/enums/ua-parser-enums.js @@ -152,6 +152,7 @@ const BrowserType = Object.freeze({ EMAIL: 'email', FETCHER: 'fetcher', INAPP: 'inapp', + MEDIAPLAYER: 'mediaplayer', MODULE: 'module' }); diff --git a/src/enums/ua-parser-enums.mjs b/src/enums/ua-parser-enums.mjs index 92aa605fd..539cf3059 100644 --- a/src/enums/ua-parser-enums.mjs +++ b/src/enums/ua-parser-enums.mjs @@ -156,6 +156,7 @@ const BrowserType = Object.freeze({ EMAIL: 'email', FETCHER: 'fetcher', INAPP: 'inapp', + MEDIAPLAYER: 'mediaplayer', MODULE: 'module' }); @@ -228,6 +229,7 @@ const Vendor = Object.freeze({ PALM: 'Palm', PANASONIC: 'Panasonic', PEBBLE: 'Pebble', + PICO: 'Pico', POLYTRON: 'Polytron', REALME: 'Realme', RIM: 'RIM', @@ -325,6 +327,7 @@ const OS = Object.freeze({ PALM: 'Palm', PC_BSD: 'PC-BSD', PCLINUXOS: 'PCLinuxOS', + PICO: 'Pico', PLAN9: 'Plan9', PLAYSTATION: 'PlayStation', QNX: 'QNX', diff --git a/src/extensions/ua-parser-extensions.js b/src/extensions/ua-parser-extensions.js index 5975ac9ed..84d391f10 100644 --- a/src/extensions/ua-parser-extensions.js +++ b/src/extensions/ua-parser-extensions.js @@ -19,6 +19,7 @@ const CLI = 'cli'; const EMAIL = 'email'; const FETCHER = 'fetcher'; const INAPP = 'inapp'; +const MEDIAPLAYER = 'mediaplayer'; const MODULE = 'module'; ////////////////////// @@ -221,13 +222,13 @@ const MediaPlayers = Object.freeze({ /(apple(?:coremedia|))\/([\w\._]+)/i, // Generic Apple CoreMedia /(coremedia) v([\w\._]+)/i - ], [NAME, VERSION], [ + ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [ /(aqualung|lyssna|bsplayer)\/([\w\.-]+)/i // Aqualung/Lyssna/BSPlayer - ], [NAME, VERSION], [ + ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [ /(ares|ossproxy)\s([\w\.-]+)/i // Ares/OSSProxy - ], [NAME, VERSION], [ + ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [ /(audacious|audimusicstream|amarok|bass|core|dalvik|gnomemplayer|music on console|nsplayer|psp-internetradioplayer|videos)\/([\w\.-]+)/i, // Audacious/AudiMusicStream/Amarok/BASS/OpenCORE/Dalvik/GnomeMplayer/MoC @@ -235,90 +236,90 @@ const MediaPlayers = Object.freeze({ /(clementine|music player daemon)\s([\w\.-]+)/i, // Clementine/MPD /(lg player|nexplayer)\s([\d\.]+)/i, /player\/(nexplayer|lg player)\s([\w\.-]+)/i // NexPlayer/LG Player - ], [NAME, VERSION], [ + ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [ /(nexplayer)\s([\w\.-]+)/i // Nexplayer - ], [NAME, VERSION], [ + ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [ /(flrp)\/([\w\.-]+)/i // Flip Player - ], [[NAME, 'Flip Player'], VERSION], [ + ], [[NAME, 'Flip Player'], VERSION, [TYPE, MEDIAPLAYER]], [ /(fstream|nativehost|queryseekspider|ia-archiver|facebookexternalhit)/i // FStream/NativeHost/QuerySeekSpider/IA Archiver/facebookexternalhit - ], [NAME], [ + ], [NAME, [TYPE, MEDIAPLAYER]], [ /(gstreamer) souphttpsrc.+libsoup\/([\w\.-]+)/i // Gstreamer - ], [NAME, VERSION], [ + ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [ /(htc streaming player)\s[\w_]+\s\/\s([\d\.]+)/i, // HTC Streaming Player /(java|python-urllib|python-requests|wget|libcurl)\/([\w\.-_]+)/i, // Java/urllib/requests/wget/cURL /(lavf)([\d\.]+)/i // Lavf (FFMPEG) - ], [NAME, VERSION], [ + ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [ /(htc_one_s)\/([\d\.]+)/i, // HTC One S - ], [[NAME, /_/g, ' '], VERSION], [ + ], [[NAME, /_/g, ' '], VERSION, [TYPE, MEDIAPLAYER]], [ /(mplayer)(?:\s|\/)(?:(?:sherpya-){0,1}svn)(?:-|\s)(r\d+(?:-\d+[\w\.-]+))/i, // MPlayer SVN - ], [NAME, VERSION], [ + ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [ /(mplayer)(?:\s|\/)([\w\.-]+)/i, // MPlayer /(mplayer) unknown-([\w\.\-]+)/i // MPlayer UNKNOWN - ], [NAME, VERSION], [ + ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [ /(mplayer)/i, // MPlayer (no other info) /(yourmuze)/i, // YourMuze /(media player classic|nero showtime)/i // Media Player Classic/Nero ShowTime - ], [NAME], [ + ], [NAME, [TYPE, MEDIAPLAYER]], [ /(nero (?:home|scout))\/([\w\.-]+)/i // Nero Home/Nero Scout - ], [NAME, VERSION], [ + ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [ /(nokia\d+)\/([\w\.-]+)/i // Nokia - ], [NAME, VERSION], [ + ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [ /\s(songbird)\/([\w\.-]+)/i // Songbird/Philips-Songbird - ], [NAME, VERSION], [ + ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [ /(winamp)3 version ([\w\.-]+)/i, // Winamp /(winamp)\s([\w\.-]+)/i, /(winamp)mpeg\/([\w\.-]+)/i - ], [NAME, VERSION], [ + ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [ /(ocms-bot|tapinradio|tunein radio|unknown|winamp|inlight radio)/i // OCMS-bot/tap in radio/tunein/unknown/winamp (no other info) // inlight radio - ], [NAME], [ + ], [NAME, [TYPE, MEDIAPLAYER]], [ /(quicktime|rma|radioapp|radioclientapplication|soundtap|totem|stagefright|streamium)\/([\w\.-]+)/i // QuickTime/RealMedia/RadioApp/RadioClientApplication/ // SoundTap/Totem/Stagefright/Streamium - ], [NAME, VERSION], [ + ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [ /(smp)([\d\.]+)/i // SMP - ], [NAME, VERSION], [ + ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [ /(vlc) media player - version ([\w\.]+)/i, // VLC Videolan /(vlc)\/([\w\.-]+)/i, /(xbmc|gvfs|xine|xmms|irapp)\/([\w\.-]+)/i, // XBMC/gvfs/Xine/XMMS/irapp /(foobar2000)\/([\d\.]+)/i, // Foobar2000 /(itunes)\/([\d\.]+)/i // iTunes - ], [NAME, VERSION], [ + ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [ /(wmplayer)\/([\w\.-]+)/i, // Windows Media Player /(windows-media-player)\/([\w\.-]+)/i - ], [[NAME, /-/g, ' '], VERSION], [ + ], [[NAME, /-/g, ' '], VERSION, [TYPE, MEDIAPLAYER]], [ /windows\/([\w\.-]+) upnp\/[\d\.]+ dlnadoc\/[\d\.]+ (home media server)/i, // Windows Media Server - ], [VERSION, [NAME, 'Windows']], [ + ], [VERSION, [NAME, 'Windows'], [TYPE, MEDIAPLAYER]], [ /(com\.riseupradioalarm)\/([\d\.]*)/i // RiseUP Radio Alarm - ], [NAME, VERSION], [ + ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [ /(rad.io)\s([\d\.]+)/i, // Rad.io /(radio.(?:de|at|fr))\s([\d\.]+)/i - ], [[NAME, 'rad.io'], VERSION] + ], [[NAME, 'rad.io'], VERSION, [TYPE, MEDIAPLAYER]] ] }); diff --git a/src/main/ua-parser.d.ts b/src/main/ua-parser.d.ts index 2fa75c759..b83783180 100644 --- a/src/main/ua-parser.d.ts +++ b/src/main/ua-parser.d.ts @@ -15,7 +15,7 @@ declare namespace UAParser { name?: string; version?: string; major?: string; - type?: 'crawler' | 'cli' | 'email' | 'fetcher' | 'inapp' | 'module'; + type?: 'crawler' | 'cli' | 'email' | 'fetcher' | 'inapp' | 'mediaplayer' | 'module'; } interface ICPU extends IData { diff --git a/test/dts-test.ts b/test/dts-test.ts index d8a8fc215..e5c5065d1 100644 --- a/test/dts-test.ts +++ b/test/dts-test.ts @@ -28,7 +28,7 @@ expectType(browser); expectType(browser.name); expectType(browser.version); expectType(browser.major); -expectType<'crawler' | 'cli' | 'email' | 'fetcher' | 'inapp' | 'module' | undefined>(browser.type); +expectType<'crawler' | 'cli' | 'email' | 'fetcher' | 'inapp' | 'mediaplayer' | 'module' | undefined>(browser.type); expectType(browser.is('')); expectType(browser.toString()); expectType>(browser.withClientHints()); From 4fa991be16d093a6bf4afaffbd505f9652882690 Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Sun, 16 Jun 2024 00:10:21 +0700 Subject: [PATCH 08/64] Update README.md --- README.md | 94 ++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 82 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 116870e39..72cb670b1 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,86 @@ The most comprehensive, compact, & up-to-date isomorphic JavaScript library to d user's Browser, Engine, OS, CPU, and Device type/model. Runs either in browser (client-side) or node.js (server-side). -## License Options +# Overview + +```js +import { UAParser } from 'ua-parser-js'; + +// 1. Problem: +// Imagine getting this wild user-agent string from a visitor: +const ua = `Mozilla/5.0 (Linux; Android 10; STK-LX1 +Build/HONORSTK-LX1; wv) AppleWebKit/537.36 (KHTML, +like Gecko) Version/4.0 Chrome/110.0.5481.153 Mobile +Safari/537.36 musical_ly_2022803040 JsSdk/1.0 +NetType/WIFI Channel/huaweiadsglobal_int +AppName/musical_ly app_version/28.3.4 ByteLocale/en +ByteFullLocale/en Region/IQ Spark/1.2.7-alpha.8 +AppVersion/28.3.4 PIA/1.5.11 BytedanceWebview/d8a21c6`; +// Note: this is a real user-agent (what???) + +// 2. Solution: +// Just pass the complex user-agent string to `UAParser` +const parser = new UAParser(ua); + +// 3. Result: +// And voila! +console.log(parser.getBrowser()); +// { name : "TikTok", version : "28.3.4", major : "28", type: undefined } + +console.log(parser.getCPU()); +// { architecture : undefined } + +console.log(parser.getEngine()); +// { name : "Blink", version : "110.0.5481.153" } + +console.log(parser.getDevice()); +// { type : "mobile", vendor : "Huawei", model : "STK-LX1" } + +console.log(parser.getOS()); +// { name : "Android", version : "10" } + +console.log(parser.getResult()); +/* +{ + ua: "Mozilla/5.0 (Linux; Android 10; STK-LX1 Build/HONORSTK-LX1; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/110.0.5481.153 Mobile Safari/537.36 musical_ly_2022803040 JsSdk/1.0 NetType/WIFI Channel/huaweiadsglobal_int AppName/musical_ly app_version/28.3.4 ByteLocale/en ByteFullLocale/en Region/IQ Spark/1.2.7-alpha.8 AppVersion/28.3.4 PIA/1.5.11 BytedanceWebview/d8a21c6", + browser: { + name: "TikTok", + version: "28.3.4", + major: "28" + }, + cpu: {}, + device: { + type: "mobile", + model: "STK-LX1", + vendor: "Huawei" + }, + engine: { + name: "Blink", + version: "110.0.5481.153" + }, + os: { + name: "Android", + version: "10" + } +} +*/ + +// 4. Conclusion: +// The visitor is browsing from a TikTok app using an Android-powered Huawei device +// Phew! Thanks, UAParser.js! +``` + + * Live demo: https://uaparser.js.org/ + +# Documentation + + * v1.0: https://github.com/faisalman/ua-parser-js/tree/1.0.38#documentation + * v2.0: https://docs.uaparser.js.org/v2 + +Before upgrading from `v0.7` / `v1.0`, please read [CHANGELOG](CHANGELOG.md) to +see what's new & breaking. + +# License Options @@ -32,8 +111,8 @@ user's Browser, Engine, OS, CPU, and Device type/model. Runs either in browser - - + + @@ -192,15 +271,6 @@ user's Browser, Engine, OS, CPU, and Device type/model. Runs either in browser
License optionsMITAGPLMIT (v1.x)AGPL (v2.x) PRO Personal PRO Business PRO Enterprise
-## Version 2.0 -Before upgrading from `v0.7` / `v1.0`, please read [CHANGELOG](CHANGELOG.md) to -see what's new & breaking. - -# Documentation - - * v1.0: https://github.com/faisalman/ua-parser-js/tree/1.0.35#documentation - * v2.0: https://docs.uaparser.js.org/v2 - # Development ## Contributors From f24e4acae2d4639770e78ee91d966edb91ae0603 Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Sun, 16 Jun 2024 14:02:30 +0700 Subject: [PATCH 09/64] Update playwright test --- package.json | 2 +- script/{build-module.js => build-esm.js} | 2 +- test/playwright-test-main.spec.mjs | 152 +++++++++++++++-------- 3 files changed, 102 insertions(+), 54 deletions(-) rename script/{build-module.js => build-esm.js} (94%) diff --git a/package.json b/package.json index 35fb6d143..704d4dfed 100755 --- a/package.json +++ b/package.json @@ -199,7 +199,7 @@ ], "bin": "./script/cli.js", "scripts": { - "build": "./script/build-dist.sh && ./script/build-module.js", + "build": "./script/build-dist.sh && ./script/build-esm.js", "build+test": "npm run build && npm run test", "fuzz": "jazzer ./test/jazzer-fuzz-test.js --sync", "test": "./script/test-all.sh", diff --git a/script/build-module.js b/script/build-esm.js similarity index 94% rename from script/build-module.js rename to script/build-esm.js index 98fb8dbb2..cd7523878 100755 --- a/script/build-module.js +++ b/script/build-esm.js @@ -7,7 +7,7 @@ const generateMJS = (module) => { let text = fs.readFileSync(src, 'utf-8'); replacements.push( - [/const (.+?)\s*=\s*require\((.+)\)/ig, 'import $1 from $2'], + [/const (.+?)\s*=\s*require\(\'(.+)\'\)/ig, 'import $1 from \'$2.mjs\''], [/module\.exports =/ig, 'export'] ); replacements.forEach(rep => { diff --git a/test/playwright-test-main.spec.mjs b/test/playwright-test-main.spec.mjs index e830bbfeb..fe4ac7cbd 100644 --- a/test/playwright-test-main.spec.mjs +++ b/test/playwright-test-main.spec.mjs @@ -4,75 +4,123 @@ import url from 'url'; const localHtml = `file://${path.resolve(path.dirname(url.fileURLToPath(import.meta.url)), '../')}/dist/ua-parser.html`; -test.describe('test input', () => { +test.describe('Custom navigator.userAgent tests', () => { + + test('Undefined navigator.userAgent regarded as an empty user-agent string', async ({ page }) => { + await page.addInitScript(() => { + Object.defineProperty(navigator, 'userAgent', { + value: undefined + }); + }); + await page.goto(localHtml); + // @ts-ignore + const uap = await page.evaluate(async () => await UAParser()); + expect(uap).toHaveProperty('ua', ''); + expect(uap).toHaveProperty('browser.name', undefined); + }); +}); + +test.describe('User-defined user-agent tests', () => { + test.beforeEach(async ({ page }) => { await page.goto(localHtml); }); - test('accept empty string', async ({ page }) => { + test('Accept empty user-agent', async ({ page }) => { // @ts-ignore const uap = await page.evaluate(async () => await UAParser('')); expect(uap).toHaveProperty('ua', ''); }); + + test('Truncate very long user-agent', async ({ page }) => { + // @ts-ignore + const uap = await page.evaluate(async () => await UAParser('Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; (R1 1.6); SLCC1; .NET CLR 2.0.50727; InfoPath.2; OfficeLiveConnector.1.3; OfficeLivePatch.0.0; .NET CLR 3.5.30729; .NET CLR 3.0.30618; 66760635803; runtime 11.00294; 876906799603; 97880703; 669602703; 9778063903; 877905603; 89670803; 96690803; 8878091903; 7879040603; 999608065603; 799808803; 6666059903; 669602102803; 888809342903; 696901603; 788907703; 887806555703; 97690214703; 66760903; 968909903; 796802422703; 8868026703; 889803611803; 898706903; 977806408603; 976900799903; 9897086903; 88780803; 798802301603; 9966008603; 66760703; 97890452603; 9789064803; 96990759803; 99960107703; 8868087903; 889801155603; 78890703; 8898070603; 89970603; 89970539603; 89970488703; 8789007603; 87890903; 877904603; 9887077703; 798804903; 97890264603; 967901703; 87890703; 97690420803; 79980706603; 9867086703; 996602846703; 87690803; 6989010903; 977809603; 666601903; 876905337803; 89670603; 89970200903; 786903603; 696901911703; 788905703; 896709803; 96890703; 998601903; 88980703; 666604769703; 978806603; 7988020803; 996608803; 788903297903; 98770043603; 899708803; 66960371603; 9669088903; 69990703; 99660519903; 97780603; 888801803; 9867071703; 79780803; 9779087603; 899708603; 66960456803; 898706824603; 78890299903; 99660703; 9768079803; 977901591603; 89670605603; 787903608603; 998607934903; 799808573903; 878909603; 979808146703; 9996088603; 797803154903; 69790603; 99660565603; 7869028603; 896707703; 97980965603; 976907191703; 88680703; 888809803; 69690903; 889805523703; 899707703; 997605035603; 89970029803; 9699094903; 877906803; 899707002703; 786905857603; 69890803; 97980051903; 997603978803; 9897097903; 66960141703; 7968077603; 977804603; 88980603; 989700803; 999607887803; 78690772803; 96990560903; 98970961603; 9996032903; 9699098703; 69890655603; 978903803; 698905066803; 977806903; 9789061703; 967903747703; 976900550903; 88980934703; 8878075803; 8977028703; 97980903; 9769006603; 786900803; 98770682703; 78790903; 878906967903; 87690399603; 99860976703; 796805703; 87990603; 968906803; 967904724603; 999606603; 988705903; 989702842603; 96790603; 99760703; 88980166703; 9799038903; 98670903; 697905248603; 7968043603; 66860703; 66860127903; 9779048903; 89670123903; 78890397703; 97890603; 87890803; 8789030603; 69990603; 88880763703; 9769000603; 96990203903; 978900405903; 7869022803; 699905422903; 97890703; 87990903; 878908703; 7998093903; 898702507603; 97780637603; 966907903; 896702603; 9769004803; 7869007903; 99660158803; 7899099603; 8977055803; 99660603; 7889080903; 66660981603; 997604603; 6969089803; 899701903; 9769072703; 666603903; 99860803; 997608803; 69790903; 88680756703; 979805677903; 9986047703; 89970803; 66660603; 96690903; 8997051603; 789901209803; 8977098903; 968900326803; 87790703; 98770024803; 697901794603; 69990803; 887805925803; 968908903; 97880603; 897709148703; 877909476903; 66760197703; 977908603; 698902703; 988706504803; 977802026603; 88680964703; 8878068703; 987705107903; 978902878703; 8898069803; 9768031703; 79680803; 79980803; 669609328703; 89870238703; 99960593903; 969904218703; 78890603; 9788000703; 69690630903; 889800982903; 988709748803; 7968052803; 99960007803; 969900800803; 668604817603; 66960903; 78790734603; 8868007703; 79780034903; 8878085903; 976907603; 89670830803; 877900903; 969904889703; 7978033903; 8987043903; 99860703; 979805903; 667603803; 976805348603; 999604127603; 97790701603; 78990342903; 98770672903; 87990253903; 9877027703; 97790803; 877901895603; 8789076903; 896708595603; 997601903; 799806903; 97690603; 87790371703; 667605603; 99760303703; 97680283803; 788902750803; 787909803; 79780603; 79880866903; 9986050903; 87890543903; 979800803; 97690179703; 876901603; 699909903; 96990192603; 878904903; 877904734903; 796801446903; 977904803; 9887044803; 797805565603; 98870789703; 7869093903; 87790727703; 797801232803; 666604803; 9778071903; 9799086703; 6969000903; 89670903; 8799075903; 897708903; 88680903; 97980362603; 97980503903; 889803256703; 88980388703; 789909376803; 69690703; 6969025903; 89970309903; 96690703; 877901847803; 968901903; 96690603; 88680607603; 7889001703; 789904761803; 976807703; 976902903; 878907889703; 9897014903; 896707046603; 696909903; 666603998903; 969902703; 79680421803; 9769075603; 798800192703; 97990903; 9689024903; 668604803; 969908671903; 9996094703; 69990642703; 97890895903; 977805619903; 79980859903; 88980443803; 98970649603; 997602703; 888802169903; 699907803; 667602028803; 786903283903; 997607703; 969909803; 798809925903; 9976045603; 97790903; 9789001903; 966903603; 9789069603; 968906603; 6989091803; 896701603; 6979059803; 978803903; 997606362603; 88980803; 98970803; 88880921703; 8997065703; 899700703; 698908703; 797801027903; 7889050903; 87890603; 78690703; 99660069703; 97980309903; 976800603; 666606803; 898707703; 79880019803; 66960250803; 7978049803; 88780602603; 79680903; 88880792703; 96990903; 667608603; 87790730903; 98970903; 9699032903; 8987004803; 88880703; 89770046603; 978800803; 969908903; 9798022603; 696901903; 799803703; 989703703; 668605903; 79780903; 998601371703; 796803339703; 87890922603; 898708903; 9966061903; 66960891903; 96790903; 8779050803; 98870858803; 976909298603; 9887029903; 669608703; 979806903; 878903803; 99960703; 9789086703; 979801803; 66960008703; 979806830803; 99760212703; 786906603; 797807603; 789907297703; 96990703; 786901603; 796807766603; 896702651603; 789902585603; 66660925903; 9986085703; 66960302703; 69890703; 789900703; 89970903; 9679060703; 9789002903; 979908821603; 986708140803; 976809828703; 7988082803; 79680997903; 99960803; 9788081903; 979805703; 787908603; 66960602803; 9887098703; 978803237703; 888806804603; 999604703; 977904703; 966904635703; 97680291703; 977809345603; 8878046703; 988709803; 976900773603; 989703903; 88780198603; 87790603; 986708703; 78890604703; 87790544803; 976809850903; 887806703; 987707527603; 79880803; 9897059603; 897709820603; 97880804803; 66960026703; 9789062803; 9867090803; 669600603; 8967087703; 78890903; 89770903; 97980703; 976802687603; 66860400803; 979901288603; 96990160903; 99860228903; 966900703; 66760603; 9689035703; 9779064703; 7968023603; 87890791903; 98770870603; 9798005803; 6969087903; 9779097903; 6979065703; 699903252603; 79780989703; 87690901803; 978905763903; 977809703; 97790369703; 899703269603; 8878012703; 78790803; 87690395603; 8888042803; 667607689903; 8977041803; 6666085603; 6999080703; 69990797803; 88680721603; 99660519803; 889807603; 87890146703; 699906325903; 89770603; 669608615903; 9779028803; 88880603; 97790703; 79780703; 97680355603; 6696024803; 78790784703; 97880329903; 9699077703; 89870803; 79680227903; 976905852703; 8997098903; 896704796703; 66860598803; 9897036703; 66960703; 9699094703; 9699008703; 97780485903; 999603179903; 89770834803; 96790445603; 79680460903; 9867009603; 89870328703; 799801035803; 989702903; 66960758903; 66860150803; 6686088603; 9877092803; 96990603; 99860603; 987703663603; 98870903; 699903325603; 87790803; 97680703; 8868030703; 9799030803; 89870703; 97680803; 9669054803; 6979097603; 987708046603; 999608603; 878904803; 998607408903; 968903903; 696900703; 977907491703; 6686033803; 669601803; 99960290603; 887809169903; 979803703; 69890903; 699901447903; 8987064903; 799800603; 98770903; 8997068703; 967903603; 66760146803; 978805087903; 697908138603; 799801603; 88780964903; 989708339903; 8967048603; 88880981603; 789909703; 796806603; 977905977603; 989700603; 97780703; 9669062603; 88980714603; 897709545903; 988701916703; 667604694903; 786905664603; 877900803; 886805490903; 89970559903; 99960531803; 7998033903; 98770803; 78890418703; 669600872803; 996605216603; 78690962703; 667604903; 996600903; 999608903; 9699083803; 787901803; 97780707603; 787905312703; 977805803; 8977033703; 97890708703; 989705521903; 978800703; 698905703; 78890376903; 878907703; 999602903; 986705903; 668602719603; 979901803; 997606903; 66760393903; 987703603; 78790338903; 96890803; 97680596803; 666601603; 977902178803; 877902803; 78790038603; 8868075703; 99960060603)')); + + expect(uap).toHaveProperty('ua', 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; (R1 1.6); SLCC1; .NET CLR 2.0.50727; InfoPath.2; OfficeLiveConnector.1.3; OfficeLivePatch.0.0; .NET CLR 3.5.30729; .NET CLR 3.0.30618; 66760635803; runtime 11.00294; 876906799603; 97880703; 669602703; 9778063903; 877905603; 89670803; 96690803; 8878091903; 7879040603; 999608065603; 799808803; 6666059903; 669602102803; 888809342903; 696901603; 788907703; 887806555703; 97690214703; 66760903; 968909903; 796802422703; 8868026703; 8898036'); + }); }); -test('read client hints data', async ({ page }) => { - await page.addInitScript(() => { - Object.defineProperty(navigator, 'userAgentData', { - value: { - brands: [], - platform: '', - mobile: false, - getHighEntropyValues: () => { - return Promise.resolve({ - brands: [ - { - brand: 'Chromium', - version: '110' - }, - { - brand: 'Not(A:Brand', - version: '110' - }, - { - brand: 'New Browser', - version: '110' - } - ], - platform: 'New OS', - formFactors: 'New Form Factor' - }); +test.describe('withClientHints() tests', () => { + + test('Detect custom Client Hints data', async ({ page }) => { + await page.addInitScript(() => { + Object.defineProperty(navigator, 'userAgentData', { + value: { + brands: [], + platform: '', + mobile: false, + getHighEntropyValues: () => { + return Promise.resolve({ + brands: [ + { + brand: 'Chromium', + version: '110' + }, + { + brand: 'Not(A:Brand', + version: '110' + }, + { + brand: 'New Browser', + version: '110' + } + ], + platform: 'New OS', + formFactors: 'New Form Factor' + }); + } } - } + }); }); + await page.goto(localHtml); + // @ts-ignore + const uap = await page.evaluate(async () => await UAParser().withClientHints()); + expect(uap).toHaveProperty('browser.name', 'New Browser'); + expect(uap).toHaveProperty('os.name', 'New OS'); + expect(uap).toHaveProperty('device.type', undefined); }); - - await page.goto(localHtml); - - // @ts-ignore - const uap = await page.evaluate(async () => await UAParser().withClientHints()); - - 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 }) => { - await page.addInitScript(() => { - Object.defineProperty(navigator, 'brave', { - value: { - isBrave: () => true - } +test.describe('withFeatureCheck() tests', () => { + + test('Detect Brave', async ({ page }) => { + await page.addInitScript(() => { + Object.defineProperty(navigator, 'brave', { + value: { + isBrave: () => true + } + }); }); + await page.goto(localHtml); + // @ts-ignore + let uap = await page.evaluate(() => UAParser()); + expect(uap).toHaveProperty('browser.name', 'Chrome Headless'); + // @ts-ignore + uap = await page.evaluate(() => UAParser().withFeatureCheck()); + expect(uap).toHaveProperty('browser.name', 'Brave'); }); - await page.goto(localHtml); - - // @ts-ignore - let uap = await page.evaluate(() => UAParser()); - expect(uap).toHaveProperty('browser.name', 'Chrome Headless'); - // @ts-ignore - uap = await page.evaluate(() => UAParser().withFeatureCheck()); - expect(uap).toHaveProperty('browser.name', 'Brave'); + test('Detect iPad', async ({ page }) => { + await page.addInitScript(() => { + Object.defineProperty(navigator, 'userAgent', { + value: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Safari/605.1.15' + }); + Object.defineProperty(navigator, 'standalone', { + value: true + }); + Object.defineProperty(navigator, 'maxTouchPoints', { + value: 3 + }); + }); + await page.goto(localHtml); + // @ts-ignore + let uap = await page.evaluate(() => UAParser()); + expect(uap).toHaveProperty('device.model', 'Macintosh'); + expect(uap).toHaveProperty('device.type', undefined); + // @ts-ignore + uap = await page.evaluate(() => UAParser().withFeatureCheck()); + expect(uap).toHaveProperty('device.model', 'iPad'); + expect(uap).toHaveProperty('device.type', 'tablet'); + }); }); \ No newline at end of file From 4e64cb644fb578a9cd210240fece0d95b9488cfb Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Sun, 16 Jun 2024 23:11:59 +0700 Subject: [PATCH 10/64] Migrate to uaparser.dev --- .github/ISSUE_TEMPLATE/bug_report.md | 2 +- README.md | 6 +++--- package.json | 4 ++-- src/main/ua-parser.js | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 2ba42577c..8fadfd144 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -10,7 +10,7 @@ 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 +For the issue related with detection result, you can use the demo section in https://uaparser.dev to confirm **Describe the bug** A clear and concise description of what the bug is. diff --git a/README.md b/README.md index 72cb670b1..57e0473bf 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

- +

@@ -88,12 +88,12 @@ console.log(parser.getResult()); // Phew! Thanks, UAParser.js! ``` - * Live demo: https://uaparser.js.org/ + * Live demo: https://uaparser.dev # Documentation * v1.0: https://github.com/faisalman/ua-parser-js/tree/1.0.38#documentation - * v2.0: https://docs.uaparser.js.org/v2 + * v2.0: https://docs.uaparser.dev Before upgrading from `v0.7` / `v1.0`, please read [CHANGELOG](CHANGELOG.md) to see what's new & breaking. diff --git a/package.json b/package.json index 704d4dfed..618a794d8 100755 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "os-detection", "bot-detection" ], - "homepage": "https://github.com/faisalman/ua-parser-js", + "homepage": "https://uaparser.dev", "contributors": [ "Aamir Poonawalla ", "Admas ", @@ -237,7 +237,7 @@ "test": "test" }, "bugs": "https://github.com/faisalman/ua-parser-js/issues", - "demo": "https://uaparser.js.org", + "demo": "https://uaparser.dev", "download": "https://raw.github.com/faisalman/ua-parser-js/master/dist/ua-parser.pack.js", "funding": [ { diff --git a/src/main/ua-parser.js b/src/main/ua-parser.js index c80286666..c7034f6e5 100755 --- a/src/main/ua-parser.js +++ b/src/main/ua-parser.js @@ -4,7 +4,7 @@ AGPLv3 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 */ ///////////////////////////////////////////////////////////////////////////////// From 81cbbe504e895ef5bcb6ffda96a7fa7ecff5b730 Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Sun, 16 Jun 2024 23:30:27 +0700 Subject: [PATCH 11/64] Remove package.js & move pull_request_template inside /.github --- .../PULL_REQUEST_TEMPLATE.md | 0 package.js | 12 ------------ 2 files changed, 12 deletions(-) rename PULL_REQUEST_TEMPLATE.md => .github/PULL_REQUEST_TEMPLATE.md (100%) delete mode 100644 package.js diff --git a/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md similarity index 100% rename from PULL_REQUEST_TEMPLATE.md rename to .github/PULL_REQUEST_TEMPLATE.md diff --git a/package.js b/package.js deleted file mode 100644 index 0ff949d95..000000000 --- a/package.js +++ /dev/null @@ -1,12 +0,0 @@ -Package.describe({ - name: 'faisalman:ua-parser-js', - 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' -}); - -Package.onUse(function (api) { - api.addFiles("src/ua-parser.js"); - api.export("UAParser"); -}); From a74ace8dd1c8a50b5c6163bba7a9e8973dd27d0a Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Sat, 22 Jun 2024 00:13:13 +0700 Subject: [PATCH 12/64] Add Yahoo! Japan to Crawler, Fetcher, & InApp browser --- src/extensions/ua-parser-extensions.js | 100 ++++++++++++------------- src/helpers/ua-parser-helpers.mjs | 2 +- test/specs/browser-crawlers.json | 10 +++ 3 files changed, 61 insertions(+), 51 deletions(-) diff --git a/src/extensions/ua-parser-extensions.js b/src/extensions/ua-parser-extensions.js index 84d391f10..bd0ee4056 100644 --- a/src/extensions/ua-parser-extensions.js +++ b/src/extensions/ua-parser-extensions.js @@ -39,43 +39,40 @@ const CLIs = Object.freeze({ 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]], + [ + // 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, - // Baiduspider https://help.baidu.com/question?prod_id=99&class=0&id=3001 - [/(baiduspider)[-imagevdonsfcpr]{0,6}\/([\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, - // Bytespider - // Yahoo! Slurp - http://help.yahoo.com/help/us/ysearch/slurp - [/((?:bytespider|(?=yahoo! )slurp))/i], - [NAME, [TYPE, CRAWLER]], + // ClaudeBot + /(claude(?:bot|-web))\/([\w\.]+)/i, - // 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, + + // Sogou Spider + /(sogou (?:pic|head|web|orion|news) spider)\/([\w\.]+)/i, + + // Yahoo! Japan - https://support.yahoo-net.jp/PccSearch/s/article/H000007955 + /(y!?j-(?:asr|br[uw]|dscv|mmp|vsidx|wsc))\/([\w\.]+)/i, + + // 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 + ], - // 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]] + // Bytespider + // Yahoo! Slurp - http://help.yahoo.com/help/us/ysearch/slurp + [/((?:bytespider|(?=yahoo! )slurp))/i], + [NAME, [TYPE, CRAWLER]] ] }); @@ -176,30 +173,29 @@ const Emails = Object.freeze({ const Fetchers = Object.freeze({ browser : [ - // ChatGPT-User - https://platform.openai.com/docs/plugins/bot - // BingPreview / Mastodon / Pinterestbot / Redditbot / Telegrambot / Twitterbot - [/(bingpreview|chatgpt-user|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]], + [ + // ChatGPT-User - https://platform.openai.com/docs/plugins/bot + // BingPreview / Mastodon / Pinterestbot / Redditbot / Telegrambot / Twitterbot + /(bingpreview|chatgpt-user|mastodon|(?:discord|linkedin|pinterest|reddit|telegram|twitter)bot)\/([\w\.]+)/i, + // Slackbot - https://api.slack.com/robots + /(slack(?:bot)?(?:-imgproxy|-linkexpanding)?) ([\w\.]+)/i, + + // WhatsApp + /(whatsapp)\/([\w\.]+)[\/ ][ianw]/i, - // Slackbot - https://api.slack.com/robots - [/(slack(?:bot)?(?:-imgproxy|-linkexpanding)?) ([\w\.]+)/i], - [NAME, VERSION, [TYPE, FETCHER]], + // Yahoo! Japan + /(y!?j-dlc)\/([\w\.]+)/i, - // WhatsApp - [/(whatsapp)\/([\w\.]+)[\/ ][ianw]/i], - [NAME, VERSION, [TYPE, FETCHER]], - - // Yandex Bots - https://yandex.com/bots - [ + // Yandex Bots - https://yandex.com/bots /(yandex(?:calendar|direct(?:dyn)?|searchshop)|yadirectfetcher)\/([\w\.]+)/i, /(yandex(?:sitelinks|userproxy))/i ], - [NAME, VERSION, [TYPE, FETCHER]] + [NAME, VERSION, [TYPE, FETCHER]], + + // Google Bots / Snapchat + [/(feedfetcher-google|google-read-aloud|(?=bot; )snapchat)/i], + [NAME, [TYPE, FETCHER]], ] }); @@ -209,7 +205,11 @@ const Fetchers = Object.freeze({ const InApps = Object.freeze({ browser : [ - [/chatlyio\/([\d\.]+)/i], [VERSION, 'Slack', [TYPE, INAPP]] + // Slack + [/chatlyio\/([\d\.]+)/i], [VERSION, 'Slack', [TYPE, INAPP]], + + // Yahoo! Japan + [/jp\.co\.yahoo\.android\.yjtop\/([\d\.]+)/i], [VERSION, 'Yahoo! Japan', [TYPE, INAPP]] ] }); diff --git a/src/helpers/ua-parser-helpers.mjs b/src/helpers/ua-parser-helpers.mjs index cc3533d2b..95d6c0f17 100644 --- a/src/helpers/ua-parser-helpers.mjs +++ b/src/helpers/ua-parser-helpers.mjs @@ -11,7 +11,7 @@ /*jshint esversion: 6 */ -import { CPU, OS, Engine } from '../enums/ua-parser-enums'; +import { CPU, OS, Engine } from '../enums/ua-parser-enums.mjs'; const isAppleSilicon = (res) => res.os.is(OS.MACOS) && res.cpu.is(CPU.ARM); diff --git a/test/specs/browser-crawlers.json b/test/specs/browser-crawlers.json index b72beb287..107ab24b4 100644 --- a/test/specs/browser-crawlers.json +++ b/test/specs/browser-crawlers.json @@ -79,6 +79,16 @@ "type" : "crawler" } }, + { + "desc" : "Yahoo! Japan", + "ua" : "Y!J-BRW/1.0 (https://www.yahoo-help.jp/app/answers/detail/p/595/a_id/42716)", + "expect" : + { + "name" : "Y!J-BRW", + "version" : "1.0", + "type" : "crawler" + } + }, { "desc" : "YandexBot", "ua" : "Mozilla/5.0 (compatible; YandexBot/3.0; +http://yandex.com/bots)", From 50c15ad5a8f713a3a7215ee3bcc3df75b32642ae Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Sat, 22 Jun 2024 21:15:26 +0700 Subject: [PATCH 13/64] Add new helper method `isPWA()` to check for standalone mode. Also fix #728 --- src/helpers/ua-parser-helpers.d.ts | 4 +++- src/helpers/ua-parser-helpers.js | 13 ++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/helpers/ua-parser-helpers.d.ts b/src/helpers/ua-parser-helpers.d.ts index 89f64f0cf..f467c310e 100644 --- a/src/helpers/ua-parser-helpers.d.ts +++ b/src/helpers/ua-parser-helpers.d.ts @@ -7,9 +7,11 @@ import { IResult } from "../main/ua-parser"; declare function isAppleSilicon(res: IResult): boolean; declare function isChromiumBased(res: IResult): boolean; declare function isFrozenUA(ua: string): boolean; +declare function isPWA(): boolean; export { isAppleSilicon, isChromiumBased, - isFrozenUA + isFrozenUA, + isPWA } \ No newline at end of file diff --git a/src/helpers/ua-parser-helpers.js b/src/helpers/ua-parser-helpers.js index 4cbf30eb8..a862ec539 100644 --- a/src/helpers/ua-parser-helpers.js +++ b/src/helpers/ua-parser-helpers.js @@ -15,8 +15,19 @@ const isChromiumBased = (res) => res.engine.is(Engine.BLINK); 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); +const isPWA = () => window && (window.matchMedia('(display-mode: standalone)').matches || + // iOS + navigator.standalone || + // Android + document.referrer.startsWith('android-app://') || + // Windows + window.Windows || + /trident.+(msapphost|webview)\//i.test(navigator.userAgent) || + document.referrer.startsWith('app-info://platform/microsoft-store')); + module.exports = { isAppleSilicon, isChromiumBased, - isFrozenUA + isFrozenUA, + isPWA } \ No newline at end of file From 21162f127745bef088d4ecb7fd93e27bc43a6dfb Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Sat, 22 Jun 2024 22:26:58 +0700 Subject: [PATCH 14/64] BREAKING CHANGE - Rename `isChromiumBased` -> `isChromeFamily` & `isPWA` -> `isStandalonePWA` --- src/helpers/ua-parser-helpers.d.ts | 8 ++++---- src/helpers/ua-parser-helpers.js | 8 ++++---- test/dts-test.ts | 4 ++-- test/mocha-test-helpers.js | 8 ++++---- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/helpers/ua-parser-helpers.d.ts b/src/helpers/ua-parser-helpers.d.ts index f467c310e..905e5edad 100644 --- a/src/helpers/ua-parser-helpers.d.ts +++ b/src/helpers/ua-parser-helpers.d.ts @@ -5,13 +5,13 @@ import { IResult } from "../main/ua-parser"; declare function isAppleSilicon(res: IResult): boolean; -declare function isChromiumBased(res: IResult): boolean; +declare function isChromeFamily(res: IResult): boolean; declare function isFrozenUA(ua: string): boolean; -declare function isPWA(): boolean; +declare function isStandalonePWA(): boolean; export { isAppleSilicon, - isChromiumBased, + isChromeFamily, isFrozenUA, - isPWA + isStandalonePWA } \ No newline at end of file diff --git a/src/helpers/ua-parser-helpers.js b/src/helpers/ua-parser-helpers.js index a862ec539..74923e168 100644 --- a/src/helpers/ua-parser-helpers.js +++ b/src/helpers/ua-parser-helpers.js @@ -11,11 +11,11 @@ const { CPU, OS, Engine } = require('../enums/ua-parser-enums'); const isAppleSilicon = (res) => res.os.is(OS.MACOS) && res.cpu.is(CPU.ARM); -const isChromiumBased = (res) => res.engine.is(Engine.BLINK); +const isChromeFamily = (res) => res.engine.is(Engine.BLINK); 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); -const isPWA = () => window && (window.matchMedia('(display-mode: standalone)').matches || +const isStandalonePWA = () => window && (window.matchMedia('(display-mode: standalone)').matches || // iOS navigator.standalone || // Android @@ -27,7 +27,7 @@ const isPWA = () => window && (window.matchMedia('(display-mode: standalone)').m module.exports = { isAppleSilicon, - isChromiumBased, + isChromeFamily, isFrozenUA, - isPWA + isStandalonePWA } \ No newline at end of file diff --git a/test/dts-test.ts b/test/dts-test.ts index e5c5065d1..edf1d47d6 100644 --- a/test/dts-test.ts +++ b/test/dts-test.ts @@ -1,6 +1,6 @@ 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"; +import { isAppleSilicon, isChromeFamily } 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 = { @@ -46,4 +46,4 @@ expectType(parser.setUA(uastring)); const result = parser.getResult(); expectType(isAppleSilicon(result)); -expectType(isChromiumBased(result)); \ No newline at end of file +expectType(isChromeFamily(result)); \ No newline at end of file diff --git a/test/mocha-test-helpers.js b/test/mocha-test-helpers.js index faacf617c..1cfffea72 100644 --- a/test/mocha-test-helpers.js +++ b/test/mocha-test-helpers.js @@ -1,6 +1,6 @@ const assert = require('assert'); const { UAParser } = require('../src/main/ua-parser'); -const { isAppleSilicon, isChromiumBased } = require('../src/helpers/ua-parser-helpers'); +const { isAppleSilicon, isChromeFamily } = require('../src/helpers/ua-parser-helpers'); describe('isAppleSilicon', () => { it('Can detect Apple Silicon device', () => { @@ -14,13 +14,13 @@ describe('isAppleSilicon', () => { }); }); -describe('isChromiumBased', () => { +describe('isChromeFamily', () => { 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'; - assert.equal(isChromiumBased(UAParser(edge)), true); - assert.equal(isChromiumBased(UAParser(firefox)), false); + assert.equal(isChromeFamily(UAParser(edge)), true); + assert.equal(isChromeFamily(UAParser(firefox)), false); }); }); \ No newline at end of file From 654285cf9c75367a3d5945959f09d8893e363671 Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Sun, 23 Jun 2024 11:59:54 +0700 Subject: [PATCH 15/64] Add new browser: Helio --- src/enums/ua-parser-enums.js | 2 +- src/main/ua-parser.js | 4 ++-- test/specs/browser-all.json | 10 ++++++++++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/enums/ua-parser-enums.js b/src/enums/ua-parser-enums.js index 9d93f23b0..8fbee9b00 100644 --- a/src/enums/ua-parser-enums.js +++ b/src/enums/ua-parser-enums.js @@ -52,6 +52,7 @@ const Browser = Object.freeze({ FLOW: 'Flow', GO: 'GoBrowser', GOOGLE_SEARCH: 'GSA', + HELIO: 'Helio', HEYTAP: 'HeyTap', HUAWEI: 'Huawei Browser', ICAB: 'iCab', @@ -343,7 +344,6 @@ const OS = Object.freeze({ UBUNTU: 'Ubuntu', UNIX: 'Unix', VECTORLINUX: 'VectorLinux', - VIERA: 'Viera', WATCHOS: 'watchOS', WEBOS: 'WebOS', WINDOWS: 'Windows', diff --git a/src/main/ua-parser.js b/src/main/ua-parser.js index c7034f6e5..1ca736304 100755 --- a/src/main/ua-parser.js +++ b/src/main/ua-parser.js @@ -327,8 +327,8 @@ /(?: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|duckduckgo|klar)\/([-\w\.]+)/i, - // Rekonq/Puffin/Brave/Whale/QQBrowserLite/QQ//Vivaldi/DuckDuckGo/Klar + /(flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi|iridium|phantomjs|bowser|quark|qupzilla|falkon|rekonq|puffin|brave|whale(?!.+naver)|qqbrowserlite|duckduckgo|klar|helio)\/([-\w\.]+)/i, + // Rekonq/Puffin/Brave/Whale/QQBrowserLite/QQ//Vivaldi/DuckDuckGo/Klar/Helio /(heytap|ovi)browser\/([\d\.]+)/i, // HeyTap/Ovi /(weibo)__([\d\.]+)/i // Weibo ], [NAME, VERSION], [ diff --git a/test/specs/browser-all.json b/test/specs/browser-all.json index 880ba08e6..71ae6f0a4 100644 --- a/test/specs/browser-all.json +++ b/test/specs/browser-all.json @@ -698,6 +698,16 @@ "major" : "1" } }, + { + "desc" : "Helio", + "ua" : "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.72 Safari/537.36 Helio/0.98.20", + "expect" : + { + "name" : "Helio", + "version" : "0.98.20", + "major" : "0" + } + }, { "desc" : "HeyTap", "ua" : "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.61 Safari/537.36 HeyTapBrowser/40.8.10.1", From c391d8a73c1a030c24845bc191b021bfb6cba256 Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Sat, 27 Jul 2024 10:57:11 +0700 Subject: [PATCH 16/64] Update `isAppleSilicon()` helper method to also check for WebGL renderer info #732 --- src/helpers/ua-parser-helpers.js | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/helpers/ua-parser-helpers.js b/src/helpers/ua-parser-helpers.js index 74923e168..3c7d399d5 100644 --- a/src/helpers/ua-parser-helpers.js +++ b/src/helpers/ua-parser-helpers.js @@ -9,7 +9,25 @@ const { CPU, OS, Engine } = require('../enums/ua-parser-enums'); -const isAppleSilicon = (res) => res.os.is(OS.MACOS) && res.cpu.is(CPU.ARM); +const isAppleSilicon = (res) => { + if (res.os.is(OS.MACOS)) { + if (res.cpu.is(CPU.ARM)) { + return true; + } + try { + const canvas = document.createElement('canvas'); + const webgl = canvas.getContext('webgl2') || canvas.getContext('webgl') || canvas.getContext('experimental-webgl'); + const debug = webgl.getExtension('WEBGL_debug_renderer_info'); + const renderer = webgl.getParameter(debug.UNMASKED_RENDERER_WEBGL); + if (renderer.match(/apple m\d/i)) { + return true; + } + } catch { + return false; + } + } + return false; +} const isChromeFamily = (res) => res.engine.is(Engine.BLINK); From 62fb6c29257eec5f5521ae63882f0ca2002695bb Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Sat, 27 Jul 2024 22:47:27 +0700 Subject: [PATCH 17/64] Fix #660 - Add new helper method: `getDeviceVendor()` to guess the device vendor from a model name --- src/helpers/ua-parser-helpers.d.ts | 2 ++ src/helpers/ua-parser-helpers.js | 4 ++++ test/mocha-test-helpers.js | 19 ++++++++++++++++++- 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/helpers/ua-parser-helpers.d.ts b/src/helpers/ua-parser-helpers.d.ts index 905e5edad..c58fc1463 100644 --- a/src/helpers/ua-parser-helpers.d.ts +++ b/src/helpers/ua-parser-helpers.d.ts @@ -4,12 +4,14 @@ import { IResult } from "../main/ua-parser"; +declare function getDeviceVendor(model: string): string | undefined; declare function isAppleSilicon(res: IResult): boolean; declare function isChromeFamily(res: IResult): boolean; declare function isFrozenUA(ua: string): boolean; declare function isStandalonePWA(): boolean; export { + getDeviceVendor, isAppleSilicon, isChromeFamily, isFrozenUA, diff --git a/src/helpers/ua-parser-helpers.js b/src/helpers/ua-parser-helpers.js index 3c7d399d5..e0729c94d 100644 --- a/src/helpers/ua-parser-helpers.js +++ b/src/helpers/ua-parser-helpers.js @@ -8,6 +8,9 @@ /*jshint esversion: 6 */ const { CPU, OS, Engine } = require('../enums/ua-parser-enums'); +const { UAParser } = require('../main/ua-parser'); + +const getDeviceVendor = (model) => UAParser(`Mozilla/5.0 (Linux; Android 10; ${model}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.0.0 Safari/537.36`).device.vendor; const isAppleSilicon = (res) => { if (res.os.is(OS.MACOS)) { @@ -44,6 +47,7 @@ const isStandalonePWA = () => window && (window.matchMedia('(display-mode: stand document.referrer.startsWith('app-info://platform/microsoft-store')); module.exports = { + getDeviceVendor, isAppleSilicon, isChromeFamily, isFrozenUA, diff --git a/test/mocha-test-helpers.js b/test/mocha-test-helpers.js index 1cfffea72..da9ae2c85 100644 --- a/test/mocha-test-helpers.js +++ b/test/mocha-test-helpers.js @@ -1,6 +1,23 @@ const assert = require('assert'); const { UAParser } = require('../src/main/ua-parser'); -const { isAppleSilicon, isChromeFamily } = require('../src/helpers/ua-parser-helpers'); +const { getDeviceVendor, isAppleSilicon, isChromeFamily } = require('../src/helpers/ua-parser-helpers'); + +describe('getDeviceVendor', () => { + it('Can guess the device vendor from a model name', () => { + + const modelSM = 'SM-A605G'; + const modelRedmi = 'Redmi Note 8'; + const modelNexus = 'Nexus 6P'; + const modelQuest = 'Quest 3'; + const modelAquos = 'AQUOS-TVX19B'; + + assert.equal(getDeviceVendor(modelSM), 'Samsung'); + assert.equal(getDeviceVendor(modelRedmi), 'Xiaomi'); + assert.equal(getDeviceVendor(modelNexus), 'Huawei'); + assert.equal(getDeviceVendor(modelQuest), 'Facebook'); + assert.equal(getDeviceVendor(modelAquos), 'Sharp'); + }); +}); describe('isAppleSilicon', () => { it('Can detect Apple Silicon device', () => { From 15391d2b8d5c9d2fa6b7e89d300d7521913ceff7 Mon Sep 17 00:00:00 2001 From: lj0812 Date: Wed, 31 Jul 2024 11:42:33 +0800 Subject: [PATCH 18/64] Improve browser detection for Quark (#737) Co-authored-by: lijian01 Co-authored-by: Faisal Salman --- src/main/ua-parser.js | 6 ++++-- test/specs/browser-all.json | 10 ++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/main/ua-parser.js b/src/main/ua-parser.js index 1ca736304..00f3a683d 100755 --- a/src/main/ua-parser.js +++ b/src/main/ua-parser.js @@ -327,11 +327,13 @@ /(?: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|duckduckgo|klar|helio)\/([-\w\.]+)/i, - // Rekonq/Puffin/Brave/Whale/QQBrowserLite/QQ//Vivaldi/DuckDuckGo/Klar/Helio + /(flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi|iridium|phantomjs|bowser|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], [ + /quark(?:pc)?\/([-\w\.]+)/i // Quark + ], [VERSION, [NAME, 'Quark']], [ /\bddg\/([\w\.]+)/i // DuckDuckGo ], [VERSION, [NAME, 'DuckDuckGo']], [ /(?:\buc? ?browser|(?:juc.+)ucweb)[\/ ]?([\w\.]+)/i // UCBrowser diff --git a/test/specs/browser-all.json b/test/specs/browser-all.json index 71ae6f0a4..d8638b06f 100644 --- a/test/specs/browser-all.json +++ b/test/specs/browser-all.json @@ -1418,6 +1418,16 @@ "major" : "5" } }, + { + "desc" : "Quark", + "ua" : "mozilla/5.0 (windows nt 10.0; win64; x64) applewebkit/537.36 (khtml, like gecko) chrome/112.0.0.0 safari/537.36 quarkpc/1.5.5.75", + "expect" : + { + "name" : "Quark", + "version" : "1.5.5.75", + "major" : "1" + } + }, { "desc" : "QupZilla", "ua" : "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/538.1 (KHTML, like Gecko) QupZilla/1.8.9 Safari/538.1", From 90659494518a5b5195daac5ef7b9842d61acbe0b Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Wed, 31 Jul 2024 10:16:01 +0700 Subject: [PATCH 19/64] Add new vendor: Nothing https://nothing.tech --- src/enums/ua-parser-enums.js | 1 + src/main/ua-parser.js | 4 ++++ test/specs/device-all.json | 27 +++++++++++++++++++++++++++ 3 files changed, 32 insertions(+) diff --git a/src/enums/ua-parser-enums.js b/src/enums/ua-parser-enums.js index 8fbee9b00..c755c71ce 100644 --- a/src/enums/ua-parser-enums.js +++ b/src/enums/ua-parser-enums.js @@ -219,6 +219,7 @@ const Vendor = Object.freeze({ NEXIAN: 'Nexian', NINTENDO: 'Nintendo', NOKIA: 'Nokia', + NOTHING: 'Nothing', NVIDIA: 'Nvidia', ONEPLUS: 'OnePlus', OPPO: 'OPPO', diff --git a/src/main/ua-parser.js b/src/main/ua-parser.js index 00f3a683d..9b9a3c8c5 100755 --- a/src/main/ua-parser.js +++ b/src/main/ua-parser.js @@ -641,6 +641,10 @@ /; ((?:power )?armor(?:[\w ]{0,8}))(?: bui|\))/i ], [MODEL, [VENDOR, 'Ulefone'], [TYPE, MOBILE]], [ + // Nothing + /droid.+; (a(?:015|06[35]|142p?))/i + ], [MODEL, [VENDOR, 'Nothing'], [TYPE, MOBILE]], [ + // MIXED /(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus|dell|meizu|motorola|polytron|infinix|tecno)[-_ ]?([-\w]*)/i, // BlackBerry/BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron diff --git a/test/specs/device-all.json b/test/specs/device-all.json index 5e08f1361..d4dc62c4c 100644 --- a/test/specs/device-all.json +++ b/test/specs/device-all.json @@ -1367,6 +1367,33 @@ "type": "mobile" } }, + { + "desc": "Nothing 1", + "ua": "Mozilla/5.0 (Linux; Android 13; A063) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/22.0 Chrome/111.0.5563.116 Mobile Safari/537.36", + "expect": { + "vendor": "Nothing", + "model": "A063", + "type": "mobile" + } + }, + { + "desc": "Nothing 2", + "ua": "Mozilla/5.0 (Linux; Android 14; A065 Build/UP1A.231005.007; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/125.0.6422.53 Mobile Safari/537.36", + "expect": { + "vendor": "Nothing", + "model": "A065", + "type": "mobile" + } + }, + { + "desc": "Nothing 2a", + "ua": "Mozilla/5.0 (Linux; Android 14; A142 Build/UP1A.231005.007; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/126.0.6478.71 Mobile Safari/537.36", + "expect": { + "vendor": "Nothing", + "model": "A142", + "type": "mobile" + } + }, { "desc": "Oculus Quest", "ua": "Mozilla/5.0 (Linux; Android 10; Quest) AppleWebKit/537.36 (KHTML, like Gecko) OculusBrowser/15.0.0.0.22.280317669 SamsungBrowser/4.0 Chrome/89.0.4389.90 VR Safari/537.36", From cf775f18f00959332e64c06ed1f7a56313451bf8 Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Wed, 31 Jul 2024 10:45:20 +0700 Subject: [PATCH 20/64] Restore unintentionally removed code from previous commit --- src/main/ua-parser.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/ua-parser.js b/src/main/ua-parser.js index 9b9a3c8c5..cabfb839c 100755 --- a/src/main/ua-parser.js +++ b/src/main/ua-parser.js @@ -327,8 +327,8 @@ /(?: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|qupzilla|falkon|rekonq|puffin|brave|whale(?!.+naver)|qqbrowserlite|duckduckgo|klar)\/([-\w\.]+)/i, - // Rekonq/Puffin/Brave/Whale/QQBrowserLite/QQ//Vivaldi/DuckDuckGo/Klar + /(flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi|iridium|phantomjs|bowser|qupzilla|falkon|rekonq|puffin|brave|whale(?!.+naver)|qqbrowserlite|duckduckgo|klar|helio)\/([-\w\.]+)/i, + // Rekonq/Puffin/Brave/Whale/QQBrowserLite/QQ//Vivaldi/DuckDuckGo/Klar/Helio /(heytap|ovi)browser\/([\d\.]+)/i, // HeyTap/Ovi /(weibo)__([\d\.]+)/i // Weibo ], [NAME, VERSION], [ From ac3a3c33dcd5d487021e2ebbfbb3d5536214f542 Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Sun, 4 Aug 2024 10:29:17 +0700 Subject: [PATCH 21/64] Add new device vendor: TCL https://www.tcl.com/global/en/mobile --- src/enums/ua-parser-enums.js | 1 + src/main/ua-parser.js | 4 ++ test/specs/device-all.json | 108 +++++++++++++++++++++++++++++++++++ 3 files changed, 113 insertions(+) diff --git a/src/enums/ua-parser-enums.js b/src/enums/ua-parser-enums.js index c755c71ce..3801a86e1 100644 --- a/src/enums/ua-parser-enums.js +++ b/src/enums/ua-parser-enums.js @@ -237,6 +237,7 @@ const Vendor = Object.freeze({ SIEMENS: 'Siemens', SONY: 'Sony', SPRINT: 'Sprint', + TCL: 'TCL', TECHNISAT: 'TechniSAT', TECNO: 'Tecno', TESLA: 'Tesla', diff --git a/src/main/ua-parser.js b/src/main/ua-parser.js index cabfb839c..0b87936ed 100755 --- a/src/main/ua-parser.js +++ b/src/main/ua-parser.js @@ -628,6 +628,10 @@ /(alcatel|geeksphone|nexian|panasonic(?!(?:;|\.))|sony(?!-bra))[-_ ]?([-\w]*)/i // Alcatel/GeeksPhone/Nexian/Panasonic/Sony ], [VENDOR, [MODEL, /_/g, ' '], [TYPE, MOBILE]], [ + // TCL + /droid [\w\.]+; ((?:8[14]9[16]|9(?:0(?:48|60|8[01])|1(?:3[27]|66)|2(?:6[69]|9[56])|466))[gqswx])\w*(\)| bui)/i + ], [MODEL, [VENDOR, 'TCL'], [TYPE, TABLET]], [ + // Acer /droid.+; ([ab][1-7]-?[0178a]\d\d?)/i ], [MODEL, [VENDOR, 'Acer'], [TYPE, TABLET]], [ diff --git a/test/specs/device-all.json b/test/specs/device-all.json index d4dc62c4c..0f11ef3d7 100644 --- a/test/specs/device-all.json +++ b/test/specs/device-all.json @@ -2420,6 +2420,114 @@ "type": "smarttv" } }, + { + "desc": "TCL 10 TabMax", + "ua": "Mozilla/5.0 (Linux; Android 11; 9296Q) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36", + "expect": { + "vendor": "TCL", + "model": "9296Q", + "type": "tablet" + } + }, + { + "desc": "TCL 10 TabMax 4G", + "ua": "Mozilla/5.0 (Linux; Android 10; 9295G_EEA) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36", + "expect": { + "vendor": "TCL", + "model": "9295G", + "type": "tablet" + } + }, + { + "desc": "TCL 10 TabMax WiFi", + "ua": "Mozilla/5.0 (Linux; Android 10; 9296G_TR) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.101 Safari/537.36", + "expect": { + "vendor": "TCL", + "model": "9296G", + "type": "tablet" + } + }, + { + "desc": "TCL NxtPaper 11", + "ua": "Mozilla/5.0 (Linux; Android 13; 9466X Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/126.0.6478.179 Safari/537.36 [FB_IAB/FB4A;FBAV/473.0.0.41.81;]", + "expect": { + "vendor": "TCL", + "model": "9466X", + "type": "tablet" + } + }, + { + "desc": "TCL Tab 8 4G", + "ua": "Mozilla/5.0 (Linux; Android 10; 9048S) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36", + "expect": { + "vendor": "TCL", + "model": "9048S", + "type": "tablet" + } + }, + { + "desc": "TCL Tab 8 LE", + "ua": "Mozilla/5.0 (Linux; Android 12; 9137W Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/114.0.5735.61 Mobile Safari/537.36", + "expect": { + "vendor": "TCL", + "model": "9137W", + "type": "tablet" + } + }, + { + "desc": "TCL Tab 10 FHD 4G", + "ua": "Mozilla/5.0 (Linux; Android 11; 9060G Build/RP1A.200720.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/114.0.5735.196 Safari/537.36", + "expect": { + "vendor": "TCL", + "model": "9060G", + "type": "tablet" + } + }, + { + "desc": "TCL Tab 10 HD 4G", + "ua": "Mozilla/5.0 (Linux; Android 11; 9060X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Mobile Safari/537.36", + "expect": { + "vendor": "TCL", + "model": "9060X", + "type": "tablet" + } + }, + { + "desc": "TCL Tab 10 LTE", + "ua": "Mozilla/5.0 (Linux; Android 13; 8196G Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/126.0.6478.162 Safari/537.36 [FB_IAB/FB4A;FBAV/471.0.0.35.80;]", + "expect": { + "vendor": "TCL", + "model": "8196G", + "type": "tablet" + } + }, + { + "desc": "TCL Tab 10 WiFi", + "ua": "Mozilla/5.0 (Linux; Android 13; 8496G Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/127.0.6533.61 Safari/537.36 [FB_IAB/FB4A;FBAV/474.0.0.52.74;]", + "expect": { + "vendor": "TCL", + "model": "8496G", + "type": "tablet" + } + }, + { + "desc": "TCL Tab 10L", + "ua": "Mozilla/5.0 (Linux; Android 11; 8491X_EEA Build/RP1A.200720.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/107.0.5304.105 Safari/537.36", + "expect": { + "vendor": "TCL", + "model": "8491X", + "type": "tablet" + } + }, + { + "desc": "TCL Tab 10s 4G", + "ua": "Mozilla/5.0 (Linux; Android 11; 9080G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36", + "expect": { + "vendor": "TCL", + "model": "9080G", + "type": "tablet" + } + }, { "desc": "Tecno KC8", "ua": "Mozilla/5.0 (Linux; Android 10; TECNO KC8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Mobile Safari/537.36", From cce9060b4f3c26ce1f11c6a3a444e1a4afb5f1b1 Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Tue, 6 Aug 2024 21:23:54 +0700 Subject: [PATCH 22/64] Add more TCL devices --- src/main/ua-parser.js | 5 +- test/specs/device-all.json | 369 +++++++++++++++++++++++++++++++++++++ 2 files changed, 373 insertions(+), 1 deletion(-) diff --git a/src/main/ua-parser.js b/src/main/ua-parser.js index 0b87936ed..b817bdf01 100755 --- a/src/main/ua-parser.js +++ b/src/main/ua-parser.js @@ -629,8 +629,11 @@ ], [VENDOR, [MODEL, /_/g, ' '], [TYPE, MOBILE]], [ // TCL - /droid [\w\.]+; ((?:8[14]9[16]|9(?:0(?:48|60|8[01])|1(?:3[27]|66)|2(?:6[69]|9[56])|466))[gqswx])\w*(\)| bui)/i + /tcl (xess p17aa)/i, + /droid [\w\.]+; ((?:8[14]9[16]|9(?:0(?:48|60|8[01])|1(?:3[27]|66)|2(?:6[69]|9[56])|466))[gqswx])(_\w(\w|\w\w))?(\)| bui)/i ], [MODEL, [VENDOR, 'TCL'], [TYPE, TABLET]], [ + /droid [\w\.]+; (418(?:7d|8v)|5087z|5102l|61(?:02[dh]|25[adfh]|27[ai]|56[dh]|59k|65[ah])|a509dl|t(?:43(?:0w|1[adepqu])|50(?:6d|7[adju])|6(?:09dl|10k|12b|71[efho]|76[hjk])|7(?:66[ahju]|67[hw]|7[045][bh]|71[hk]|73o|76[ho]|79w|81[hks]?|82h|90[bhsy]|99b)|810[hs]))(_\w(\w|\w\w))?(\)| bui)/i + ], [MODEL, [VENDOR, 'TCL'], [TYPE, MOBILE]], [ // Acer /droid.+; ([ab][1-7]-?[0178a]\d\d?)/i diff --git a/test/specs/device-all.json b/test/specs/device-all.json index 0f11ef3d7..40b84b129 100644 --- a/test/specs/device-all.json +++ b/test/specs/device-all.json @@ -2420,6 +2420,51 @@ "type": "smarttv" } }, + { + "desc": "TCL 10 5G", + "ua": "Mozilla/5.0 (Linux; Android 11; T790Y) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Mobile Safari/537.36 EdgA/114.0.1823.43", + "expect": { + "vendor": "TCL", + "model": "T790Y", + "type": "mobile" + } + }, + { + "desc": "TCL 10 5G UW", + "ua": "Mozilla/5.0 (Linux; Android 10; T790S) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Mobile Safari/537.36", + "expect": { + "vendor": "TCL", + "model": "T790S", + "type": "mobile" + } + }, + { + "desc": "TCL 10 Plus", + "ua": "Mozilla/5.0 (Linux; Android 11; T782H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Mobile Safari/537.36 OPR/64.3.3282.60839", + "expect": { + "vendor": "TCL", + "model": "T782H", + "type": "mobile" + } + }, + { + "desc": "TCL 10 Pro", + "ua": "Mozilla/5.0 (Linux; Android 10; T799B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.87 Mobile Safari/537.36", + "expect": { + "vendor": "TCL", + "model": "T799B", + "type": "mobile" + } + }, + { + "desc": "TCL 10 SE", + "ua": "Mozilla/5.0 (Linux; Android 10; T766H_RU) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.85 Mobile Safari/537.36", + "expect": { + "vendor": "TCL", + "model": "T766H", + "type": "mobile" + } + }, { "desc": "TCL 10 TabMax", "ua": "Mozilla/5.0 (Linux; Android 11; 9296Q) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36", @@ -2447,6 +2492,312 @@ "type": "tablet" } }, + { + "desc": "TCL 10L", + "ua": "Mozilla/5.0 (Linux; Android 10; T770B Build/QKQ1.200329.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/87.0.4280.141 Mobile Safari/537.36 GSA/11.41.10.23.arm64", + "expect": { + "vendor": "TCL", + "model": "T770B", + "type": "mobile" + } + }, + { + "desc": "TCL 10L", + "ua": "Mozilla/5.0 (Linux; Android 11; T770H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.101 Mobile Safari/537.36", + "expect": { + "vendor": "TCL", + "model": "T770H", + "type": "mobile" + } + }, + { + "desc": "TCL 20 5G", + "ua": "Mozilla/5.0 (Linux; Android 11; T781) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "expect": { + "vendor": "TCL", + "model": "T781", + "type": "mobile" + } + }, + { + "desc": "TCL 20 Pro 5G", + "ua": "Mozilla/5.0 (Linux; Android 12; T810S) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Mobile Safari/537.36 EdgA/113.0.1774.63", + "expect": { + "vendor": "TCL", + "model": "T810S", + "type": "mobile" + } + }, + { + "desc": "TCL 20 SE", + "ua": "Mozilla/5.0 (Linux; Android 11; T671H Build/RKQ1.201112.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/99.0.4844.73 Mobile Safari/537.36 GoogleApp/13.9.7.23.arm64", + "expect": { + "vendor": "TCL", + "model": "T671H", + "type": "mobile" + } + }, + { + "desc": "TCL 20 XE", + "ua": "Mozilla/5.0 (Linux; Android 11; 5087Z) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36", + "expect": { + "vendor": "TCL", + "model": "5087Z", + "type": "mobile" + } + }, + { + "desc": "TCL 20B", + "ua": "Mozilla/5.0 (Linux; Android 11; 6159K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Mobile Safari/537.36", + "expect": { + "vendor": "TCL", + "model": "6159K", + "type": "mobile" + } + }, + { + "desc": "TCL 205", + "ua": "Mozilla/5.0 (Linux; Android 11; 4187D) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Mobile Safari/537.36", + "expect": { + "vendor": "TCL", + "model": "4187D", + "type": "mobile" + } + }, + { + "desc": "TCL 20E", + "ua": "Mozilla/5.0 (Linux; Android 11; 6125A) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/18.0 Chrome/99.0.4844.88 Mobile Safari/537.36", + "expect": { + "vendor": "TCL", + "model": "6125A", + "type": "mobile" + } + }, + { + "desc": "TCL 20L", + "ua": "Mozilla/5.0 (Linux; Android 11; T774H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.59 Mobile Safari/537.36", + "expect": { + "vendor": "TCL", + "model": "T774H", + "type": "mobile" + } + }, + { + "desc": "TCL 20L Plus", + "ua": "Mozilla/5.0 (Linux; Android 11; T775H Build/RKQ1.210107.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/114.0.5735.61 Mobile Safari/537.36", + "expect": { + "vendor": "TCL", + "model": "T775H", + "type": "mobile" + } + }, + { + "desc": "TCL 20R 5G", + "ua": "Mozilla/5.0 (Linux; Android 11; T767H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.97 Mobile Safari/537.36 OPR/71.3.3718.67322", + "expect": { + "vendor": "TCL", + "model": "T767H", + "type": "mobile" + } + }, + { + "desc": "TCL 20S", + "ua": "Mozilla/5.0 (Linux; Android 11; T773O) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Mobile Safari/537.36", + "expect": { + "vendor": "TCL", + "model": "T773O", + "type": "mobile" + } + }, + { + "desc": "TCL 20Y", + "ua": "Mozilla/5.0 (Linux; Android 11; 6156D) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.134 Mobile Safari/537.36 OPR/70.3.3653.66287", + "expect": { + "vendor": "TCL", + "model": "6156D", + "type": "mobile" + } + }, + { + "desc": "TCL 30 V 5G", + "ua": "Mozilla/5.0 (Linux; Android 11; T781S Build/RKQ1.210614.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/115.0.5790.166 Mobile Safari/537.36[FBAN/EMA;FBLC/en_US;FBAV/369.0.0.5.110;]", + "expect": { + "vendor": "TCL", + "model": "T781S", + "type": "mobile" + } + }, + { + "desc": "TCL 30 XE 5G", + "ua": "Mozilla/5.0 (Linux; Android 12; T767W Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/113.0.5672.162 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/416.0.0.35.85;]", + "expect": { + "vendor": "TCL", + "model": "T767W", + "type": "mobile" + } + }, + { + "desc": "TCL 305", + "ua": "Mozilla/5.0 (Linux; arm; Android 11; 6102D) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.167 YaBrowser/22.7.6.96.00 SA/3 Mobile Safari/537.36", + "expect": { + "vendor": "TCL", + "model": "6102D", + "type": "mobile" + } + }, + { + "desc": "TCL 306", + "ua": "Mozilla/5.0 (Linux; Android 12; 6102H Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/107.0.5304.141 Mobile Safari/537.36[FBAN/EMA;FBLC/it_IT;FBAV/332.0.0.22.108;]", + "expect": { + "vendor": "TCL", + "model": "6102H", + "type": "mobile" + } + }, + { + "desc": "TCL 30", + "ua": "Mozilla/5.0 (Linux; Android 12; T676H Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/113.0.5672.162 Mobile Safari/537.36", + "expect": { + "vendor": "TCL", + "model": "T676H", + "type": "mobile" + } + }, + { + "desc": "TCL 30+", + "ua": "Mozilla/5.0 (Linux; Android 12; T676J) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Mobile Safari/537.36", + "expect": { + "vendor": "TCL", + "model": "T676J", + "type": "mobile" + } + }, + { + "desc": "TCL 30 5G", + "ua": "Mozilla/5.0 (Linux; Android 12; T776H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.104 Mobile Safari/537.36", + "expect": { + "vendor": "TCL", + "model": "T776H", + "type": "mobile" + } + }, + { + "desc": "TCL 30 LE", + "ua": "Mozilla/5.0 (Linux; Android 12; 4188V Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/112.0.5615.136 Mobile Safari/537.36[FBAN/EMA;FBLC/en_US;FBAV/352.0.0.14.108;]", + "expect": { + "vendor": "TCL", + "model": "4188V", + "type": "mobile" + } + }, + { + "desc": "TCL 30 SE", + "ua": "Mozilla/5.0 (Linux; Android 12; 6165H Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/108.0.5359.128 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/396.1.0.28.104;]", + "expect": { + "vendor": "TCL", + "model": "6165H", + "type": "mobile" + } + }, + { + "desc": "TCL 30E", + "ua": "Mozilla/5.0 (Linux; Android 12; 6127I) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Mobile Safari/537.36", + "expect": { + "vendor": "TCL", + "model": "6127I", + "type": "mobile" + } + }, + { + "desc": "TCL 40 NxtPaper", + "ua": "Mozilla/5.0 (Linux; Android 13; T612B Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/125.0.6422.53 Mobile Safari/537.36", + "expect": { + "vendor": "TCL", + "model": "T612B", + "type": "mobile" + } + }, + { + "desc": "TCL A3", + "ua": "Mozilla/5.0 (Linux; Android 11; A509DL Build/RP1A.200720.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/101.0.4951.61 Mobile Safari/537.36 GSA/13.18.7.23.arm64", + "expect": { + "vendor": "TCL", + "model": "A509DL", + "type": "mobile" + } + }, + { + "desc": "TCL A30", + "ua": "Mozilla/5.0 (Linux; Android 11; 5102L Build/RP1A.200720.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/112.0.5615.136 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/413.0.0.30.104;]", + "expect": { + "vendor": "TCL", + "model": "5102L", + "type": "mobile" + } + }, + { + "desc": "TCL 40 SE", + "ua": "Mozilla/5.0 (Linux; Android 13; T610K Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/115.0.5790.166 Mobile Safari/537.36", + "expect": { + "vendor": "TCL", + "model": "T610K", + "type": "mobile" + } + }, + { + "desc": "TCL 40 XE 5G", + "ua": "Mozilla/5.0 (Linux; Android 13; T609DL Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/125.0.6422.136 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/466.1.0.57.85;]", + "expect": { + "vendor": "TCL", + "model": "T609DL", + "type": "mobile" + } + }, + { + "desc": "TCL 403", + "ua": "Mozilla/5.0 (Linux; Android 12; T431D) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Mobile Safari/537.36", + "expect": { + "vendor": "TCL", + "model": "T431D", + "type": "mobile" + } + }, + { + "desc": "TCL 405", + "ua": "Mozilla/5.0 (Linux; Android 12; T506D Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/113.0.5672.162 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/418.0.0.33.69;]", + "expect": { + "vendor": "TCL", + "model": "T506D", + "type": "mobile" + } + }, + { + "desc": "TCL 408", + "ua": "Mozilla/5.0 (Linux; U; Android 12; T507U Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/105.0.5195.136 Mobile Safari/537.36 OPR/75.0.2254.68857", + "expect": { + "vendor": "TCL", + "model": "T507U", + "type": "mobile" + } + }, + { + "desc": "TCL 40R 5G", + "ua": "Mozilla/5.0 (Linux; Android 12; T771K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Mobile Safari/537.36 EdgA/114.0.1823.37", + "expect": { + "vendor": "TCL", + "model": "T771K", + "type": "mobile" + } + }, + { + "desc": "TCL Ion X", + "ua": "Mozilla/5.0 (Linux; Android 12; T430W Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/114.0.5735.60 Mobile Safari/537.36", + "expect": { + "vendor": "TCL", + "model": "T430W", + "type": "mobile" + } + }, { "desc": "TCL NxtPaper 11", "ua": "Mozilla/5.0 (Linux; Android 13; 9466X Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/126.0.6478.179 Safari/537.36 [FB_IAB/FB4A;FBAV/473.0.0.41.81;]", @@ -2456,6 +2807,15 @@ "type": "tablet" } }, + { + "desc": "TCL Stylus 5G", + "ua": "Mozilla/5.0 (Linux; Android 12; T779W Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/127.0.6533.2 Mobile Safari/537.36", + "expect": { + "vendor": "TCL", + "model": "T779W", + "type": "mobile" + } + }, { "desc": "TCL Tab 8 4G", "ua": "Mozilla/5.0 (Linux; Android 10; 9048S) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36", @@ -2528,6 +2888,15 @@ "type": "tablet" } }, + { + "desc": "TCL Xess P17AA", + "ua": "Mozilla/5.0 (Linux; Android 5.1; TCL Xess P17AA Build/LMY47D) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.85 Safari/537.36", + "expect": { + "vendor": "TCL", + "model": "Xess P17AA", + "type": "tablet" + } + }, { "desc": "Tecno KC8", "ua": "Mozilla/5.0 (Linux; Android 10; TECNO KC8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Mobile Safari/537.36", From 692b175d49b74d1c93e14e49daa9b36c12de221d Mon Sep 17 00:00:00 2001 From: Joey Parrish Date: Tue, 13 Aug 2024 20:46:21 -0700 Subject: [PATCH 23/64] feat: Update and expand Chromecast device families (#724) --- src/main/ua-parser.js | 27 ++++++++++++++++++++++----- test/specs/device-all.json | 36 ++++++++++++++++++++++++++++++++++++ test/specs/os-all.json | 31 +++++++++++++++++++++++++++++-- 3 files changed, 87 insertions(+), 7 deletions(-) diff --git a/src/main/ua-parser.js b/src/main/ua-parser.js index b817bdf01..a8ba868d0 100755 --- a/src/main/ua-parser.js +++ b/src/main/ua-parser.js @@ -82,6 +82,7 @@ PREFIX_MOBILE = 'Mobile ', SUFFIX_BROWSER = ' Browser', CHROME = 'Chrome', + CHROMECAST = 'Chromecast', EDGE = 'Edge', FIREFOX = 'Firefox', OPERA = 'Opera', @@ -696,8 +697,14 @@ ], [[VENDOR, LG], [TYPE, SMARTTV]], [ /(apple) ?tv/i // Apple TV ], [VENDOR, [MODEL, APPLE+' TV'], [TYPE, SMARTTV]], [ - /crkey/i // Google Chromecast - ], [[MODEL, CHROME+'cast'], [VENDOR, GOOGLE], [TYPE, SMARTTV]], [ + /crkey.*devicetype\/chromecast/i // Google Chromecast Third Generation + ], [[MODEL, CHROMECAST+' Third Generation'], [VENDOR, GOOGLE], [TYPE, SMARTTV]], [ + /crkey.*devicetype\/([^/]*)/i // Google Chromecast with specific device type + ], [[MODEL, /^/, 'Chromecast '], [VENDOR, GOOGLE], [TYPE, SMARTTV]], [ + /fuchsia.*crkey/i // Google Chromecast Nest Hub + ], [[MODEL, CHROMECAST+' Nest Hub'], [VENDOR, GOOGLE], [TYPE, SMARTTV]], [ + /crkey/i // Google Chromecast, Linux-based or unknown + ], [[MODEL, CHROMECAST], [VENDOR, GOOGLE], [TYPE, SMARTTV]], [ /droid.+aft(\w+)( bui|\))/i // Fire TV ], [MODEL, [VENDOR, AMAZON], [TYPE, SMARTTV]], [ /\(dtv[\);].+(aquos)/i, @@ -817,6 +824,18 @@ /(macintosh|mac_powerpc\b)(?!.+haiku)/i // Mac OS ], [[NAME, 'macOS'], [VERSION, /_/g, '.']], [ + // Google Chromecast + /android ([\d\.]+).*crkey/i // Google Chromecast, Android-based + ], [VERSION, [NAME, CHROMECAST + ' Android']], [ + /fuchsia.*crkey\/([\d\.]+)/i // Google Chromecast, Fuchsia-based + ], [VERSION, [NAME, CHROMECAST + ' Fuchsia']], [ + /crkey\/([\d\.]+).*devicetype\/smartspeaker/i // Google Chromecast, Linux-based Smart Speaker + ], [VERSION, [NAME, CHROMECAST + ' SmartSpeaker']], [ + /linux.*crkey\/([\d\.]+)/i // Google Chromecast, Legacy Linux-based + ], [VERSION, [NAME, CHROMECAST + ' Linux']], [ + /crkey\/([\d\.]+)/i // Google Chromecast, unknown + ], [VERSION, [NAME, CHROMECAST]], [ + // Mobile OSes /droid ([\w\.]+)\b.+(android[- ]x86|harmonyos)/i // Android-x86/HarmonyOS ], [VERSION, NAME], [ // Android/WebOS/QNX/Bada/RIM/Maemo/MeeGo/Sailfish OS @@ -837,9 +856,7 @@ /watch(?: ?os[,\/]|\d,\d\/)([\d\.]+)/i // watchOS ], [VERSION, [NAME, 'watchOS']], [ - // Google Chromecast - /crkey\/([\d\.]+)/i // Google Chromecast - ], [VERSION, [NAME, CHROME+'cast']], [ + // Google ChromeOS /(cros) [\w]+(?:\)| ([\w\.]+)\b)/i // Chromium OS ], [[NAME, "Chrome OS"], VERSION],[ diff --git a/test/specs/device-all.json b/test/specs/device-all.json index 40b84b129..aa3c8f027 100644 --- a/test/specs/device-all.json +++ b/test/specs/device-all.json @@ -3554,6 +3554,42 @@ "type": "mobile" } }, + { + "desc": "Google Chromecast with Google TV", + "ua": "Mozilla/5.0 (Linux; Android 12.0; Build/STTL.240206.002) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.0 Safari/537.36 CrKey/1.56.500000 DeviceType/AndroidTV", + "expect": { + "vendor": "Google", + "model": "Chromecast AndroidTV", + "type": "smarttv" + } + }, + { + "desc": "Google Chromecast Mini Smart Speaker", + "ua": "Mozilla/5.0 (X11; Linux armv7l) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.225 Safari/537.36 CrKey/1.56.500000 DeviceType/SmartSpeaker", + "expect": { + "vendor": "Google", + "model": "Chromecast SmartSpeaker", + "type": "smarttv" + } + }, + { + "desc": "Google Chromecast Third Generation", + "ua": "Mozilla/5.0 (X11; Linux armv7l) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.225 Safari/537.36 CrKey/1.56.500000 DeviceType/Chromecast", + "expect": { + "vendor": "Google", + "model": "Chromecast Third Generation", + "type": "smarttv" + } + }, + { + "desc": "Google Chromecast Nest Hub", + "ua": "Mozilla/5.0 (Fuchsia) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 CrKey/1.56.500000", + "expect": { + "vendor": "Google", + "model": "Chromecast Nest Hub", + "type": "smarttv" + } + }, { "desc": "Google Chromecast", "ua": "Mozilla/5.0 (X11; Linux armv7l) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.84 Safari/537.36 CrKey/1.22.79313", diff --git a/test/specs/os-all.json b/test/specs/os-all.json index 5e9beb288..6fc03ecdd 100644 --- a/test/specs/os-all.json +++ b/test/specs/os-all.json @@ -414,11 +414,38 @@ } }, { - "desc" : "Google Chromecast", + "desc" : "Google Chromecast with Google TV", + "ua" : "Mozilla/5.0 (Linux; Android 12.0; Build/STTL.240206.002) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.0 Safari/537.36 CrKey/1.56.500000 DeviceType/AndroidTV", + "expect" : + { + "name" : "Chromecast Android", + "version" : "12.0" + } + }, + { + "desc" : "Google Chromecast Nest Hub", + "ua" : "Mozilla/5.0 (Fuchsia) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 CrKey/1.56.500000", + "expect" : + { + "name" : "Chromecast Fuchsia", + "version" : "1.56.500000" + } + }, + { + "desc" : "Google Chromecast Mini Smart Speaker", + "ua" : "Mozilla/5.0 (X11; Linux armv7l) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.225 Safari/537.36 CrKey/1.56.500000 DeviceType/SmartSpeaker", + "expect" : + { + "name" : "Chromecast SmartSpeaker", + "version" : "1.56.500000" + } + }, + { + "desc" : "Google Chromecast Legacy Linux-Based", "ua" : "Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.81 Safari/537.36 CrKey/1.42.183786", "expect" : { - "name" : "Chromecast", + "name" : "Chromecast Linux", "version" : "1.42.183786" } }, From 68ae2a76deaa9cf2826b375b25d96fa4d14dd044 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Os=C3=A9s?= Date: Wed, 14 Aug 2024 00:46:46 -0300 Subject: [PATCH 24/64] adding detection of MJ12Bot and SemrushBot into extension Crawlers including testing (#738) --- src/extensions/ua-parser-extensions.js | 4 +++- src/extensions/ua-parser-extensions.mjs | 4 +++- test/specs/browser-crawlers.json | 20 ++++++++++++++++++++ 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/extensions/ua-parser-extensions.js b/src/extensions/ua-parser-extensions.js index bd0ee4056..f0d4a7b8c 100644 --- a/src/extensions/ua-parser-extensions.js +++ b/src/extensions/ua-parser-extensions.js @@ -46,7 +46,9 @@ const Crawlers = Object.freeze({ // 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, + // MJ12bot - https://mj12bot.com/ + // SemrushBot - http://www.semrush.com/bot.html + /((?:amazon|apple|bing|duckduck|facebook|gpt|mj12|semrush)bot)\/([\w\.]+)/i, // Baiduspider https://help.baidu.com/question?prod_id=99&class=0&id=3001 /(baiduspider)[-imagevdonsfcpr]{0,6}\/([\w\.]+)/i, diff --git a/src/extensions/ua-parser-extensions.mjs b/src/extensions/ua-parser-extensions.mjs index 9bec89023..192889056 100644 --- a/src/extensions/ua-parser-extensions.mjs +++ b/src/extensions/ua-parser-extensions.mjs @@ -48,7 +48,9 @@ const Crawlers = Object.freeze({ // 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], + // MJ12bot - https://mj12bot.com/ + // SemrushBot - http://www.semrush.com/bot.html + [/((?:amazon|apple|bing|duckduck|facebook|gpt|mj12|semrush)bot)\/([\w\.]+)/i], [NAME, VERSION, [TYPE, CRAWLER]], // Baiduspider https://help.baidu.com/question?prod_id=99&class=0&id=3001 diff --git a/test/specs/browser-crawlers.json b/test/specs/browser-crawlers.json index 107ab24b4..b7e8169b2 100644 --- a/test/specs/browser-crawlers.json +++ b/test/specs/browser-crawlers.json @@ -79,6 +79,26 @@ "type" : "crawler" } }, + { + "desc" : "MJ12bot", + "ua" : "Mozilla/5.0 (compatible; MJ12bot/v1.4.8; http://mj12bot.com/)", + "expect" : + { + "name" : "MJ12bot", + "version" : "v1.4.8", + "type" : "crawler" + } + }, + { + "desc" : "SemrushBot", + "ua" : "Mozilla/5.0 (compatible; SemrushBot/7~bl; +http://www.semrush.com/bot.html)", + "expect" : + { + "name" : "SemrushBot", + "version" : "7", + "type" : "crawler" + } + }, { "desc" : "Yahoo! Japan", "ua" : "Y!J-BRW/1.0 (https://www.yahoo-help.jp/app/answers/detail/p/595/a_id/42716)", From ccc554232bc29df4bea424ac89a6f7f268ca3bdc Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Fri, 16 Aug 2024 13:36:05 +0700 Subject: [PATCH 25/64] Improve detection: recognize Samsung Galaxy Watch devices as `wearable` --- src/main/ua-parser.js | 6 ++++-- test/specs/device-all.json | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/main/ua-parser.js b/src/main/ua-parser.js index a8ba868d0..a6cbfcd19 100755 --- a/src/main/ua-parser.js +++ b/src/main/ua-parser.js @@ -500,8 +500,8 @@ // Samsung /\b(sch-i[89]0\d|shw-m380s|sm-[ptx]\w{2,4}|gt-[pn]\d{2,4}|sgh-t8[56]9|nexus 10)/i ], [MODEL, [VENDOR, SAMSUNG], [TYPE, TABLET]], [ - /\b((?:s[cgp]h|gt|sm)-\w+|sc[g-]?[\d]+a?|galaxy nexus)/i, - /samsung[- ]([-\w]+)/i, + /\b((?:s[cgp]h|gt|sm)-(?![lr])\w+|sc[g-]?[\d]+a?|galaxy nexus)/i, + /samsung[- ]((?!sm-[lr])[-\w]+)/i, /sec-(sgh\w+)/i ], [MODEL, [VENDOR, SAMSUNG], [TYPE, MOBILE]], [ @@ -740,6 +740,8 @@ // WEARABLES /////////////////// + /\b(sm-[lr]\d\d[05][fnuw]?s?)\b/i // Samsung Galaxy Watch + ], [MODEL, [VENDOR, SAMSUNG], [TYPE, WEARABLE]], [ /((pebble))app/i // Pebble ], [VENDOR, MODEL, [TYPE, WEARABLE]], [ /(watch)(?: ?os[,\/]|\d,\d\/)[\d\.]+/i // Apple Watch diff --git a/test/specs/device-all.json b/test/specs/device-all.json index aa3c8f027..bff516361 100644 --- a/test/specs/device-all.json +++ b/test/specs/device-all.json @@ -2132,6 +2132,42 @@ "type": "tablet" } }, + { + "desc": "Samsung Galaxy Watch", + "ua": "Mozilla/5.0 (Linux; Tizen 5.5; SAMSUNG SM-R805W) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/2.0 Chrome/69.0.3497.106 Mobile Safari/537.36", + "expect": { + "vendor": "Samsung", + "model": "SM-R805W", + "type": "wearable" + } + }, + { + "desc": "Samsung Galaxy Watch Active 2", + "ua": "Mozilla/5.0 (Linux; Tizen 5.5; SAMSUNG SM-R820) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/2.0 Chrome/69.0.3497.106 Mobile Safari/537.36", + "expect": { + "vendor": "Samsung", + "model": "SM-R820", + "type": "wearable" + } + }, + { + "desc": "Samsung Galaxy Watch4", + "ua": "Mozilla/5.0 (Linux; Android 11; SAMSUNG SM-R875U) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/2.2. Chrome/102.0.5005.125 Mobile Safari/537.36", + "expect": { + "vendor": "Samsung", + "model": "SM-R875U", + "type": "wearable" + } + }, + { + "desc": "Samsung Galaxy Watch5 Pro", + "ua": "Mozilla/5.0 (Linux; Android 11; SAMSUNG SM-R925U) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/3.2. Chrome/111.0.5563.116 Mobile Safari/537.36", + "expect": { + "vendor": "Samsung", + "model": "SM-R925U", + "type": "wearable" + } + }, { "desc": "Samsung Note 10.1", "ua": "Mozilla/5.0 (Linux; Android 5.1.1; SM-P605) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36", From b8d823dd574411906028c4ae3e4bd1bcc5ee936c Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Fri, 16 Aug 2024 14:23:07 +0700 Subject: [PATCH 26/64] Improve detection: Amazon Echo Show devices --- src/main/ua-parser.js | 2 +- test/specs/device-all.json | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/main/ua-parser.js b/src/main/ua-parser.js index a6cbfcd19..75ff935c1 100755 --- a/src/main/ua-parser.js +++ b/src/main/ua-parser.js @@ -600,7 +600,7 @@ // Amazon /(alexa)webm/i, - /(kf[a-z]{2}wi|aeo[c-r]{2})( bui|\))/i, // Kindle Fire without Silk / Echo Show + /(kf[a-z]{2}wi|aeo(?!bc)\w\w)( bui|\))/i, // Kindle Fire without Silk / Echo Show /(kf[a-z]+)( bui|\)).+silk\//i // Kindle Fire HD ], [MODEL, [VENDOR, AMAZON], [TYPE, TABLET]], [ /((?:sd|kf)[0349hijorstuw]+)( bui|\)).+silk\//i // Fire Phone diff --git a/test/specs/device-all.json b/test/specs/device-all.json index bff516361..125555ab8 100644 --- a/test/specs/device-all.json +++ b/test/specs/device-all.json @@ -1916,6 +1916,24 @@ "type": "tablet" } }, + { + "desc": "Echo Show 8", + "ua": "Mozilla/5.0 (Linux; Android 7.1.2; AEOCW) AppleWebKit/537.36 (KHTML, like Gecko) Silk/106.3.3 like Chrome/106.0.5249.170 Safari/537.36", + "expect": { + "vendor": "Amazon", + "model": "AEOCW", + "type": "tablet" + } + }, + { + "desc": "Echo Show 15", + "ua": "Mozilla/5.0 (Linux; Android 9; AEOHY) AppleWebKit/537.36 (KHTML, like Gecko) Silk/112.6.3 like Chrome/112.0.5615.213 Safari/537.36", + "expect": { + "vendor": "Amazon", + "model": "AEOHY", + "type": "tablet" + } + }, { "desc": "Echo Dot", "ua": "Dalvik/2.1.0 (Linux; U; Android 5.1.1; AEOBC Build/LVY48F)", From b1dae13245189dd3c56dbd5ae8fd67eca55496fb Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Mon, 19 Aug 2024 11:10:15 +0700 Subject: [PATCH 27/64] [extension][bot] Add AhrefsBot, AhrefsSiteAudit, Dotbot, Rogerbot, Uptimerobot, Coc Coc Bot --- src/extensions/ua-parser-extensions.js | 12 ++++++-- test/specs/browser-crawlers.json | 40 ++++++++++++++++++++++++++ test/specs/browser-fetchers.json | 30 +++++++++++++++++++ 3 files changed, 79 insertions(+), 3 deletions(-) diff --git a/src/extensions/ua-parser-extensions.js b/src/extensions/ua-parser-extensions.js index f0d4a7b8c..a85052c37 100644 --- a/src/extensions/ua-parser-extensions.js +++ b/src/extensions/ua-parser-extensions.js @@ -40,15 +40,17 @@ const CLIs = Object.freeze({ const Crawlers = Object.freeze({ browser : [ [ + // AhrefsBot - https://ahrefs.com/robot // Amazonbot - https://developer.amazon.com/amazonbot // Applebot - http://apple.com/go/applebot // Bingbot - http://www.bing.com/bingbot.htm + // Dotbot - https://moz.com/help/moz-procedures/crawlers/dotbot // DuckDuckBot - http://duckduckgo.com/duckduckbot.html // FacebookBot - https://developers.facebook.com/docs/sharing/bot/ // GPTBot - https://platform.openai.com/docs/gptbot // MJ12bot - https://mj12bot.com/ // SemrushBot - http://www.semrush.com/bot.html - /((?:amazon|apple|bing|duckduck|facebook|gpt|mj12|semrush)bot)\/([\w\.]+)/i, + /((?:ahrefs|amazon|apple|bing|dot|duckduck|facebook|gpt|mj12|semrush)bot)\/([\w\.]+)/i, // Baiduspider https://help.baidu.com/question?prod_id=99&class=0&id=3001 /(baiduspider)[-imagevdonsfcpr]{0,6}\/([\w\.]+)/i, @@ -56,6 +58,9 @@ const Crawlers = Object.freeze({ // ClaudeBot /(claude(?:bot|-web))\/([\w\.]+)/i, + // Coc Coc Bot - https://help.coccoc.com/en/search-engine + /(coccocbot-(?:image|web))\/([\w\.]+)/i, + // Googlebot - http://www.google.com/bot.html /(google(?:bot|other)(?:-image|-video|-news|-extended)?|(?:storebot-)?google(?:-inspectiontool)?)\/?([\w\.]*)/i, @@ -176,9 +181,10 @@ const Emails = Object.freeze({ const Fetchers = Object.freeze({ browser : [ [ + // AhrefsSiteAudit - https://ahrefs.com/robot/site-audit // ChatGPT-User - https://platform.openai.com/docs/plugins/bot - // BingPreview / Mastodon / Pinterestbot / Redditbot / Telegrambot / Twitterbot - /(bingpreview|chatgpt-user|mastodon|(?:discord|linkedin|pinterest|reddit|telegram|twitter)bot)\/([\w\.]+)/i, + // BingPreview / Mastodon / Pinterestbot / Redditbot / Rogerbot / Telegrambot / Twitterbot / UptimeRobot + /(ahrefssiteaudit|bingpreview|chatgpt-user|mastodon|(?:discord|linkedin|pinterest|reddit|roger|telegram|twitter|uptimero)bot)\/([\w\.]+)/i, // Slackbot - https://api.slack.com/robots /(slack(?:bot)?(?:-imgproxy|-linkexpanding)?) ([\w\.]+)/i, diff --git a/test/specs/browser-crawlers.json b/test/specs/browser-crawlers.json index b7e8169b2..b205ebf83 100644 --- a/test/specs/browser-crawlers.json +++ b/test/specs/browser-crawlers.json @@ -1,4 +1,14 @@ [ + { + "desc" : "AhrefsBot", + "ua" : "Mozilla/5.0 (compatible; AhrefsBot/7.0; +http://ahrefs.com/robot/)", + "expect" : + { + "name" : "AhrefsBot", + "version" : "7.0", + "type" : "crawler" + } + }, { "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)", @@ -39,6 +49,26 @@ "type" : "crawler" } }, + { + "desc" : "Coc Coc Bot (web)", + "ua" : "Mozilla/5.0 (compatible; coccocbot-web/1.0; +http://help.coccoc.com/searchengine)", + "expect" : + { + "name" : "coccocbot-web", + "version" : "1.0", + "type" : "crawler" + } + }, + { + "desc" : "Coc Coc Bot (image)", + "ua" : "Mozilla/5.0 (compatible; coccocbot-image/1.0; +http://help.coccoc.com/searchengine)", + "expect" : + { + "name" : "coccocbot-image", + "version" : "1.0", + "type" : "crawler" + } + }, { "desc" : "ClaudeWeb", "ua" : "Claude-Web/1.0 (web crawler; +https://www.anthropic.com/; bots@anthropic.com)", @@ -49,6 +79,16 @@ "type" : "crawler" } }, + { + "desc" : "Dotbot", + "ua" : "Mozilla/5.0 (compatible; DotBot/1.2; +https://opensiteexplorer.org/dotbot; help@moz.com)", + "expect" : + { + "name" : "DotBot", + "version" : "1.2", + "type" : "crawler" + } + }, { "desc" : "FacebookBot", "ua" : "Mozilla/5.0 (compatible; FacebookBot/1.0; +https://developers.facebook.com/docs/sharing/webmasters/facebookbot/", diff --git a/test/specs/browser-fetchers.json b/test/specs/browser-fetchers.json index 6b537728f..c508bd22f 100644 --- a/test/specs/browser-fetchers.json +++ b/test/specs/browser-fetchers.json @@ -1,4 +1,14 @@ [ + { + "desc" : "AhrefsSiteAudit", + "ua" : "Mozilla/5.0 (Linux; Android 13) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.5359.128 Mobile Safari/537.36 (compatible; AhrefsSiteAudit/6.1; +http://ahrefs.com/robot/site-audit)", + "expect" : + { + "name" : "AhrefsSiteAudit", + "version" : "6.1", + "type" : "fetcher" + } + }, { "desc" : "BingPreview", "ua" : "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534+ (KHTML, like Gecko) BingPreview/1.0b", @@ -18,5 +28,25 @@ "version" : "1.0", "type" : "fetcher" } + }, + { + "desc" : "Rogerbot", + "ua" : "Mozilla/5.0 (compatible; rogerBot/1.0; UrlCrawler; http://www.seomoz.org/dp/rogerbot)", + "expect" : + { + "name" : "rogerBot", + "version" : "1.0", + "type" : "fetcher" + } + }, + { + "desc" : "UptimeRobot", + "ua" : "Mozilla/5.0 (compatible; UptimeRobot/2.0; http://www.uptimerobot.com/)", + "expect" : + { + "name" : "UptimeRobot", + "version" : "2.0", + "type" : "fetcher" + } } ] \ No newline at end of file From 491c2d7477b8536b332ee6e1a9af5744129e3c9a Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Sat, 24 Aug 2024 10:38:09 +0700 Subject: [PATCH 28/64] Add new device vendor: itel https://www.itel-life.com/ --- src/enums/ua-parser-enums.js | 1 + src/main/ua-parser.js | 4 +++ test/specs/device-all.json | 54 ++++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+) diff --git a/src/enums/ua-parser-enums.js b/src/enums/ua-parser-enums.js index 3801a86e1..e8c638efb 100644 --- a/src/enums/ua-parser-enums.js +++ b/src/enums/ua-parser-enums.js @@ -209,6 +209,7 @@ const Vendor = Object.freeze({ HTC: 'HTC', HUAWEI: 'Huawei', INFINIX: 'Infinix', + ITEL: 'itel', JOLLA: 'Jolla', KOBO: 'Kobo', LENOVO: 'Lenovo', diff --git a/src/main/ua-parser.js b/src/main/ua-parser.js index 75ff935c1..2a729e74c 100755 --- a/src/main/ua-parser.js +++ b/src/main/ua-parser.js @@ -636,6 +636,10 @@ /droid [\w\.]+; (418(?:7d|8v)|5087z|5102l|61(?:02[dh]|25[adfh]|27[ai]|56[dh]|59k|65[ah])|a509dl|t(?:43(?:0w|1[adepqu])|50(?:6d|7[adju])|6(?:09dl|10k|12b|71[efho]|76[hjk])|7(?:66[ahju]|67[hw]|7[045][bh]|71[hk]|73o|76[ho]|79w|81[hks]?|82h|90[bhsy]|99b)|810[hs]))(_\w(\w|\w\w))?(\)| bui)/i ], [MODEL, [VENDOR, 'TCL'], [TYPE, MOBILE]], [ + // itel + /(itel) ((\w+))/i + ], [[VENDOR, lowerize], MODEL, [TYPE, strMapper, { 'tablet' : ['p10001l', 'w7001'], '*' : 'mobile' }]], [ + // Acer /droid.+; ([ab][1-7]-?[0178a]\d\d?)/i ], [MODEL, [VENDOR, 'Acer'], [TYPE, TABLET]], [ diff --git a/test/specs/device-all.json b/test/specs/device-all.json index 125555ab8..03340a2d9 100644 --- a/test/specs/device-all.json +++ b/test/specs/device-all.json @@ -1286,6 +1286,60 @@ "type": "mobile" } }, + { + "desc": "itel A25", + "ua": "Mozilla/5.0 (Linux; Android 9; itel L5002) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.130 Mobile Safari/537.36 OPR/63.3.3216.58675", + "expect": { + "vendor": "itel", + "model": "L5002", + "type": "mobile" + } + }, + { + "desc": "itel A50", + "ua": "Mozilla/5.0 (Linux; U; Android 14; itel A667L Build/UP1A.231005.007; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/127.0.6533.103 Mobile Safari/537.36 OPR/83.1.2254.73239", + "expect": { + "vendor": "itel", + "model": "A667L", + "type": "mobile" + } + }, + { + "desc": "itel KidPad 1", + "ua": "Mozilla/5.0 (Linux; Android 10; Itel W7001) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.101 Mobile Safari/537.36", + "expect": { + "vendor": "itel", + "model": "W7001", + "type": "tablet" + } + }, + { + "desc": "itel Pad One", + "ua": "Mozilla/5.0 (Linux; Android 12; itel P10001L Build/SP1A.210812.016) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.172 Safari/537.36", + "expect": { + "vendor": "itel", + "model": "P10001L", + "type": "tablet" + } + }, + { + "desc": "itel RS4", + "ua": "Mozilla/5.0 (Linux; Android 13; itel S666LN Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/125.0.6422.165 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/468.1.0.56.78;]", + "expect": { + "vendor": "itel", + "model": "S666LN", + "type": "mobile" + } + }, + { + "desc": "itel Vision 2S", + "ua": "Mozilla/5.0 (Linux; Android 11; itel P651L Build/RP1A.201005.001) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.5672.76 Mobile Safari/537.36", + "expect": { + "vendor": "itel", + "model": "P651L", + "type": "mobile" + } + }, { "desc": "Moto X", "ua": "Mozilla/5.0 (Linux; U; Android 4.2; xx-xx; XT1058 Build/13.9.0Q2.X-70-GHOST-ATT_LE-2) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30", From b9f1bf6223f0470b316449959f08210e12dc474f Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Fri, 6 Sep 2024 19:26:05 +0700 Subject: [PATCH 29/64] Fix #743 - Improve device detection for Xiaomi --- src/main/ua-parser.js | 2 +- test/specs/device-all.json | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/ua-parser.js b/src/main/ua-parser.js index 2a729e74c..36c9e787c 100755 --- a/src/main/ua-parser.js +++ b/src/main/ua-parser.js @@ -532,7 +532,7 @@ /\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 + /\b(mi[-_ ]?(?:a\d|one|one[_ ]plus|note lte|max|cc)?[_ ]?(?:\d?\w?)[_ ]?(?:plus|se|lite|pro)?)(?: 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 diff --git a/test/specs/device-all.json b/test/specs/device-all.json index 03340a2d9..c85860024 100644 --- a/test/specs/device-all.json +++ b/test/specs/device-all.json @@ -3230,6 +3230,15 @@ "type": "mobile" } }, + { + "desc": "Xiaomi Mi 10 Pro", + "ua": "Linux; U; Android 13; Mi 10 Pro Build/TKQ1.221114.001", + "expect": { + "vendor": "Xiaomi", + "model": "Mi 10 Pro", + "type": "mobile" + } + }, { "desc": "Xiaomi Mi 5s Plus", "ua": "Mozilla/5.0 (Linux; U; Android 6.0.1; zh-cn; MI 5s Plus Build/MXB48T) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/53.0.2785.146 Mobile Safari/537.36 XiaoMi/MiuiBrowser/8.7.1", From db1612401f1d135b49b12be185d46f121f50af48 Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Sat, 14 Sep 2024 12:38:51 +0700 Subject: [PATCH 30/64] Add new helper method: `isFromEU()` to detect whether user comes from an EU country --- package-lock.json | 22 ++++++++++++++++++++++ package.json | 3 +++ script/build-esm.js | 3 ++- src/helpers/ua-parser-helpers.d.ts | 2 ++ src/helpers/ua-parser-helpers.js | 2 ++ 5 files changed, 31 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 71498414b..c1e325174 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,6 +22,9 @@ } ], "license": "AGPL-3.0-or-later", + "dependencies": { + "detect-europe-js": "^0.1.1" + }, "bin": { "ua-parser-js": "script/cli.js" }, @@ -1664,6 +1667,25 @@ "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", "dev": true }, + "node_modules/detect-europe-js": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/detect-europe-js/-/detect-europe-js-0.1.1.tgz", + "integrity": "sha512-+bUXDf+tI3L4dcEuRdAFa44Amx9aEaJzoZssx7Xis4H1bXWc5fAcOP850BOj0wJPRzOdovOuOVEvrg6T+GflZA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/faisalman" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + } + ] + }, "node_modules/detect-libc": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", diff --git a/package.json b/package.json index 618a794d8..6a7d31ac2 100755 --- a/package.json +++ b/package.json @@ -210,6 +210,9 @@ "test:mocha": "mocha test/mocha*js", "test:playwright": "playwright test" }, + "dependencies": { + "detect-europe-js": "^0.1.1" + }, "devDependencies": { "@babel/parser": "7.15.8", "@babel/traverse": "7.23.2", diff --git a/script/build-esm.js b/script/build-esm.js index cd7523878..68b8258a0 100755 --- a/script/build-esm.js +++ b/script/build-esm.js @@ -7,7 +7,8 @@ const generateMJS = (module) => { let text = fs.readFileSync(src, 'utf-8'); replacements.push( - [/const (.+?)\s*=\s*require\(\'(.+)\'\)/ig, 'import $1 from \'$2.mjs\''], + [/const (.+?)\s*=\s*require\(\'\.(.+)\'\)/ig, 'import $1 from \'$2.mjs\''], + [/const (.+?)\s*=\s*require\(\'(.+)\'\)/ig, 'import $1 from \'$2\''], [/module\.exports =/ig, 'export'] ); replacements.forEach(rep => { diff --git a/src/helpers/ua-parser-helpers.d.ts b/src/helpers/ua-parser-helpers.d.ts index c58fc1463..6a9765830 100644 --- a/src/helpers/ua-parser-helpers.d.ts +++ b/src/helpers/ua-parser-helpers.d.ts @@ -7,6 +7,7 @@ import { IResult } from "../main/ua-parser"; declare function getDeviceVendor(model: string): string | undefined; declare function isAppleSilicon(res: IResult): boolean; declare function isChromeFamily(res: IResult): boolean; +declare function isFromEU(): boolean; declare function isFrozenUA(ua: string): boolean; declare function isStandalonePWA(): boolean; @@ -14,6 +15,7 @@ export { getDeviceVendor, isAppleSilicon, isChromeFamily, + isFromEU, isFrozenUA, isStandalonePWA } \ No newline at end of file diff --git a/src/helpers/ua-parser-helpers.js b/src/helpers/ua-parser-helpers.js index e0729c94d..72116124f 100644 --- a/src/helpers/ua-parser-helpers.js +++ b/src/helpers/ua-parser-helpers.js @@ -9,6 +9,7 @@ const { CPU, OS, Engine } = require('../enums/ua-parser-enums'); const { UAParser } = require('../main/ua-parser'); +const { isFromEU } = require('detect-europe-js'); const getDeviceVendor = (model) => UAParser(`Mozilla/5.0 (Linux; Android 10; ${model}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.0.0 Safari/537.36`).device.vendor; @@ -50,6 +51,7 @@ module.exports = { getDeviceVendor, isAppleSilicon, isChromeFamily, + isFromEU, isFrozenUA, isStandalonePWA } \ No newline at end of file From 3de1961892af54985e991ee356453e300ab57e75 Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Sat, 14 Sep 2024 13:13:36 +0700 Subject: [PATCH 31/64] Add new helper method: `isElectron()` to detect whether the current window is running inside Electron --- src/helpers/ua-parser-helpers.d.ts | 2 ++ src/helpers/ua-parser-helpers.js | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/src/helpers/ua-parser-helpers.d.ts b/src/helpers/ua-parser-helpers.d.ts index 6a9765830..e8dd9d358 100644 --- a/src/helpers/ua-parser-helpers.d.ts +++ b/src/helpers/ua-parser-helpers.d.ts @@ -7,6 +7,7 @@ import { IResult } from "../main/ua-parser"; declare function getDeviceVendor(model: string): string | undefined; declare function isAppleSilicon(res: IResult): boolean; declare function isChromeFamily(res: IResult): boolean; +declare function isElectron(): boolean; declare function isFromEU(): boolean; declare function isFrozenUA(ua: string): boolean; declare function isStandalonePWA(): boolean; @@ -15,6 +16,7 @@ export { getDeviceVendor, isAppleSilicon, isChromeFamily, + isElectron, isFromEU, isFrozenUA, isStandalonePWA diff --git a/src/helpers/ua-parser-helpers.js b/src/helpers/ua-parser-helpers.js index 72116124f..8582fe5b4 100644 --- a/src/helpers/ua-parser-helpers.js +++ b/src/helpers/ua-parser-helpers.js @@ -35,6 +35,9 @@ const isAppleSilicon = (res) => { const isChromeFamily = (res) => res.engine.is(Engine.BLINK); +const isElectron = () => !!(process?.versions?.hasOwnProperty('electron') || // node.js + / electron\//i.test(navigator?.userAgent)); // browser + 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); const isStandalonePWA = () => window && (window.matchMedia('(display-mode: standalone)').matches || @@ -51,6 +54,7 @@ module.exports = { getDeviceVendor, isAppleSilicon, isChromeFamily, + isElectron, isFromEU, isFrozenUA, isStandalonePWA From 391b8087fbfcad6fd2e763dc5159aabcfe805b2a Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Fri, 20 Sep 2024 09:26:39 +0700 Subject: [PATCH 32/64] Fix #747: Python Request mistakenly identified as Meta Quest --- src/main/ua-parser.js | 2 +- test/specs/device-all.json | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/ua-parser.js b/src/main/ua-parser.js index 36c9e787c..59ac6553d 100755 --- a/src/main/ua-parser.js +++ b/src/main/ua-parser.js @@ -761,7 +761,7 @@ ], [MODEL, [VENDOR, GOOGLE], [TYPE, XR]], [ /(pico) (4|neo3(?: link|pro)?)/i // Pico ], [VENDOR, MODEL, [TYPE, XR]], [ - /(quest( \d| pro)?)/i // Oculus Quest + /; (quest( \d| pro)?)/i // Oculus Quest ], [MODEL, [VENDOR, FACEBOOK], [TYPE, XR]], [ /////////////////// diff --git a/test/specs/device-all.json b/test/specs/device-all.json index c85860024..d8ef0bb91 100644 --- a/test/specs/device-all.json +++ b/test/specs/device-all.json @@ -1484,6 +1484,15 @@ "type": "xr" } }, + { + "desc": "Issue #747", + "ua": "python-requests/2.25.1", + "expect": { + "vendor": "undefined", + "model": "undefined", + "type": "undefined" + } + }, { "desc": "OnePlus One", "ua": "Mozilla/5.0 (Linux; Android 4.4.4; A0001 Build/KTU84Q) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.59 Mobile Safari/537.36", From f00fb3a2e239722d123edf811754e8cb918a6ed7 Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Sun, 22 Sep 2024 13:46:17 +0700 Subject: [PATCH 33/64] [submodule:extensions] Restore `Bots` as an umbrella term for any kind of automated browsers: `CLIs`, `Crawlers`, `Fetchers`, and `Modules` --- src/extensions/ua-parser-extensions.d.ts | 1 + src/extensions/ua-parser-extensions.js | 14 ++++++++++++++ test/mocha-test-extension.js | 6 ++++-- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/extensions/ua-parser-extensions.d.ts b/src/extensions/ua-parser-extensions.d.ts index 5d6f300de..e432b21f6 100644 --- a/src/extensions/ua-parser-extensions.d.ts +++ b/src/extensions/ua-parser-extensions.d.ts @@ -4,6 +4,7 @@ import type { UAParserExt } from "../main/ua-parser"; +export const Bots: UAParserExt; export const CLIs: UAParserExt; export const Crawlers: UAParserExt; export const ExtraDevices: UAParserExt; diff --git a/src/extensions/ua-parser-extensions.js b/src/extensions/ua-parser-extensions.js index a85052c37..a1efa2491 100644 --- a/src/extensions/ua-parser-extensions.js +++ b/src/extensions/ua-parser-extensions.js @@ -342,7 +342,21 @@ const Modules = Object.freeze({ ] }); +////////// +// BOTS +///////// + +const Bots = Object.freeze({ + browser : [ + ...CLIs.browser, + ...Crawlers.browser, + ...Fetchers.browser, + ...Modules.browser + ] +}); + module.exports = { + Bots, CLIs, Crawlers, ExtraDevices, diff --git a/test/mocha-test-extension.js b/test/mocha-test-extension.js index c2ee99d89..2f81a5c2f 100644 --- a/test/mocha-test-extension.js +++ b/test/mocha-test-extension.js @@ -9,7 +9,7 @@ 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'); +const { Bots, CLIs, Crawlers, Emails, Fetchers, Modules } = require('../src/extensions/ua-parser-extensions'); describe('Extensions', () => { [ @@ -38,6 +38,8 @@ describe('Extensions', () => { 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)'; + assert.equal(UAParser(scrapy, Bots).browser.name, 'Scrapy'); + 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"}); @@ -67,7 +69,7 @@ describe('Merge', () => { }); }); -describe('Testing regexes', () => { +describe('Testing the safety of regexes', () => { let regexes; let code = fs.readFileSync('src/extensions/ua-parser-extensions.js', 'utf8').toString(); From a4c81a5600e8fb30515b8375e24463b5acedaec8 Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Sat, 28 Sep 2024 10:29:40 +0700 Subject: [PATCH 34/64] [submodule:extensions] Add new crawler: OAI-SearchBot (OpenAI's bot for SearchGPT) --- src/extensions/ua-parser-extensions.js | 3 ++- test/specs/browser-crawlers.json | 10 ++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/extensions/ua-parser-extensions.js b/src/extensions/ua-parser-extensions.js index a1efa2491..a50145daf 100644 --- a/src/extensions/ua-parser-extensions.js +++ b/src/extensions/ua-parser-extensions.js @@ -49,8 +49,9 @@ const Crawlers = Object.freeze({ // FacebookBot - https://developers.facebook.com/docs/sharing/bot/ // GPTBot - https://platform.openai.com/docs/gptbot // MJ12bot - https://mj12bot.com/ + // OpenAI Search - https://platform.openai.com/docs/bots // SemrushBot - http://www.semrush.com/bot.html - /((?:ahrefs|amazon|apple|bing|dot|duckduck|facebook|gpt|mj12|semrush)bot)\/([\w\.]+)/i, + /((?:ahrefs|amazon|apple|bing|dot|duckduck|facebook|gpt|mj12|oai-search|semrush)bot)\/([\w\.]+)/i, // Baiduspider https://help.baidu.com/question?prod_id=99&class=0&id=3001 /(baiduspider)[-imagevdonsfcpr]{0,6}\/([\w\.]+)/i, diff --git a/test/specs/browser-crawlers.json b/test/specs/browser-crawlers.json index b205ebf83..45e25ad18 100644 --- a/test/specs/browser-crawlers.json +++ b/test/specs/browser-crawlers.json @@ -129,6 +129,16 @@ "type" : "crawler" } }, + { + "desc" : "OpenAI Search", + "ua" : "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko); compatible; OAI-SearchBot/1.0; +https://openai.com/searchbot", + "expect" : + { + "name" : "OAI-SearchBot", + "version" : "1.0", + "type" : "crawler" + } + }, { "desc" : "SemrushBot", "ua" : "Mozilla/5.0 (compatible; SemrushBot/7~bl; +http://www.semrush.com/bot.html)", From 5b7fe9141b67b3121ca1012accc34954012a13c0 Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Thu, 17 Oct 2024 15:43:06 +0700 Subject: [PATCH 35/64] [submodule:enums] Replace underscore with quotation --- src/enums/ua-parser-enums.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/enums/ua-parser-enums.js b/src/enums/ua-parser-enums.js index e8c638efb..9f58b6158 100644 --- a/src/enums/ua-parser-enums.js +++ b/src/enums/ua-parser-enums.js @@ -8,8 +8,8 @@ /*jshint esversion: 6 */ const Browser = Object.freeze({ - _2345_EXPLORER: '2345Explorer', - _360: '360 Browser', + '2345_EXPLORER': '2345Explorer', + '360': '360 Browser', ALIPAY: 'Alipay', AMAYA: 'Amaya', ANDROID: 'Android Browser', @@ -158,6 +158,7 @@ const BrowserType = Object.freeze({ }); const CPU = Object.freeze({ + '68K': '68k', ARM : 'arm', ARM_64: 'arm64', ARM_HF: 'armhf', @@ -168,7 +169,6 @@ const CPU = Object.freeze({ IRIX_64: 'irix64', MIPS: 'mips', MIPS_64: 'mips64', - M68K: '68k', PA_RISC: 'pa-risc', PPC: 'ppc', SPARC: 'sparc', From 7201755f5fbe433fb5f1284da046b0f01e684f25 Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Fri, 18 Oct 2024 21:34:07 +0700 Subject: [PATCH 36/64] Fix #719 - Add icons --- src/icons/mono/LICENSE.md | 3 +++ src/icons/mono/browser/alipay.svg | 1 + src/icons/mono/browser/android-browser.svg | 1 + src/icons/mono/browser/avast-secure-browser.svg | 1 + src/icons/mono/browser/baidu-browser.svg | 1 + src/icons/mono/browser/brave.svg | 1 + src/icons/mono/browser/chrome-headless.svg | 1 + src/icons/mono/browser/chrome-webview.svg | 1 + src/icons/mono/browser/chrome.svg | 1 + src/icons/mono/browser/chromium.svg | 1 + src/icons/mono/browser/duckduckgo.svg | 1 + src/icons/mono/browser/edge.svg | 1 + src/icons/mono/browser/electron.svg | 1 + src/icons/mono/browser/facebook.svg | 1 + src/icons/mono/browser/firefox-focus.svg | 1 + src/icons/mono/browser/firefox-reality.svg | 1 + src/icons/mono/browser/firefox.svg | 1 + src/icons/mono/browser/gsa.svg | 1 + src/icons/mono/browser/huawei-browser.svg | 1 + src/icons/mono/browser/icecat.svg | 1 + src/icons/mono/browser/ie.svg | 1 + src/icons/mono/browser/instagram.svg | 1 + src/icons/mono/browser/jasmine.svg | 1 + src/icons/mono/browser/kakaotalk.svg | 1 + src/icons/mono/browser/klarna.svg | 1 + src/icons/mono/browser/line.svg | 1 + src/icons/mono/browser/linkedin.svg | 1 + src/icons/mono/browser/miui-browser.svg | 1 + src/icons/mono/browser/mobile-chrome.svg | 1 + src/icons/mono/browser/mobile-firefox.svg | 1 + src/icons/mono/browser/mobile-safari.svg | 1 + src/icons/mono/browser/mozilla.svg | 1 + src/icons/mono/browser/naver.svg | 1 + src/icons/mono/browser/nokia-browser.svg | 1 + src/icons/mono/browser/oculus-browser.svg | 1 + src/icons/mono/browser/opera-coast.svg | 1 + src/icons/mono/browser/opera-gx.svg | 1 + src/icons/mono/browser/opera-mini.svg | 1 + src/icons/mono/browser/opera-mobi.svg | 1 + src/icons/mono/browser/opera-tablet.svg | 1 + src/icons/mono/browser/opera-touch.svg | 1 + src/icons/mono/browser/opera.svg | 1 + src/icons/mono/browser/qqbrowser.svg | 1 + src/icons/mono/browser/qqbrowserlite.svg | 1 + src/icons/mono/browser/safari.svg | 1 + src/icons/mono/browser/sailfish-browser.svg | 1 + src/icons/mono/browser/samsung-internet.svg | 1 + src/icons/mono/browser/smart-lenovo-browser.svg | 1 + src/icons/mono/browser/snapchat.svg | 1 + src/icons/mono/browser/sogou-explorer.svg | 1 + src/icons/mono/browser/sogou-mobile.svg | 1 + src/icons/mono/browser/tesla.svg | 1 + src/icons/mono/browser/tiktok.svg | 1 + src/icons/mono/browser/twitter.svg | 1 + src/icons/mono/browser/vivaldi.svg | 1 + src/icons/mono/browser/vivo-browser.svg | 1 + src/icons/mono/browser/wechat.svg | 1 + src/icons/mono/browser/weibo.svg | 1 + src/icons/mono/browser/yandex.svg | 1 + src/icons/mono/device/acer.svg | 1 + src/icons/mono/device/amazon.svg | 1 + src/icons/mono/device/apple.svg | 1 + src/icons/mono/device/asus.svg | 1 + src/icons/mono/device/att.svg | 1 + src/icons/mono/device/blackberry.svg | 1 + src/icons/mono/device/dell.svg | 1 + src/icons/mono/device/facebook.svg | 1 + src/icons/mono/device/fairphone.svg | 1 + src/icons/mono/device/google.svg | 1 + src/icons/mono/device/hp.svg | 1 + src/icons/mono/device/huawei.svg | 1 + src/icons/mono/device/lenovo.svg | 1 + src/icons/mono/device/lg.svg | 1 + src/icons/mono/device/meizu.svg | 1 + src/icons/mono/device/microsoft.svg | 1 + src/icons/mono/device/motorola.svg | 1 + src/icons/mono/device/nintendo.svg | 1 + src/icons/mono/device/nokia.svg | 1 + src/icons/mono/device/nvidia.svg | 1 + src/icons/mono/device/oneplus.svg | 1 + src/icons/mono/device/oppo.svg | 1 + src/icons/mono/device/panasonic.svg | 1 + src/icons/mono/device/roku.svg | 1 + src/icons/mono/device/samsung.svg | 1 + src/icons/mono/device/siemens.svg | 1 + src/icons/mono/device/sony.svg | 1 + src/icons/mono/device/tesla.svg | 1 + src/icons/mono/device/vivo.svg | 1 + src/icons/mono/device/vodafone.svg | 1 + src/icons/mono/device/xiaomi.svg | 1 + src/icons/mono/device/zebra.svg | 1 + src/icons/mono/os/android.svg | 1 + src/icons/mono/os/arch.svg | 1 + src/icons/mono/os/blackberry.svg | 1 + src/icons/mono/os/centos.svg | 1 + src/icons/mono/os/chrome_os.svg | 1 + src/icons/mono/os/chromecast.svg | 1 + src/icons/mono/os/debian.svg | 1 + src/icons/mono/os/deepin.svg | 1 + src/icons/mono/os/elementary_os.svg | 1 + src/icons/mono/os/fedora.svg | 1 + src/icons/mono/os/firefox.svg | 1 + src/icons/mono/os/freebsd.svg | 1 + src/icons/mono/os/gentoo.svg | 1 + src/icons/mono/os/gnu.svg | 1 + src/icons/mono/os/harmonyos.svg | 1 + src/icons/mono/os/ios.svg | 1 + src/icons/mono/os/kaios.svg | 1 + src/icons/mono/os/linux.svg | 1 + src/icons/mono/os/macos.svg | 1 + src/icons/mono/os/manjaro.svg | 1 + src/icons/mono/os/mint.svg | 1 + src/icons/mono/os/netbsd.svg | 1 + src/icons/mono/os/nintendo.svg | 1 + src/icons/mono/os/openbsd.svg | 1 + src/icons/mono/os/playstation.svg | 1 + src/icons/mono/os/raspbian.svg | 1 + src/icons/mono/os/redhat.svg | 1 + src/icons/mono/os/sailfish.svg | 1 + src/icons/mono/os/slackware.svg | 1 + src/icons/mono/os/suse.svg | 1 + src/icons/mono/os/ubuntu.svg | 1 + src/icons/mono/os/windows.svg | 1 + src/icons/mono/os/xbox.svg | 1 + src/icons/ua-parser-icons.js | 0 125 files changed, 126 insertions(+) create mode 100644 src/icons/mono/LICENSE.md create mode 100644 src/icons/mono/browser/alipay.svg create mode 100644 src/icons/mono/browser/android-browser.svg create mode 100644 src/icons/mono/browser/avast-secure-browser.svg create mode 100644 src/icons/mono/browser/baidu-browser.svg create mode 100644 src/icons/mono/browser/brave.svg create mode 100644 src/icons/mono/browser/chrome-headless.svg create mode 100644 src/icons/mono/browser/chrome-webview.svg create mode 100644 src/icons/mono/browser/chrome.svg create mode 100644 src/icons/mono/browser/chromium.svg create mode 100644 src/icons/mono/browser/duckduckgo.svg create mode 100644 src/icons/mono/browser/edge.svg create mode 100644 src/icons/mono/browser/electron.svg create mode 100644 src/icons/mono/browser/facebook.svg create mode 100644 src/icons/mono/browser/firefox-focus.svg create mode 100644 src/icons/mono/browser/firefox-reality.svg create mode 100644 src/icons/mono/browser/firefox.svg create mode 100644 src/icons/mono/browser/gsa.svg create mode 100644 src/icons/mono/browser/huawei-browser.svg create mode 100644 src/icons/mono/browser/icecat.svg create mode 100644 src/icons/mono/browser/ie.svg create mode 100644 src/icons/mono/browser/instagram.svg create mode 100644 src/icons/mono/browser/jasmine.svg create mode 100644 src/icons/mono/browser/kakaotalk.svg create mode 100644 src/icons/mono/browser/klarna.svg create mode 100644 src/icons/mono/browser/line.svg create mode 100644 src/icons/mono/browser/linkedin.svg create mode 100644 src/icons/mono/browser/miui-browser.svg create mode 100644 src/icons/mono/browser/mobile-chrome.svg create mode 100644 src/icons/mono/browser/mobile-firefox.svg create mode 100644 src/icons/mono/browser/mobile-safari.svg create mode 100644 src/icons/mono/browser/mozilla.svg create mode 100644 src/icons/mono/browser/naver.svg create mode 100644 src/icons/mono/browser/nokia-browser.svg create mode 100644 src/icons/mono/browser/oculus-browser.svg create mode 100644 src/icons/mono/browser/opera-coast.svg create mode 100644 src/icons/mono/browser/opera-gx.svg create mode 100644 src/icons/mono/browser/opera-mini.svg create mode 100644 src/icons/mono/browser/opera-mobi.svg create mode 100644 src/icons/mono/browser/opera-tablet.svg create mode 100644 src/icons/mono/browser/opera-touch.svg create mode 100644 src/icons/mono/browser/opera.svg create mode 100644 src/icons/mono/browser/qqbrowser.svg create mode 100644 src/icons/mono/browser/qqbrowserlite.svg create mode 100644 src/icons/mono/browser/safari.svg create mode 100644 src/icons/mono/browser/sailfish-browser.svg create mode 100644 src/icons/mono/browser/samsung-internet.svg create mode 100644 src/icons/mono/browser/smart-lenovo-browser.svg create mode 100644 src/icons/mono/browser/snapchat.svg create mode 100644 src/icons/mono/browser/sogou-explorer.svg create mode 100644 src/icons/mono/browser/sogou-mobile.svg create mode 100644 src/icons/mono/browser/tesla.svg create mode 100644 src/icons/mono/browser/tiktok.svg create mode 100644 src/icons/mono/browser/twitter.svg create mode 100644 src/icons/mono/browser/vivaldi.svg create mode 100644 src/icons/mono/browser/vivo-browser.svg create mode 100644 src/icons/mono/browser/wechat.svg create mode 100644 src/icons/mono/browser/weibo.svg create mode 100644 src/icons/mono/browser/yandex.svg create mode 100644 src/icons/mono/device/acer.svg create mode 100644 src/icons/mono/device/amazon.svg create mode 100644 src/icons/mono/device/apple.svg create mode 100644 src/icons/mono/device/asus.svg create mode 100644 src/icons/mono/device/att.svg create mode 100644 src/icons/mono/device/blackberry.svg create mode 100644 src/icons/mono/device/dell.svg create mode 100644 src/icons/mono/device/facebook.svg create mode 100644 src/icons/mono/device/fairphone.svg create mode 100644 src/icons/mono/device/google.svg create mode 100644 src/icons/mono/device/hp.svg create mode 100644 src/icons/mono/device/huawei.svg create mode 100644 src/icons/mono/device/lenovo.svg create mode 100644 src/icons/mono/device/lg.svg create mode 100644 src/icons/mono/device/meizu.svg create mode 100644 src/icons/mono/device/microsoft.svg create mode 100644 src/icons/mono/device/motorola.svg create mode 100644 src/icons/mono/device/nintendo.svg create mode 100644 src/icons/mono/device/nokia.svg create mode 100644 src/icons/mono/device/nvidia.svg create mode 100644 src/icons/mono/device/oneplus.svg create mode 100644 src/icons/mono/device/oppo.svg create mode 100644 src/icons/mono/device/panasonic.svg create mode 100644 src/icons/mono/device/roku.svg create mode 100644 src/icons/mono/device/samsung.svg create mode 100644 src/icons/mono/device/siemens.svg create mode 100644 src/icons/mono/device/sony.svg create mode 100644 src/icons/mono/device/tesla.svg create mode 100644 src/icons/mono/device/vivo.svg create mode 100644 src/icons/mono/device/vodafone.svg create mode 100644 src/icons/mono/device/xiaomi.svg create mode 100644 src/icons/mono/device/zebra.svg create mode 100644 src/icons/mono/os/android.svg create mode 100644 src/icons/mono/os/arch.svg create mode 100644 src/icons/mono/os/blackberry.svg create mode 100644 src/icons/mono/os/centos.svg create mode 100644 src/icons/mono/os/chrome_os.svg create mode 100644 src/icons/mono/os/chromecast.svg create mode 100644 src/icons/mono/os/debian.svg create mode 100644 src/icons/mono/os/deepin.svg create mode 100644 src/icons/mono/os/elementary_os.svg create mode 100644 src/icons/mono/os/fedora.svg create mode 100644 src/icons/mono/os/firefox.svg create mode 100644 src/icons/mono/os/freebsd.svg create mode 100644 src/icons/mono/os/gentoo.svg create mode 100644 src/icons/mono/os/gnu.svg create mode 100644 src/icons/mono/os/harmonyos.svg create mode 100644 src/icons/mono/os/ios.svg create mode 100644 src/icons/mono/os/kaios.svg create mode 100644 src/icons/mono/os/linux.svg create mode 100644 src/icons/mono/os/macos.svg create mode 100644 src/icons/mono/os/manjaro.svg create mode 100644 src/icons/mono/os/mint.svg create mode 100644 src/icons/mono/os/netbsd.svg create mode 100644 src/icons/mono/os/nintendo.svg create mode 100644 src/icons/mono/os/openbsd.svg create mode 100644 src/icons/mono/os/playstation.svg create mode 100644 src/icons/mono/os/raspbian.svg create mode 100644 src/icons/mono/os/redhat.svg create mode 100644 src/icons/mono/os/sailfish.svg create mode 100644 src/icons/mono/os/slackware.svg create mode 100644 src/icons/mono/os/suse.svg create mode 100644 src/icons/mono/os/ubuntu.svg create mode 100644 src/icons/mono/os/windows.svg create mode 100644 src/icons/mono/os/xbox.svg create mode 100644 src/icons/ua-parser-icons.js diff --git a/src/icons/mono/LICENSE.md b/src/icons/mono/LICENSE.md new file mode 100644 index 000000000..a4c806be3 --- /dev/null +++ b/src/icons/mono/LICENSE.md @@ -0,0 +1,3 @@ +CC0-1.0 +https://github.com/simple-icons/simple-icons +https://github.com/coreui/coreui-icons \ No newline at end of file diff --git a/src/icons/mono/browser/alipay.svg b/src/icons/mono/browser/alipay.svg new file mode 100644 index 000000000..30fa27f22 --- /dev/null +++ b/src/icons/mono/browser/alipay.svg @@ -0,0 +1 @@ +Alipay \ No newline at end of file diff --git a/src/icons/mono/browser/android-browser.svg b/src/icons/mono/browser/android-browser.svg new file mode 100644 index 000000000..2482150a6 --- /dev/null +++ b/src/icons/mono/browser/android-browser.svg @@ -0,0 +1 @@ +Android Browser \ No newline at end of file diff --git a/src/icons/mono/browser/avast-secure-browser.svg b/src/icons/mono/browser/avast-secure-browser.svg new file mode 100644 index 000000000..b77658a1a --- /dev/null +++ b/src/icons/mono/browser/avast-secure-browser.svg @@ -0,0 +1 @@ +Avast Secure Browser \ No newline at end of file diff --git a/src/icons/mono/browser/baidu-browser.svg b/src/icons/mono/browser/baidu-browser.svg new file mode 100644 index 000000000..f7f0dd163 --- /dev/null +++ b/src/icons/mono/browser/baidu-browser.svg @@ -0,0 +1 @@ +Baidu Browser \ No newline at end of file diff --git a/src/icons/mono/browser/brave.svg b/src/icons/mono/browser/brave.svg new file mode 100644 index 000000000..fa798a452 --- /dev/null +++ b/src/icons/mono/browser/brave.svg @@ -0,0 +1 @@ +Brave \ No newline at end of file diff --git a/src/icons/mono/browser/chrome-headless.svg b/src/icons/mono/browser/chrome-headless.svg new file mode 100644 index 000000000..5fc57d212 --- /dev/null +++ b/src/icons/mono/browser/chrome-headless.svg @@ -0,0 +1 @@ +Chrome Headless \ No newline at end of file diff --git a/src/icons/mono/browser/chrome-webview.svg b/src/icons/mono/browser/chrome-webview.svg new file mode 100644 index 000000000..38b45e32c --- /dev/null +++ b/src/icons/mono/browser/chrome-webview.svg @@ -0,0 +1 @@ +Chrome Webview \ No newline at end of file diff --git a/src/icons/mono/browser/chrome.svg b/src/icons/mono/browser/chrome.svg new file mode 100644 index 000000000..3404d6e21 --- /dev/null +++ b/src/icons/mono/browser/chrome.svg @@ -0,0 +1 @@ +Chrome \ No newline at end of file diff --git a/src/icons/mono/browser/chromium.svg b/src/icons/mono/browser/chromium.svg new file mode 100644 index 000000000..90605418c --- /dev/null +++ b/src/icons/mono/browser/chromium.svg @@ -0,0 +1 @@ +Chromium \ No newline at end of file diff --git a/src/icons/mono/browser/duckduckgo.svg b/src/icons/mono/browser/duckduckgo.svg new file mode 100644 index 000000000..2f466f49e --- /dev/null +++ b/src/icons/mono/browser/duckduckgo.svg @@ -0,0 +1 @@ +DuckDuckGo \ No newline at end of file diff --git a/src/icons/mono/browser/edge.svg b/src/icons/mono/browser/edge.svg new file mode 100644 index 000000000..958a7ed0b --- /dev/null +++ b/src/icons/mono/browser/edge.svg @@ -0,0 +1 @@ +Edge \ No newline at end of file diff --git a/src/icons/mono/browser/electron.svg b/src/icons/mono/browser/electron.svg new file mode 100644 index 000000000..8e855ab30 --- /dev/null +++ b/src/icons/mono/browser/electron.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/mono/browser/facebook.svg b/src/icons/mono/browser/facebook.svg new file mode 100644 index 000000000..f66767e46 --- /dev/null +++ b/src/icons/mono/browser/facebook.svg @@ -0,0 +1 @@ +Facebook \ No newline at end of file diff --git a/src/icons/mono/browser/firefox-focus.svg b/src/icons/mono/browser/firefox-focus.svg new file mode 100644 index 000000000..009082ea8 --- /dev/null +++ b/src/icons/mono/browser/firefox-focus.svg @@ -0,0 +1 @@ +Firefox Focus \ No newline at end of file diff --git a/src/icons/mono/browser/firefox-reality.svg b/src/icons/mono/browser/firefox-reality.svg new file mode 100644 index 000000000..e02dcdfeb --- /dev/null +++ b/src/icons/mono/browser/firefox-reality.svg @@ -0,0 +1 @@ +Firefox Reality \ No newline at end of file diff --git a/src/icons/mono/browser/firefox.svg b/src/icons/mono/browser/firefox.svg new file mode 100644 index 000000000..baace0bad --- /dev/null +++ b/src/icons/mono/browser/firefox.svg @@ -0,0 +1 @@ +Firefox \ No newline at end of file diff --git a/src/icons/mono/browser/gsa.svg b/src/icons/mono/browser/gsa.svg new file mode 100644 index 000000000..753feb554 --- /dev/null +++ b/src/icons/mono/browser/gsa.svg @@ -0,0 +1 @@ +GSA \ No newline at end of file diff --git a/src/icons/mono/browser/huawei-browser.svg b/src/icons/mono/browser/huawei-browser.svg new file mode 100644 index 000000000..200489d3c --- /dev/null +++ b/src/icons/mono/browser/huawei-browser.svg @@ -0,0 +1 @@ +Huawei Browser \ No newline at end of file diff --git a/src/icons/mono/browser/icecat.svg b/src/icons/mono/browser/icecat.svg new file mode 100644 index 000000000..05b01735f --- /dev/null +++ b/src/icons/mono/browser/icecat.svg @@ -0,0 +1 @@ +IceCat \ No newline at end of file diff --git a/src/icons/mono/browser/ie.svg b/src/icons/mono/browser/ie.svg new file mode 100644 index 000000000..f444f15fc --- /dev/null +++ b/src/icons/mono/browser/ie.svg @@ -0,0 +1 @@ +IE \ No newline at end of file diff --git a/src/icons/mono/browser/instagram.svg b/src/icons/mono/browser/instagram.svg new file mode 100644 index 000000000..c0e86b0bf --- /dev/null +++ b/src/icons/mono/browser/instagram.svg @@ -0,0 +1 @@ +Instagram \ No newline at end of file diff --git a/src/icons/mono/browser/jasmine.svg b/src/icons/mono/browser/jasmine.svg new file mode 100644 index 000000000..bda1b3ed9 --- /dev/null +++ b/src/icons/mono/browser/jasmine.svg @@ -0,0 +1 @@ +Jasmine \ No newline at end of file diff --git a/src/icons/mono/browser/kakaotalk.svg b/src/icons/mono/browser/kakaotalk.svg new file mode 100644 index 000000000..8e9f9b123 --- /dev/null +++ b/src/icons/mono/browser/kakaotalk.svg @@ -0,0 +1 @@ +KakaoTalk \ No newline at end of file diff --git a/src/icons/mono/browser/klarna.svg b/src/icons/mono/browser/klarna.svg new file mode 100644 index 000000000..c12c2cef4 --- /dev/null +++ b/src/icons/mono/browser/klarna.svg @@ -0,0 +1 @@ +Klarna \ No newline at end of file diff --git a/src/icons/mono/browser/line.svg b/src/icons/mono/browser/line.svg new file mode 100644 index 000000000..9e4dc98c2 --- /dev/null +++ b/src/icons/mono/browser/line.svg @@ -0,0 +1 @@ +LINE \ No newline at end of file diff --git a/src/icons/mono/browser/linkedin.svg b/src/icons/mono/browser/linkedin.svg new file mode 100644 index 000000000..caa6e69d1 --- /dev/null +++ b/src/icons/mono/browser/linkedin.svg @@ -0,0 +1 @@ +LinkedIn \ No newline at end of file diff --git a/src/icons/mono/browser/miui-browser.svg b/src/icons/mono/browser/miui-browser.svg new file mode 100644 index 000000000..a86433446 --- /dev/null +++ b/src/icons/mono/browser/miui-browser.svg @@ -0,0 +1 @@ +MIUI Browser \ No newline at end of file diff --git a/src/icons/mono/browser/mobile-chrome.svg b/src/icons/mono/browser/mobile-chrome.svg new file mode 100644 index 000000000..cc6792673 --- /dev/null +++ b/src/icons/mono/browser/mobile-chrome.svg @@ -0,0 +1 @@ +Mobile Chrome \ No newline at end of file diff --git a/src/icons/mono/browser/mobile-firefox.svg b/src/icons/mono/browser/mobile-firefox.svg new file mode 100644 index 000000000..b00ccef29 --- /dev/null +++ b/src/icons/mono/browser/mobile-firefox.svg @@ -0,0 +1 @@ +Mobile Firefox \ No newline at end of file diff --git a/src/icons/mono/browser/mobile-safari.svg b/src/icons/mono/browser/mobile-safari.svg new file mode 100644 index 000000000..ac9eab67b --- /dev/null +++ b/src/icons/mono/browser/mobile-safari.svg @@ -0,0 +1 @@ +Mobile Safari \ No newline at end of file diff --git a/src/icons/mono/browser/mozilla.svg b/src/icons/mono/browser/mozilla.svg new file mode 100644 index 000000000..507eb6695 --- /dev/null +++ b/src/icons/mono/browser/mozilla.svg @@ -0,0 +1 @@ +Mozilla \ No newline at end of file diff --git a/src/icons/mono/browser/naver.svg b/src/icons/mono/browser/naver.svg new file mode 100644 index 000000000..611ad4b64 --- /dev/null +++ b/src/icons/mono/browser/naver.svg @@ -0,0 +1 @@ +Naver \ No newline at end of file diff --git a/src/icons/mono/browser/nokia-browser.svg b/src/icons/mono/browser/nokia-browser.svg new file mode 100644 index 000000000..bf4b85c6b --- /dev/null +++ b/src/icons/mono/browser/nokia-browser.svg @@ -0,0 +1 @@ +Nokia Browser \ No newline at end of file diff --git a/src/icons/mono/browser/oculus-browser.svg b/src/icons/mono/browser/oculus-browser.svg new file mode 100644 index 000000000..a0d272f06 --- /dev/null +++ b/src/icons/mono/browser/oculus-browser.svg @@ -0,0 +1 @@ +Oculus Browser \ No newline at end of file diff --git a/src/icons/mono/browser/opera-coast.svg b/src/icons/mono/browser/opera-coast.svg new file mode 100644 index 000000000..f7c88c193 --- /dev/null +++ b/src/icons/mono/browser/opera-coast.svg @@ -0,0 +1 @@ +Opera Coast \ No newline at end of file diff --git a/src/icons/mono/browser/opera-gx.svg b/src/icons/mono/browser/opera-gx.svg new file mode 100644 index 000000000..b560822cb --- /dev/null +++ b/src/icons/mono/browser/opera-gx.svg @@ -0,0 +1 @@ +Opera GX \ No newline at end of file diff --git a/src/icons/mono/browser/opera-mini.svg b/src/icons/mono/browser/opera-mini.svg new file mode 100644 index 000000000..1cc64857a --- /dev/null +++ b/src/icons/mono/browser/opera-mini.svg @@ -0,0 +1 @@ +Opera Mini \ No newline at end of file diff --git a/src/icons/mono/browser/opera-mobi.svg b/src/icons/mono/browser/opera-mobi.svg new file mode 100644 index 000000000..dfc102673 --- /dev/null +++ b/src/icons/mono/browser/opera-mobi.svg @@ -0,0 +1 @@ +Opera Mobi \ No newline at end of file diff --git a/src/icons/mono/browser/opera-tablet.svg b/src/icons/mono/browser/opera-tablet.svg new file mode 100644 index 000000000..d47eea29c --- /dev/null +++ b/src/icons/mono/browser/opera-tablet.svg @@ -0,0 +1 @@ +Opera Tablet \ No newline at end of file diff --git a/src/icons/mono/browser/opera-touch.svg b/src/icons/mono/browser/opera-touch.svg new file mode 100644 index 000000000..50211d4de --- /dev/null +++ b/src/icons/mono/browser/opera-touch.svg @@ -0,0 +1 @@ +Opera Touch \ No newline at end of file diff --git a/src/icons/mono/browser/opera.svg b/src/icons/mono/browser/opera.svg new file mode 100644 index 000000000..d1194ee24 --- /dev/null +++ b/src/icons/mono/browser/opera.svg @@ -0,0 +1 @@ +Opera \ No newline at end of file diff --git a/src/icons/mono/browser/qqbrowser.svg b/src/icons/mono/browser/qqbrowser.svg new file mode 100644 index 000000000..6a94a49f7 --- /dev/null +++ b/src/icons/mono/browser/qqbrowser.svg @@ -0,0 +1 @@ +QQBrowser \ No newline at end of file diff --git a/src/icons/mono/browser/qqbrowserlite.svg b/src/icons/mono/browser/qqbrowserlite.svg new file mode 100644 index 000000000..d4ccef286 --- /dev/null +++ b/src/icons/mono/browser/qqbrowserlite.svg @@ -0,0 +1 @@ +QQBrowserLite \ No newline at end of file diff --git a/src/icons/mono/browser/safari.svg b/src/icons/mono/browser/safari.svg new file mode 100644 index 000000000..5d1543889 --- /dev/null +++ b/src/icons/mono/browser/safari.svg @@ -0,0 +1 @@ +Safari \ No newline at end of file diff --git a/src/icons/mono/browser/sailfish-browser.svg b/src/icons/mono/browser/sailfish-browser.svg new file mode 100644 index 000000000..0884da1c3 --- /dev/null +++ b/src/icons/mono/browser/sailfish-browser.svg @@ -0,0 +1 @@ +Sailfish Browser \ No newline at end of file diff --git a/src/icons/mono/browser/samsung-internet.svg b/src/icons/mono/browser/samsung-internet.svg new file mode 100644 index 000000000..15e89529f --- /dev/null +++ b/src/icons/mono/browser/samsung-internet.svg @@ -0,0 +1 @@ +Samsung Internet \ No newline at end of file diff --git a/src/icons/mono/browser/smart-lenovo-browser.svg b/src/icons/mono/browser/smart-lenovo-browser.svg new file mode 100644 index 000000000..e9be1500a --- /dev/null +++ b/src/icons/mono/browser/smart-lenovo-browser.svg @@ -0,0 +1 @@ +Smart Lenovo Browser \ No newline at end of file diff --git a/src/icons/mono/browser/snapchat.svg b/src/icons/mono/browser/snapchat.svg new file mode 100644 index 000000000..3110fbada --- /dev/null +++ b/src/icons/mono/browser/snapchat.svg @@ -0,0 +1 @@ +Snapchat \ No newline at end of file diff --git a/src/icons/mono/browser/sogou-explorer.svg b/src/icons/mono/browser/sogou-explorer.svg new file mode 100644 index 000000000..1449ecb61 --- /dev/null +++ b/src/icons/mono/browser/sogou-explorer.svg @@ -0,0 +1 @@ +Sogou Explorer \ No newline at end of file diff --git a/src/icons/mono/browser/sogou-mobile.svg b/src/icons/mono/browser/sogou-mobile.svg new file mode 100644 index 000000000..36165fe4c --- /dev/null +++ b/src/icons/mono/browser/sogou-mobile.svg @@ -0,0 +1 @@ +Sogou Mobile \ No newline at end of file diff --git a/src/icons/mono/browser/tesla.svg b/src/icons/mono/browser/tesla.svg new file mode 100644 index 000000000..77e66012d --- /dev/null +++ b/src/icons/mono/browser/tesla.svg @@ -0,0 +1 @@ +Tesla \ No newline at end of file diff --git a/src/icons/mono/browser/tiktok.svg b/src/icons/mono/browser/tiktok.svg new file mode 100644 index 000000000..57ce3ae5d --- /dev/null +++ b/src/icons/mono/browser/tiktok.svg @@ -0,0 +1 @@ +TikTok \ No newline at end of file diff --git a/src/icons/mono/browser/twitter.svg b/src/icons/mono/browser/twitter.svg new file mode 100644 index 000000000..b4aeefd37 --- /dev/null +++ b/src/icons/mono/browser/twitter.svg @@ -0,0 +1 @@ +Twitter \ No newline at end of file diff --git a/src/icons/mono/browser/vivaldi.svg b/src/icons/mono/browser/vivaldi.svg new file mode 100644 index 000000000..167e8ad69 --- /dev/null +++ b/src/icons/mono/browser/vivaldi.svg @@ -0,0 +1 @@ +Vivaldi \ No newline at end of file diff --git a/src/icons/mono/browser/vivo-browser.svg b/src/icons/mono/browser/vivo-browser.svg new file mode 100644 index 000000000..db5270682 --- /dev/null +++ b/src/icons/mono/browser/vivo-browser.svg @@ -0,0 +1 @@ +vivo Browser \ No newline at end of file diff --git a/src/icons/mono/browser/wechat.svg b/src/icons/mono/browser/wechat.svg new file mode 100644 index 000000000..c3eb6c4a6 --- /dev/null +++ b/src/icons/mono/browser/wechat.svg @@ -0,0 +1 @@ +WeChat \ No newline at end of file diff --git a/src/icons/mono/browser/weibo.svg b/src/icons/mono/browser/weibo.svg new file mode 100644 index 000000000..13944085e --- /dev/null +++ b/src/icons/mono/browser/weibo.svg @@ -0,0 +1 @@ +Weibo \ No newline at end of file diff --git a/src/icons/mono/browser/yandex.svg b/src/icons/mono/browser/yandex.svg new file mode 100644 index 000000000..16a76fe16 --- /dev/null +++ b/src/icons/mono/browser/yandex.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/mono/device/acer.svg b/src/icons/mono/device/acer.svg new file mode 100644 index 000000000..ca9b2bbf7 --- /dev/null +++ b/src/icons/mono/device/acer.svg @@ -0,0 +1 @@ +Acer \ No newline at end of file diff --git a/src/icons/mono/device/amazon.svg b/src/icons/mono/device/amazon.svg new file mode 100644 index 000000000..70316babd --- /dev/null +++ b/src/icons/mono/device/amazon.svg @@ -0,0 +1 @@ +Amazon \ No newline at end of file diff --git a/src/icons/mono/device/apple.svg b/src/icons/mono/device/apple.svg new file mode 100644 index 000000000..de4b0d17b --- /dev/null +++ b/src/icons/mono/device/apple.svg @@ -0,0 +1 @@ +Apple \ No newline at end of file diff --git a/src/icons/mono/device/asus.svg b/src/icons/mono/device/asus.svg new file mode 100644 index 000000000..18ef199da --- /dev/null +++ b/src/icons/mono/device/asus.svg @@ -0,0 +1 @@ +ASUS \ No newline at end of file diff --git a/src/icons/mono/device/att.svg b/src/icons/mono/device/att.svg new file mode 100644 index 000000000..166ca3920 --- /dev/null +++ b/src/icons/mono/device/att.svg @@ -0,0 +1 @@ +AT&T \ No newline at end of file diff --git a/src/icons/mono/device/blackberry.svg b/src/icons/mono/device/blackberry.svg new file mode 100644 index 000000000..b0c55837a --- /dev/null +++ b/src/icons/mono/device/blackberry.svg @@ -0,0 +1 @@ +Blackberry \ No newline at end of file diff --git a/src/icons/mono/device/dell.svg b/src/icons/mono/device/dell.svg new file mode 100644 index 000000000..d272bbf6f --- /dev/null +++ b/src/icons/mono/device/dell.svg @@ -0,0 +1 @@ +Dell \ No newline at end of file diff --git a/src/icons/mono/device/facebook.svg b/src/icons/mono/device/facebook.svg new file mode 100644 index 000000000..f66767e46 --- /dev/null +++ b/src/icons/mono/device/facebook.svg @@ -0,0 +1 @@ +Facebook \ No newline at end of file diff --git a/src/icons/mono/device/fairphone.svg b/src/icons/mono/device/fairphone.svg new file mode 100644 index 000000000..3262e30dc --- /dev/null +++ b/src/icons/mono/device/fairphone.svg @@ -0,0 +1 @@ +Fairphone \ No newline at end of file diff --git a/src/icons/mono/device/google.svg b/src/icons/mono/device/google.svg new file mode 100644 index 000000000..2eaf91554 --- /dev/null +++ b/src/icons/mono/device/google.svg @@ -0,0 +1 @@ +Google \ No newline at end of file diff --git a/src/icons/mono/device/hp.svg b/src/icons/mono/device/hp.svg new file mode 100644 index 000000000..04b5f0ef8 --- /dev/null +++ b/src/icons/mono/device/hp.svg @@ -0,0 +1 @@ +HP \ No newline at end of file diff --git a/src/icons/mono/device/huawei.svg b/src/icons/mono/device/huawei.svg new file mode 100644 index 000000000..0c72bab82 --- /dev/null +++ b/src/icons/mono/device/huawei.svg @@ -0,0 +1 @@ +Huawei \ No newline at end of file diff --git a/src/icons/mono/device/lenovo.svg b/src/icons/mono/device/lenovo.svg new file mode 100644 index 000000000..c03719a43 --- /dev/null +++ b/src/icons/mono/device/lenovo.svg @@ -0,0 +1 @@ +Lenovo \ No newline at end of file diff --git a/src/icons/mono/device/lg.svg b/src/icons/mono/device/lg.svg new file mode 100644 index 000000000..5eedc7978 --- /dev/null +++ b/src/icons/mono/device/lg.svg @@ -0,0 +1 @@ +LG \ No newline at end of file diff --git a/src/icons/mono/device/meizu.svg b/src/icons/mono/device/meizu.svg new file mode 100644 index 000000000..8f903f6dc --- /dev/null +++ b/src/icons/mono/device/meizu.svg @@ -0,0 +1 @@ +Meizu \ No newline at end of file diff --git a/src/icons/mono/device/microsoft.svg b/src/icons/mono/device/microsoft.svg new file mode 100644 index 000000000..eeacf2520 --- /dev/null +++ b/src/icons/mono/device/microsoft.svg @@ -0,0 +1 @@ +Microsoft \ No newline at end of file diff --git a/src/icons/mono/device/motorola.svg b/src/icons/mono/device/motorola.svg new file mode 100644 index 000000000..3e744bda2 --- /dev/null +++ b/src/icons/mono/device/motorola.svg @@ -0,0 +1 @@ +Motorola \ No newline at end of file diff --git a/src/icons/mono/device/nintendo.svg b/src/icons/mono/device/nintendo.svg new file mode 100644 index 000000000..5cad9642f --- /dev/null +++ b/src/icons/mono/device/nintendo.svg @@ -0,0 +1 @@ +Nintendo \ No newline at end of file diff --git a/src/icons/mono/device/nokia.svg b/src/icons/mono/device/nokia.svg new file mode 100644 index 000000000..a4a21137e --- /dev/null +++ b/src/icons/mono/device/nokia.svg @@ -0,0 +1 @@ +Nokia \ No newline at end of file diff --git a/src/icons/mono/device/nvidia.svg b/src/icons/mono/device/nvidia.svg new file mode 100644 index 000000000..2c7ff66f8 --- /dev/null +++ b/src/icons/mono/device/nvidia.svg @@ -0,0 +1 @@ +NVIDIA \ No newline at end of file diff --git a/src/icons/mono/device/oneplus.svg b/src/icons/mono/device/oneplus.svg new file mode 100644 index 000000000..11c3131ad --- /dev/null +++ b/src/icons/mono/device/oneplus.svg @@ -0,0 +1 @@ +OnePlus \ No newline at end of file diff --git a/src/icons/mono/device/oppo.svg b/src/icons/mono/device/oppo.svg new file mode 100644 index 000000000..b886af3e7 --- /dev/null +++ b/src/icons/mono/device/oppo.svg @@ -0,0 +1 @@ +OPPO \ No newline at end of file diff --git a/src/icons/mono/device/panasonic.svg b/src/icons/mono/device/panasonic.svg new file mode 100644 index 000000000..e5902436c --- /dev/null +++ b/src/icons/mono/device/panasonic.svg @@ -0,0 +1 @@ +Panasonic \ No newline at end of file diff --git a/src/icons/mono/device/roku.svg b/src/icons/mono/device/roku.svg new file mode 100644 index 000000000..17dde5e36 --- /dev/null +++ b/src/icons/mono/device/roku.svg @@ -0,0 +1 @@ +Roku \ No newline at end of file diff --git a/src/icons/mono/device/samsung.svg b/src/icons/mono/device/samsung.svg new file mode 100644 index 000000000..627cbf2c1 --- /dev/null +++ b/src/icons/mono/device/samsung.svg @@ -0,0 +1 @@ +Samsung \ No newline at end of file diff --git a/src/icons/mono/device/siemens.svg b/src/icons/mono/device/siemens.svg new file mode 100644 index 000000000..ec60e7b17 --- /dev/null +++ b/src/icons/mono/device/siemens.svg @@ -0,0 +1 @@ +Siemens \ No newline at end of file diff --git a/src/icons/mono/device/sony.svg b/src/icons/mono/device/sony.svg new file mode 100644 index 000000000..38d17e13d --- /dev/null +++ b/src/icons/mono/device/sony.svg @@ -0,0 +1 @@ +Sony \ No newline at end of file diff --git a/src/icons/mono/device/tesla.svg b/src/icons/mono/device/tesla.svg new file mode 100644 index 000000000..77e66012d --- /dev/null +++ b/src/icons/mono/device/tesla.svg @@ -0,0 +1 @@ +Tesla \ No newline at end of file diff --git a/src/icons/mono/device/vivo.svg b/src/icons/mono/device/vivo.svg new file mode 100644 index 000000000..0591ac425 --- /dev/null +++ b/src/icons/mono/device/vivo.svg @@ -0,0 +1 @@ +vivo \ No newline at end of file diff --git a/src/icons/mono/device/vodafone.svg b/src/icons/mono/device/vodafone.svg new file mode 100644 index 000000000..f882e2fe0 --- /dev/null +++ b/src/icons/mono/device/vodafone.svg @@ -0,0 +1 @@ +Vodafone \ No newline at end of file diff --git a/src/icons/mono/device/xiaomi.svg b/src/icons/mono/device/xiaomi.svg new file mode 100644 index 000000000..f08eae5bd --- /dev/null +++ b/src/icons/mono/device/xiaomi.svg @@ -0,0 +1 @@ +Xiaomi \ No newline at end of file diff --git a/src/icons/mono/device/zebra.svg b/src/icons/mono/device/zebra.svg new file mode 100644 index 000000000..8282e7744 --- /dev/null +++ b/src/icons/mono/device/zebra.svg @@ -0,0 +1 @@ +Zebra \ No newline at end of file diff --git a/src/icons/mono/os/android.svg b/src/icons/mono/os/android.svg new file mode 100644 index 000000000..3f44ef6ba --- /dev/null +++ b/src/icons/mono/os/android.svg @@ -0,0 +1 @@ +Android \ No newline at end of file diff --git a/src/icons/mono/os/arch.svg b/src/icons/mono/os/arch.svg new file mode 100644 index 000000000..a331ef91d --- /dev/null +++ b/src/icons/mono/os/arch.svg @@ -0,0 +1 @@ +Arch \ No newline at end of file diff --git a/src/icons/mono/os/blackberry.svg b/src/icons/mono/os/blackberry.svg new file mode 100644 index 000000000..b0c55837a --- /dev/null +++ b/src/icons/mono/os/blackberry.svg @@ -0,0 +1 @@ +Blackberry \ No newline at end of file diff --git a/src/icons/mono/os/centos.svg b/src/icons/mono/os/centos.svg new file mode 100644 index 000000000..3f16a9e00 --- /dev/null +++ b/src/icons/mono/os/centos.svg @@ -0,0 +1 @@ +CentOS \ No newline at end of file diff --git a/src/icons/mono/os/chrome_os.svg b/src/icons/mono/os/chrome_os.svg new file mode 100644 index 000000000..0a282625e --- /dev/null +++ b/src/icons/mono/os/chrome_os.svg @@ -0,0 +1 @@ +Chrome OS \ No newline at end of file diff --git a/src/icons/mono/os/chromecast.svg b/src/icons/mono/os/chromecast.svg new file mode 100644 index 000000000..6b251ed8a --- /dev/null +++ b/src/icons/mono/os/chromecast.svg @@ -0,0 +1 @@ +Chromecast \ No newline at end of file diff --git a/src/icons/mono/os/debian.svg b/src/icons/mono/os/debian.svg new file mode 100644 index 000000000..c983b3245 --- /dev/null +++ b/src/icons/mono/os/debian.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/mono/os/deepin.svg b/src/icons/mono/os/deepin.svg new file mode 100644 index 000000000..2a5fbca2d --- /dev/null +++ b/src/icons/mono/os/deepin.svg @@ -0,0 +1 @@ +deepin \ No newline at end of file diff --git a/src/icons/mono/os/elementary_os.svg b/src/icons/mono/os/elementary_os.svg new file mode 100644 index 000000000..2b4c9515b --- /dev/null +++ b/src/icons/mono/os/elementary_os.svg @@ -0,0 +1 @@ +elementary OS \ No newline at end of file diff --git a/src/icons/mono/os/fedora.svg b/src/icons/mono/os/fedora.svg new file mode 100644 index 000000000..7f461d0e6 --- /dev/null +++ b/src/icons/mono/os/fedora.svg @@ -0,0 +1 @@ +Fedora \ No newline at end of file diff --git a/src/icons/mono/os/firefox.svg b/src/icons/mono/os/firefox.svg new file mode 100644 index 000000000..e7c9fff23 --- /dev/null +++ b/src/icons/mono/os/firefox.svg @@ -0,0 +1 @@ +Firefox \ No newline at end of file diff --git a/src/icons/mono/os/freebsd.svg b/src/icons/mono/os/freebsd.svg new file mode 100644 index 000000000..8febe9d4c --- /dev/null +++ b/src/icons/mono/os/freebsd.svg @@ -0,0 +1 @@ +FreeBSD \ No newline at end of file diff --git a/src/icons/mono/os/gentoo.svg b/src/icons/mono/os/gentoo.svg new file mode 100644 index 000000000..4c48a0227 --- /dev/null +++ b/src/icons/mono/os/gentoo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/mono/os/gnu.svg b/src/icons/mono/os/gnu.svg new file mode 100644 index 000000000..f29f4d7e4 --- /dev/null +++ b/src/icons/mono/os/gnu.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/mono/os/harmonyos.svg b/src/icons/mono/os/harmonyos.svg new file mode 100644 index 000000000..99b8d7e62 --- /dev/null +++ b/src/icons/mono/os/harmonyos.svg @@ -0,0 +1 @@ +HarmonyOS \ No newline at end of file diff --git a/src/icons/mono/os/ios.svg b/src/icons/mono/os/ios.svg new file mode 100644 index 000000000..a16369768 --- /dev/null +++ b/src/icons/mono/os/ios.svg @@ -0,0 +1 @@ +iOS \ No newline at end of file diff --git a/src/icons/mono/os/kaios.svg b/src/icons/mono/os/kaios.svg new file mode 100644 index 000000000..27a0ec770 --- /dev/null +++ b/src/icons/mono/os/kaios.svg @@ -0,0 +1 @@ +KaiOS \ No newline at end of file diff --git a/src/icons/mono/os/linux.svg b/src/icons/mono/os/linux.svg new file mode 100644 index 000000000..381d3d8a8 --- /dev/null +++ b/src/icons/mono/os/linux.svg @@ -0,0 +1 @@ +Linux \ No newline at end of file diff --git a/src/icons/mono/os/macos.svg b/src/icons/mono/os/macos.svg new file mode 100644 index 000000000..87630c456 --- /dev/null +++ b/src/icons/mono/os/macos.svg @@ -0,0 +1 @@ +macOS \ No newline at end of file diff --git a/src/icons/mono/os/manjaro.svg b/src/icons/mono/os/manjaro.svg new file mode 100644 index 000000000..d99972e2a --- /dev/null +++ b/src/icons/mono/os/manjaro.svg @@ -0,0 +1 @@ +Manjaro \ No newline at end of file diff --git a/src/icons/mono/os/mint.svg b/src/icons/mono/os/mint.svg new file mode 100644 index 000000000..442c8b2d5 --- /dev/null +++ b/src/icons/mono/os/mint.svg @@ -0,0 +1 @@ +Mint \ No newline at end of file diff --git a/src/icons/mono/os/netbsd.svg b/src/icons/mono/os/netbsd.svg new file mode 100644 index 000000000..511f066ed --- /dev/null +++ b/src/icons/mono/os/netbsd.svg @@ -0,0 +1 @@ +NetBSD \ No newline at end of file diff --git a/src/icons/mono/os/nintendo.svg b/src/icons/mono/os/nintendo.svg new file mode 100644 index 000000000..5cad9642f --- /dev/null +++ b/src/icons/mono/os/nintendo.svg @@ -0,0 +1 @@ +Nintendo \ No newline at end of file diff --git a/src/icons/mono/os/openbsd.svg b/src/icons/mono/os/openbsd.svg new file mode 100644 index 000000000..e78fbc7e6 --- /dev/null +++ b/src/icons/mono/os/openbsd.svg @@ -0,0 +1 @@ +OpenBSD \ No newline at end of file diff --git a/src/icons/mono/os/playstation.svg b/src/icons/mono/os/playstation.svg new file mode 100644 index 000000000..be3370316 --- /dev/null +++ b/src/icons/mono/os/playstation.svg @@ -0,0 +1 @@ +PlayStation \ No newline at end of file diff --git a/src/icons/mono/os/raspbian.svg b/src/icons/mono/os/raspbian.svg new file mode 100644 index 000000000..de6feed52 --- /dev/null +++ b/src/icons/mono/os/raspbian.svg @@ -0,0 +1 @@ +Raspbian \ No newline at end of file diff --git a/src/icons/mono/os/redhat.svg b/src/icons/mono/os/redhat.svg new file mode 100644 index 000000000..b68e41333 --- /dev/null +++ b/src/icons/mono/os/redhat.svg @@ -0,0 +1 @@ +RedHat \ No newline at end of file diff --git a/src/icons/mono/os/sailfish.svg b/src/icons/mono/os/sailfish.svg new file mode 100644 index 000000000..b695e10b4 --- /dev/null +++ b/src/icons/mono/os/sailfish.svg @@ -0,0 +1 @@ +Sailfish \ No newline at end of file diff --git a/src/icons/mono/os/slackware.svg b/src/icons/mono/os/slackware.svg new file mode 100644 index 000000000..611bf809d --- /dev/null +++ b/src/icons/mono/os/slackware.svg @@ -0,0 +1 @@ +Slackware \ No newline at end of file diff --git a/src/icons/mono/os/suse.svg b/src/icons/mono/os/suse.svg new file mode 100644 index 000000000..a4e474a1d --- /dev/null +++ b/src/icons/mono/os/suse.svg @@ -0,0 +1 @@ +SUSE \ No newline at end of file diff --git a/src/icons/mono/os/ubuntu.svg b/src/icons/mono/os/ubuntu.svg new file mode 100644 index 000000000..227f86aa3 --- /dev/null +++ b/src/icons/mono/os/ubuntu.svg @@ -0,0 +1 @@ +Ubuntu \ No newline at end of file diff --git a/src/icons/mono/os/windows.svg b/src/icons/mono/os/windows.svg new file mode 100644 index 000000000..9c79dffdb --- /dev/null +++ b/src/icons/mono/os/windows.svg @@ -0,0 +1 @@ +Windows 10 \ No newline at end of file diff --git a/src/icons/mono/os/xbox.svg b/src/icons/mono/os/xbox.svg new file mode 100644 index 000000000..85a9689a6 --- /dev/null +++ b/src/icons/mono/os/xbox.svg @@ -0,0 +1 @@ +Xbox \ No newline at end of file diff --git a/src/icons/ua-parser-icons.js b/src/icons/ua-parser-icons.js new file mode 100644 index 000000000..e69de29bb From fe15f115f9c5b811e72836cb68a8497004976d64 Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Tue, 22 Oct 2024 21:36:46 +0700 Subject: [PATCH 37/64] Fix #754: Add new Engine: ArkWeb & new OS: OpenHarmony --- src/enums/ua-parser-enums.js | 2 ++ src/main/ua-parser.js | 7 +++++-- test/specs/engine-all.json | 9 +++++++++ test/specs/os-all.json | 9 +++++++++ 4 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/enums/ua-parser-enums.js b/src/enums/ua-parser-enums.js index 9f58b6158..e80a0d57a 100644 --- a/src/enums/ua-parser-enums.js +++ b/src/enums/ua-parser-enums.js @@ -255,6 +255,7 @@ const Vendor = Object.freeze({ const Engine = Object.freeze({ AMAYA: 'Amaya', + ARKWEB: 'ArkWeb', BLINK: 'Blink', EDGEHTML: 'EdgeHTML', FLOW: 'Flow', @@ -321,6 +322,7 @@ const OS = Object.freeze({ NETRANGE: 'NetRange', NETTV: 'NetTV', NINTENDO: 'Nintendo', + OPENHARMONY: 'OpenHarmony', OPENBSD: 'OpenBSD', OPENVMS: 'OpenVMS', OS2: 'OS/2', diff --git a/src/main/ua-parser.js b/src/main/ua-parser.js index 59ac6553d..0eb24efd1 100755 --- a/src/main/ua-parser.js +++ b/src/main/ua-parser.js @@ -794,6 +794,9 @@ /windows.+ edge\/([\w\.]+)/i // EdgeHTML ], [VERSION, [NAME, EDGE+'HTML']], [ + /(arkweb)\/([\w\.]+)/i // ArkWeb + ], [NAME, VERSION], [ + /webkit\/537\.36.+chrome\/(?!27)([\w\.]+)/i // Blink ], [VERSION, [NAME, 'Blink']], [ @@ -844,8 +847,8 @@ // Mobile OSes /droid ([\w\.]+)\b.+(android[- ]x86|harmonyos)/i // Android-x86/HarmonyOS - ], [VERSION, NAME], [ // Android/WebOS/QNX/Bada/RIM/Maemo/MeeGo/Sailfish OS - /(android|webos|qnx|bada|rim tablet os|maemo|meego|sailfish)[-\/ ]?([\w\.]*)/i, + ], [VERSION, NAME], [ // Android/WebOS/QNX/Bada/RIM/Maemo/MeeGo/Sailfish OS/OpenHarmony + /(android|webos|qnx|bada|rim tablet os|maemo|meego|sailfish|openharmony)[-\/ ]?([\w\.]*)/i, /(blackberry)\w*\/([\w\.]*)/i, // Blackberry /(tizen|kaios)[\/ ]([\w\.]+)/i, // Tizen/KaiOS /\((series40);/i // Series 40 diff --git a/test/specs/engine-all.json b/test/specs/engine-all.json index e75e539cc..67fdd3381 100644 --- a/test/specs/engine-all.json +++ b/test/specs/engine-all.json @@ -1,4 +1,13 @@ [ + { + "desc" : "ArkWeb", + "ua" : "Mozilla/5.0 (Phone; OpenHarmony 4.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 ArkWeb/4.1.6.1 Mobile", + "expect" : + { + "name" : "ArkWeb", + "version" : "4.1.6.1" + } + }, { "desc" : "Blink", "ua" : "Mozilla/5.0 (Linux; Android 7.0; SM-G920I Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) OculusBrowser/3.4.9 SamsungBrowser/4.0 Chrome/57.0.2987.146 Mobile VR Safari/537.36", diff --git a/test/specs/os-all.json b/test/specs/os-all.json index 6fc03ecdd..b93dc33bd 100644 --- a/test/specs/os-all.json +++ b/test/specs/os-all.json @@ -1309,5 +1309,14 @@ "name" : "SerenityOS", "version" : "undefined" } + }, + { + "desc" : "OpenHarmony", + "ua" : "Mozilla/5.0 (Phone; OpenHarmony 4.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 ArkWeb/4.1.6.1 Mobile", + "expect" : + { + "name" : "OpenHarmony", + "version" : "4.1" + } } ] From 9890f9f5f80e7ffeec7392175c2a8fccb81df8a9 Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Fri, 25 Oct 2024 10:31:07 +0700 Subject: [PATCH 38/64] Move icons under `/dist` folder --- dist/icons/color/LICENSE.md | 3 +++ dist/icons/color/browser/android-browser.svg | 1 + dist/icons/color/browser/avant.png | Bin 0 -> 21415 bytes dist/icons/color/browser/basilisk.png | Bin 0 -> 6366 bytes dist/icons/color/browser/basilisk.svg | 1 + dist/icons/color/browser/brave.png | Bin 0 -> 7114 bytes dist/icons/color/browser/brave.svg | 1 + dist/icons/color/browser/chrome.png | Bin 0 -> 8883 bytes dist/icons/color/browser/chrome.svg | 1 + dist/icons/color/browser/chromium.png | Bin 0 -> 5190 bytes dist/icons/color/browser/chromium.svg | 1 + dist/icons/color/browser/coc-coc.png | Bin 0 -> 18330 bytes dist/icons/color/browser/default.png | Bin 0 -> 6914 bytes dist/icons/color/browser/default.svg | 1 + dist/icons/color/browser/dolphin.png | Bin 0 -> 5689 bytes dist/icons/color/browser/edge.png | Bin 0 -> 11311 bytes dist/icons/color/browser/edge.svg | 1 + dist/icons/color/browser/electron.png | Bin 0 -> 4667 bytes dist/icons/color/browser/electron.svg | 1 + dist/icons/color/browser/falkon.png | Bin 0 -> 13611 bytes dist/icons/color/browser/falkon.svg | 1 + dist/icons/color/browser/firefox-reality.png | Bin 0 -> 16015 bytes dist/icons/color/browser/firefox-reality.svg | 1 + dist/icons/color/browser/firefox.png | Bin 0 -> 15035 bytes dist/icons/color/browser/firefox.svg | 1 + dist/icons/color/browser/gsa.svg | 9 +++++++++ dist/icons/color/browser/icecat.png | Bin 0 -> 24923 bytes dist/icons/color/browser/ie.svg | 6 ++++++ dist/icons/color/browser/konqueror.png | Bin 0 -> 15036 bytes dist/icons/color/browser/konqueror.svg | 1 + dist/icons/color/browser/maxthon.png | Bin 0 -> 4754 bytes dist/icons/color/browser/midori.png | Bin 0 -> 14611 bytes dist/icons/color/browser/midori.svg | 1 + dist/icons/color/browser/netsurf.png | Bin 0 -> 12702 bytes dist/icons/color/browser/netsurf.svg | 1 + dist/icons/color/browser/opera-gx.png | Bin 0 -> 4922 bytes dist/icons/color/browser/opera-gx.svg | 1 + dist/icons/color/browser/opera-mini.png | Bin 0 -> 9242 bytes dist/icons/color/browser/opera-touch.png | Bin 0 -> 8351 bytes dist/icons/color/browser/opera.png | Bin 0 -> 5749 bytes dist/icons/color/browser/opera.svg | 1 + dist/icons/color/browser/palemoon.png | Bin 0 -> 23124 bytes dist/icons/color/browser/puffin.png | Bin 0 -> 15274 bytes dist/icons/color/browser/safari.png | Bin 0 -> 21132 bytes dist/icons/color/browser/safari.svg | 1 + dist/icons/color/browser/samsung-internet.png | Bin 0 -> 5192 bytes dist/icons/color/browser/samsung-internet.svg | 1 + dist/icons/color/browser/seamonkey.png | Bin 0 -> 16454 bytes dist/icons/color/browser/silk.png | Bin 0 -> 9184 bytes dist/icons/color/browser/sogou-mobile.png | Bin 0 -> 7704 bytes dist/icons/color/browser/ucbrowser.png | Bin 0 -> 9026 bytes dist/icons/color/browser/ucbrowser.svg | 1 + dist/icons/color/browser/vivaldi.png | Bin 0 -> 7634 bytes dist/icons/color/browser/vivaldi.svg | 1 + dist/icons/color/browser/webkit.png | Bin 0 -> 11500 bytes dist/icons/color/browser/webkit.svg | 1 + dist/icons/color/browser/yandex.png | Bin 0 -> 10997 bytes dist/icons/color/os/centos.svg | 1 + {src => dist}/icons/mono/LICENSE.md | 0 {src => dist}/icons/mono/browser/alipay.svg | 0 .../icons/mono/browser/android-browser.svg | 0 .../icons/mono/browser/avast-secure-browser.svg | 0 .../icons/mono/browser/baidu-browser.svg | 0 {src => dist}/icons/mono/browser/brave.svg | 0 .../icons/mono/browser/chrome-headless.svg | 0 .../icons/mono/browser/chrome-webview.svg | 0 {src => dist}/icons/mono/browser/chrome.svg | 0 {src => dist}/icons/mono/browser/chromium.svg | 0 {src => dist}/icons/mono/browser/duckduckgo.svg | 0 {src => dist}/icons/mono/browser/edge.svg | 0 {src => dist}/icons/mono/browser/electron.svg | 0 {src => dist}/icons/mono/browser/facebook.svg | 0 .../icons/mono/browser/firefox-focus.svg | 0 .../icons/mono/browser/firefox-reality.svg | 0 {src => dist}/icons/mono/browser/firefox.svg | 0 {src => dist}/icons/mono/browser/gsa.svg | 0 .../icons/mono/browser/huawei-browser.svg | 0 {src => dist}/icons/mono/browser/icecat.svg | 0 {src => dist}/icons/mono/browser/ie.svg | 0 {src => dist}/icons/mono/browser/instagram.svg | 0 {src => dist}/icons/mono/browser/jasmine.svg | 0 {src => dist}/icons/mono/browser/kakaotalk.svg | 0 {src => dist}/icons/mono/browser/klarna.svg | 0 {src => dist}/icons/mono/browser/line.svg | 0 {src => dist}/icons/mono/browser/linkedin.svg | 0 .../icons/mono/browser/miui-browser.svg | 0 .../icons/mono/browser/mobile-chrome.svg | 0 .../icons/mono/browser/mobile-firefox.svg | 0 .../icons/mono/browser/mobile-safari.svg | 0 {src => dist}/icons/mono/browser/mozilla.svg | 0 {src => dist}/icons/mono/browser/naver.svg | 0 .../icons/mono/browser/nokia-browser.svg | 0 .../icons/mono/browser/oculus-browser.svg | 0 .../icons/mono/browser/opera-coast.svg | 0 {src => dist}/icons/mono/browser/opera-gx.svg | 0 {src => dist}/icons/mono/browser/opera-mini.svg | 0 {src => dist}/icons/mono/browser/opera-mobi.svg | 0 .../icons/mono/browser/opera-tablet.svg | 0 .../icons/mono/browser/opera-touch.svg | 0 {src => dist}/icons/mono/browser/opera.svg | 0 {src => dist}/icons/mono/browser/qqbrowser.svg | 0 .../icons/mono/browser/qqbrowserlite.svg | 0 {src => dist}/icons/mono/browser/safari.svg | 0 .../icons/mono/browser/sailfish-browser.svg | 0 .../icons/mono/browser/samsung-internet.svg | 0 .../icons/mono/browser/smart-lenovo-browser.svg | 0 {src => dist}/icons/mono/browser/snapchat.svg | 0 .../icons/mono/browser/sogou-explorer.svg | 0 .../icons/mono/browser/sogou-mobile.svg | 0 {src => dist}/icons/mono/browser/tesla.svg | 0 {src => dist}/icons/mono/browser/tiktok.svg | 0 {src => dist}/icons/mono/browser/twitter.svg | 0 {src => dist}/icons/mono/browser/vivaldi.svg | 0 .../icons/mono/browser/vivo-browser.svg | 0 {src => dist}/icons/mono/browser/wechat.svg | 0 {src => dist}/icons/mono/browser/weibo.svg | 0 {src => dist}/icons/mono/browser/yandex.svg | 0 {src => dist}/icons/mono/device/acer.svg | 0 {src => dist}/icons/mono/device/amazon.svg | 0 {src => dist}/icons/mono/device/apple.svg | 0 {src => dist}/icons/mono/device/asus.svg | 0 {src => dist}/icons/mono/device/att.svg | 0 {src => dist}/icons/mono/device/blackberry.svg | 0 {src => dist}/icons/mono/device/dell.svg | 0 {src => dist}/icons/mono/device/facebook.svg | 0 {src => dist}/icons/mono/device/fairphone.svg | 0 {src => dist}/icons/mono/device/google.svg | 0 {src => dist}/icons/mono/device/hp.svg | 0 {src => dist}/icons/mono/device/huawei.svg | 0 {src => dist}/icons/mono/device/lenovo.svg | 0 {src => dist}/icons/mono/device/lg.svg | 0 {src => dist}/icons/mono/device/meizu.svg | 0 {src => dist}/icons/mono/device/microsoft.svg | 0 {src => dist}/icons/mono/device/motorola.svg | 0 {src => dist}/icons/mono/device/nintendo.svg | 0 {src => dist}/icons/mono/device/nokia.svg | 0 {src => dist}/icons/mono/device/nvidia.svg | 0 {src => dist}/icons/mono/device/oneplus.svg | 0 {src => dist}/icons/mono/device/oppo.svg | 0 {src => dist}/icons/mono/device/panasonic.svg | 0 {src => dist}/icons/mono/device/roku.svg | 0 {src => dist}/icons/mono/device/samsung.svg | 0 {src => dist}/icons/mono/device/siemens.svg | 0 {src => dist}/icons/mono/device/sony.svg | 0 {src => dist}/icons/mono/device/tesla.svg | 0 {src => dist}/icons/mono/device/vivo.svg | 0 {src => dist}/icons/mono/device/vodafone.svg | 0 {src => dist}/icons/mono/device/xiaomi.svg | 0 {src => dist}/icons/mono/device/zebra.svg | 0 {src => dist}/icons/mono/os/android.svg | 0 {src => dist}/icons/mono/os/arch.svg | 0 {src => dist}/icons/mono/os/blackberry.svg | 0 {src => dist}/icons/mono/os/centos.svg | 0 .../icons/mono/os/chrome-os.svg | 0 {src => dist}/icons/mono/os/chromecast.svg | 0 {src => dist}/icons/mono/os/debian.svg | 0 {src => dist}/icons/mono/os/deepin.svg | 0 .../icons/mono/os/elementary-os.svg | 0 {src => dist}/icons/mono/os/fedora.svg | 0 {src => dist}/icons/mono/os/firefox.svg | 0 {src => dist}/icons/mono/os/freebsd.svg | 0 {src => dist}/icons/mono/os/gentoo.svg | 0 {src => dist}/icons/mono/os/gnu.svg | 0 {src => dist}/icons/mono/os/harmonyos.svg | 0 {src => dist}/icons/mono/os/ios.svg | 0 {src => dist}/icons/mono/os/kaios.svg | 0 {src => dist}/icons/mono/os/linux.svg | 0 {src => dist}/icons/mono/os/macos.svg | 0 {src => dist}/icons/mono/os/manjaro.svg | 0 {src => dist}/icons/mono/os/mint.svg | 0 {src => dist}/icons/mono/os/netbsd.svg | 0 {src => dist}/icons/mono/os/nintendo.svg | 0 {src => dist}/icons/mono/os/openbsd.svg | 0 {src => dist}/icons/mono/os/playstation.svg | 0 {src => dist}/icons/mono/os/raspbian.svg | 0 {src => dist}/icons/mono/os/redhat.svg | 0 {src => dist}/icons/mono/os/sailfish.svg | 0 {src => dist}/icons/mono/os/slackware.svg | 0 {src => dist}/icons/mono/os/suse.svg | 0 {src => dist}/icons/mono/os/ubuntu.svg | 0 {src => dist}/icons/mono/os/windows.svg | 0 {src => dist}/icons/mono/os/xbox.svg | 0 src/icons/ua-parser-icons.js | 0 183 files changed, 40 insertions(+) create mode 100644 dist/icons/color/LICENSE.md create mode 100644 dist/icons/color/browser/android-browser.svg create mode 100644 dist/icons/color/browser/avant.png create mode 100644 dist/icons/color/browser/basilisk.png create mode 100644 dist/icons/color/browser/basilisk.svg create mode 100644 dist/icons/color/browser/brave.png create mode 100644 dist/icons/color/browser/brave.svg create mode 100644 dist/icons/color/browser/chrome.png create mode 100644 dist/icons/color/browser/chrome.svg create mode 100644 dist/icons/color/browser/chromium.png create mode 100644 dist/icons/color/browser/chromium.svg create mode 100644 dist/icons/color/browser/coc-coc.png create mode 100644 dist/icons/color/browser/default.png create mode 100644 dist/icons/color/browser/default.svg create mode 100644 dist/icons/color/browser/dolphin.png create mode 100644 dist/icons/color/browser/edge.png create mode 100644 dist/icons/color/browser/edge.svg create mode 100644 dist/icons/color/browser/electron.png create mode 100644 dist/icons/color/browser/electron.svg create mode 100644 dist/icons/color/browser/falkon.png create mode 100644 dist/icons/color/browser/falkon.svg create mode 100644 dist/icons/color/browser/firefox-reality.png create mode 100644 dist/icons/color/browser/firefox-reality.svg create mode 100644 dist/icons/color/browser/firefox.png create mode 100644 dist/icons/color/browser/firefox.svg create mode 100644 dist/icons/color/browser/gsa.svg create mode 100644 dist/icons/color/browser/icecat.png create mode 100644 dist/icons/color/browser/ie.svg create mode 100644 dist/icons/color/browser/konqueror.png create mode 100644 dist/icons/color/browser/konqueror.svg create mode 100644 dist/icons/color/browser/maxthon.png create mode 100644 dist/icons/color/browser/midori.png create mode 100644 dist/icons/color/browser/midori.svg create mode 100644 dist/icons/color/browser/netsurf.png create mode 100644 dist/icons/color/browser/netsurf.svg create mode 100644 dist/icons/color/browser/opera-gx.png create mode 100644 dist/icons/color/browser/opera-gx.svg create mode 100644 dist/icons/color/browser/opera-mini.png create mode 100644 dist/icons/color/browser/opera-touch.png create mode 100644 dist/icons/color/browser/opera.png create mode 100644 dist/icons/color/browser/opera.svg create mode 100644 dist/icons/color/browser/palemoon.png create mode 100644 dist/icons/color/browser/puffin.png create mode 100644 dist/icons/color/browser/safari.png create mode 100644 dist/icons/color/browser/safari.svg create mode 100644 dist/icons/color/browser/samsung-internet.png create mode 100644 dist/icons/color/browser/samsung-internet.svg create mode 100644 dist/icons/color/browser/seamonkey.png create mode 100644 dist/icons/color/browser/silk.png create mode 100644 dist/icons/color/browser/sogou-mobile.png create mode 100644 dist/icons/color/browser/ucbrowser.png create mode 100644 dist/icons/color/browser/ucbrowser.svg create mode 100644 dist/icons/color/browser/vivaldi.png create mode 100644 dist/icons/color/browser/vivaldi.svg create mode 100644 dist/icons/color/browser/webkit.png create mode 100644 dist/icons/color/browser/webkit.svg create mode 100644 dist/icons/color/browser/yandex.png create mode 100644 dist/icons/color/os/centos.svg rename {src => dist}/icons/mono/LICENSE.md (100%) rename {src => dist}/icons/mono/browser/alipay.svg (100%) rename {src => dist}/icons/mono/browser/android-browser.svg (100%) rename {src => dist}/icons/mono/browser/avast-secure-browser.svg (100%) rename {src => dist}/icons/mono/browser/baidu-browser.svg (100%) rename {src => dist}/icons/mono/browser/brave.svg (100%) rename {src => dist}/icons/mono/browser/chrome-headless.svg (100%) rename {src => dist}/icons/mono/browser/chrome-webview.svg (100%) rename {src => dist}/icons/mono/browser/chrome.svg (100%) rename {src => dist}/icons/mono/browser/chromium.svg (100%) rename {src => dist}/icons/mono/browser/duckduckgo.svg (100%) rename {src => dist}/icons/mono/browser/edge.svg (100%) rename {src => dist}/icons/mono/browser/electron.svg (100%) rename {src => dist}/icons/mono/browser/facebook.svg (100%) rename {src => dist}/icons/mono/browser/firefox-focus.svg (100%) rename {src => dist}/icons/mono/browser/firefox-reality.svg (100%) rename {src => dist}/icons/mono/browser/firefox.svg (100%) rename {src => dist}/icons/mono/browser/gsa.svg (100%) rename {src => dist}/icons/mono/browser/huawei-browser.svg (100%) rename {src => dist}/icons/mono/browser/icecat.svg (100%) rename {src => dist}/icons/mono/browser/ie.svg (100%) rename {src => dist}/icons/mono/browser/instagram.svg (100%) rename {src => dist}/icons/mono/browser/jasmine.svg (100%) rename {src => dist}/icons/mono/browser/kakaotalk.svg (100%) rename {src => dist}/icons/mono/browser/klarna.svg (100%) rename {src => dist}/icons/mono/browser/line.svg (100%) rename {src => dist}/icons/mono/browser/linkedin.svg (100%) rename {src => dist}/icons/mono/browser/miui-browser.svg (100%) rename {src => dist}/icons/mono/browser/mobile-chrome.svg (100%) rename {src => dist}/icons/mono/browser/mobile-firefox.svg (100%) rename {src => dist}/icons/mono/browser/mobile-safari.svg (100%) rename {src => dist}/icons/mono/browser/mozilla.svg (100%) rename {src => dist}/icons/mono/browser/naver.svg (100%) rename {src => dist}/icons/mono/browser/nokia-browser.svg (100%) rename {src => dist}/icons/mono/browser/oculus-browser.svg (100%) rename {src => dist}/icons/mono/browser/opera-coast.svg (100%) rename {src => dist}/icons/mono/browser/opera-gx.svg (100%) rename {src => dist}/icons/mono/browser/opera-mini.svg (100%) rename {src => dist}/icons/mono/browser/opera-mobi.svg (100%) rename {src => dist}/icons/mono/browser/opera-tablet.svg (100%) rename {src => dist}/icons/mono/browser/opera-touch.svg (100%) rename {src => dist}/icons/mono/browser/opera.svg (100%) rename {src => dist}/icons/mono/browser/qqbrowser.svg (100%) rename {src => dist}/icons/mono/browser/qqbrowserlite.svg (100%) rename {src => dist}/icons/mono/browser/safari.svg (100%) rename {src => dist}/icons/mono/browser/sailfish-browser.svg (100%) rename {src => dist}/icons/mono/browser/samsung-internet.svg (100%) rename {src => dist}/icons/mono/browser/smart-lenovo-browser.svg (100%) rename {src => dist}/icons/mono/browser/snapchat.svg (100%) rename {src => dist}/icons/mono/browser/sogou-explorer.svg (100%) rename {src => dist}/icons/mono/browser/sogou-mobile.svg (100%) rename {src => dist}/icons/mono/browser/tesla.svg (100%) rename {src => dist}/icons/mono/browser/tiktok.svg (100%) rename {src => dist}/icons/mono/browser/twitter.svg (100%) rename {src => dist}/icons/mono/browser/vivaldi.svg (100%) rename {src => dist}/icons/mono/browser/vivo-browser.svg (100%) rename {src => dist}/icons/mono/browser/wechat.svg (100%) rename {src => dist}/icons/mono/browser/weibo.svg (100%) rename {src => dist}/icons/mono/browser/yandex.svg (100%) rename {src => dist}/icons/mono/device/acer.svg (100%) rename {src => dist}/icons/mono/device/amazon.svg (100%) rename {src => dist}/icons/mono/device/apple.svg (100%) rename {src => dist}/icons/mono/device/asus.svg (100%) rename {src => dist}/icons/mono/device/att.svg (100%) rename {src => dist}/icons/mono/device/blackberry.svg (100%) rename {src => dist}/icons/mono/device/dell.svg (100%) rename {src => dist}/icons/mono/device/facebook.svg (100%) rename {src => dist}/icons/mono/device/fairphone.svg (100%) rename {src => dist}/icons/mono/device/google.svg (100%) rename {src => dist}/icons/mono/device/hp.svg (100%) rename {src => dist}/icons/mono/device/huawei.svg (100%) rename {src => dist}/icons/mono/device/lenovo.svg (100%) rename {src => dist}/icons/mono/device/lg.svg (100%) rename {src => dist}/icons/mono/device/meizu.svg (100%) rename {src => dist}/icons/mono/device/microsoft.svg (100%) rename {src => dist}/icons/mono/device/motorola.svg (100%) rename {src => dist}/icons/mono/device/nintendo.svg (100%) rename {src => dist}/icons/mono/device/nokia.svg (100%) rename {src => dist}/icons/mono/device/nvidia.svg (100%) rename {src => dist}/icons/mono/device/oneplus.svg (100%) rename {src => dist}/icons/mono/device/oppo.svg (100%) rename {src => dist}/icons/mono/device/panasonic.svg (100%) rename {src => dist}/icons/mono/device/roku.svg (100%) rename {src => dist}/icons/mono/device/samsung.svg (100%) rename {src => dist}/icons/mono/device/siemens.svg (100%) rename {src => dist}/icons/mono/device/sony.svg (100%) rename {src => dist}/icons/mono/device/tesla.svg (100%) rename {src => dist}/icons/mono/device/vivo.svg (100%) rename {src => dist}/icons/mono/device/vodafone.svg (100%) rename {src => dist}/icons/mono/device/xiaomi.svg (100%) rename {src => dist}/icons/mono/device/zebra.svg (100%) rename {src => dist}/icons/mono/os/android.svg (100%) rename {src => dist}/icons/mono/os/arch.svg (100%) rename {src => dist}/icons/mono/os/blackberry.svg (100%) rename {src => dist}/icons/mono/os/centos.svg (100%) rename src/icons/mono/os/chrome_os.svg => dist/icons/mono/os/chrome-os.svg (100%) rename {src => dist}/icons/mono/os/chromecast.svg (100%) rename {src => dist}/icons/mono/os/debian.svg (100%) rename {src => dist}/icons/mono/os/deepin.svg (100%) rename src/icons/mono/os/elementary_os.svg => dist/icons/mono/os/elementary-os.svg (100%) rename {src => dist}/icons/mono/os/fedora.svg (100%) rename {src => dist}/icons/mono/os/firefox.svg (100%) rename {src => dist}/icons/mono/os/freebsd.svg (100%) rename {src => dist}/icons/mono/os/gentoo.svg (100%) rename {src => dist}/icons/mono/os/gnu.svg (100%) rename {src => dist}/icons/mono/os/harmonyos.svg (100%) rename {src => dist}/icons/mono/os/ios.svg (100%) rename {src => dist}/icons/mono/os/kaios.svg (100%) rename {src => dist}/icons/mono/os/linux.svg (100%) rename {src => dist}/icons/mono/os/macos.svg (100%) rename {src => dist}/icons/mono/os/manjaro.svg (100%) rename {src => dist}/icons/mono/os/mint.svg (100%) rename {src => dist}/icons/mono/os/netbsd.svg (100%) rename {src => dist}/icons/mono/os/nintendo.svg (100%) rename {src => dist}/icons/mono/os/openbsd.svg (100%) rename {src => dist}/icons/mono/os/playstation.svg (100%) rename {src => dist}/icons/mono/os/raspbian.svg (100%) rename {src => dist}/icons/mono/os/redhat.svg (100%) rename {src => dist}/icons/mono/os/sailfish.svg (100%) rename {src => dist}/icons/mono/os/slackware.svg (100%) rename {src => dist}/icons/mono/os/suse.svg (100%) rename {src => dist}/icons/mono/os/ubuntu.svg (100%) rename {src => dist}/icons/mono/os/windows.svg (100%) rename {src => dist}/icons/mono/os/xbox.svg (100%) delete mode 100644 src/icons/ua-parser-icons.js diff --git a/dist/icons/color/LICENSE.md b/dist/icons/color/LICENSE.md new file mode 100644 index 000000000..c025cd011 --- /dev/null +++ b/dist/icons/color/LICENSE.md @@ -0,0 +1,3 @@ +MIT License +Copyright (c) Cătălin Mariș +https://github.com/alrra/browser-logos \ No newline at end of file diff --git a/dist/icons/color/browser/android-browser.svg b/dist/icons/color/browser/android-browser.svg new file mode 100644 index 000000000..92d59275b --- /dev/null +++ b/dist/icons/color/browser/android-browser.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/dist/icons/color/browser/avant.png b/dist/icons/color/browser/avant.png new file mode 100644 index 0000000000000000000000000000000000000000..e0b715d8b9a2c8c87024344a333117558976a86e GIT binary patch literal 21415 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 literal 0 HcmV?d00001 diff --git a/dist/icons/color/browser/basilisk.svg b/dist/icons/color/browser/basilisk.svg new file mode 100644 index 000000000..64e1f61c3 --- /dev/null +++ b/dist/icons/color/browser/basilisk.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/dist/icons/color/browser/brave.png b/dist/icons/color/browser/brave.png new file mode 100644 index 0000000000000000000000000000000000000000..06fa477700a166c3842b1eba0e65dac4d4f49efd GIT binary patch literal 7114 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 literal 0 HcmV?d00001 diff --git a/dist/icons/color/browser/brave.svg b/dist/icons/color/browser/brave.svg new file mode 100644 index 000000000..fb5ed8b82 --- /dev/null +++ b/dist/icons/color/browser/brave.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/dist/icons/color/browser/chrome.png b/dist/icons/color/browser/chrome.png new file mode 100644 index 0000000000000000000000000000000000000000..f251ad8e91a422f0c0c118b4f53b39d2a7680df1 GIT binary patch literal 8883 zcmXYXXIvBC^Yw;=B=k^}&^rhs9qAB?QUocAprU|)fFMO$s0k37AVm~Wse+=S0xCsX z=*2=41f(RPNQZ2v%0I->xnb@6tvHv}A z=*hcX-}MIoh)0;47+yt#R!6}B@=N?ll-jbxzcrjPC1btS_a|zu*VUx*zV?Y+JNF^X zEog13tD#?G=~Mnsx!D5uH_Ksp=A*iFT79~j^Dl?3ktm_{(IHe>weG-kN8z7U&tMI} z2iEzO^IToa0kw=;t3NrCy6#|-s)q@#ifqA}Cbe1EC-Hk$Ew_c%1FxAztX5|UvpjHA z+wN4{t-fheOKOSZxxxSQ5fL=GZ*8Jj(3VeUXk@4$^=aHrUkF;TmPnOB9MgO{l6aU+ ziC9C)b7m#?>R4`zY75TDi0;E_h|5@}%h)~6<1(tj-2mAPAcM*r3=)khSWoT-6gn?Z z6=Qxfk^L@Xm0uYkKlgj7RO!F?>T1YuZtOH?2a*t4Se0PVf& zPzsoe+Y`t2|6Y^8ay6kcQ~)XJDa})awjc`1%-tW3ymTY8E_J8#*Itd(>4*tIGaNai zODBb{=wu%Js~d=d61k>W_TfK)hngUUR|5LFb*wEOfPPj8er`Swz_j0FqQl|XswZF; zE{CedGu*=L9gaOUghz{t-Go5BU}ckF4uvR4Z3qL87Is1h#6S%oDFaf?pTMIt{b*%y zvuekf3)~DfBYllmwebF>mRMv5MlI~vAsq7I`C_=!OeCDy8oSISd_3>szNZBOqPJs1Cpz> z3Tni5uGaeNKJ&I}fs$^nf6u4e&k%sNg*y1|W#CnJ6mUimu)Byt^Pa52ALSRV8!5B; z$VL3V;c~G8;mIO9sTokwDbqYNei=y2i0|OAi7`{1|UQdHz2?{BO%(%G6jig_Y88zN%S~o-gq~z@j^=X zKku9h@hKav9M*s+O$Ma}M*StHY#1`(<2{YjKBibQ*s-YZOMh894P)S@Ck-eyv#6&} z18|NylhFZ<&5K0AhaeM*r^-2wg>{4YSwhDi@g?~eXs+#0EGA#eHBx*FHS7*iPsuQx zafW&T8eGn?a_m4S2QVT4_yqx30({ub@%s{t<1c<{X5M@ESAcsek?3K=EusJ(XalKP zW25+MFgvDG;n~lJvxVTd+1X$S6bBu!`2_-K z(}2>`Xaxv+sndM3Va$=3mnJ|kF&G10(AjibfXtnC5X8*>9%R0&Rt&AFkksY|+;|64 z69J*n4Ctu!hv#&GIFnmYlotz^Ha9cxjRX*}rw|yFXi1nsoAtc!27KW$kj_T~{{T5P zV6qEH6DX!ee9MS?PhpkKAm0tkooN^YiyiBhvF$4mF@u%(Z-JI21UwW5z6$|Fqoqxsp1$Bei9985F}f35 zCNOE*k0Mr4-2*p$fcxd!A0|%1%8voOGoSL~VxE=?2h#?of(%d^SHnQA;i}OrP-UE} z^w>;H@nA0I8}Z8iP|xax!akm!10Cz$<#kn+{=`+w-SNzLZL&eI$fg;~EAc&1T7)KG zPy-e{;EH_)$9LdwTIk#IHVBub3T3pFgj8)+9nk{ohwtm2cU+G7`frQAfNq%N0xmN%^-=FUpV>FwqIFmJSx8Vmw$QmBk3l&))X2X ziFR36d{D!79kcqCQ47A+9(%Mre;u~jRLdGeVh~pao`Jkpp)PSjKNa5;ma?p63^6h& zT5m%ID#Ekyhf5s$&yE+RH~SbGAGxKro&6zuMYE>e>kaC;R$9jMD|heSwX|cu@?1=? zfi*++=W0EVPWbM6U$kfGtk>7urVqv4MmFf{aCxh!zUfHM(2x47F?((DwKG#1`QI;W zO?{VgAqiZbkNlngU1L2&u0Ukts-@P{xYoO*hOI2)seBHRx1su>rGK@=tk&{!)5py1 zEf>wS(Op$u{w|Y+j>bCn*V}QsMftq?gdF9gu}>*$?>Xl&su^`)$A&_meC7}6>+h_k0ur5g9m8wNSkbl8F0_hx!zIKwlID0mQy{67=H0rTzra_eoyiXFkh=tnmS9*5m*g5Iw1FA|D&&$l#5&l zi*zS|&}Up61CPbu&B*yM8dD^Fe1II!8^4lcIFP6TWJIZ<%WeBPN1p8widWCQv>cR( zd%u|UbhBNC>5M7&@#3fI@3&%7KJ$vCJ8P#^&Y86$1((~!2IaNKlHzp*7fDz+i;vg5 z*vO^x$!A$QqPOFjP|!X;H{K@AYnStNjcB2)CTCHqj*~4=RDA6ljPvzJ{P^R|t*bi+ zA>SqHWlI*Fh;=07%H8HaQQt;c-#=lebunw@>6wb}Ytk#1`HJNJHN6%;@QQunU`Cjz zZFu5K`pXb1e}!kLCr@K9wR)N~Lc`i4o3;tA$DD{zLt1*$jG z%Rmu6*1&ai4-znaUSf8vrwdcmLlq8UXP{%ue`Y-I_WX0E_k?_}Is3=c>IwOci+#;w z>uV0Z5-f6a4%zseE9-}L5B&d%>3y13$gdcCGw61l8*>?d5r2)IMjO{AI6M)!NC@@k zS=i#f&gI201ovpYd%h0lh%93$S6GgE^>0x`EzIdG9RG%%r+g!rH~B8{gYDy;@0$B- z`JUes^QJ$4xXlJoY&WW@I)2Sv9(Q>?1WaEoB-2Ol-t-~A+Y(&%y(?fS9sLDSE)qE~4yx_cGQDSG`X-wjKUhJ)~% zt;NHtmHkj`k73a){NXwvrq=4!8{_@qr%))C#HVBeJ z`CWga0zOTed^Zld#v%BEST?L$X8=WajslKstXR+kXQYI&3@Z~8{1JHG2A(FF%hJD!XE@9#4NMq3X2RYMu?!q^`v zahxO<_`yMdi3MP1%3_%xemWDCJcB54C;rSD+Iw2HIUth$^xSh_c(yz6P{jO@hp@W7 zbARcxTyH~olKu^=!N-Z-(#L!UUvd;GxHvcN8S>2&dFy40nApq6Y}ZcnJhEYn0A7gd zgL6&k{%Iuy1ZG(HAinKe$$Z^AiMg#=+wz^yl^8BofZ}jBY=q5Oa_y`H`Mhgjf?$X% zb#c{#w8H(L_ifM19iA`sk~O$B3kv~G26*sEPIFfdblQND~UcOzKk z>6e4U zR(_I&TZjHAwUYRM!*|9-&U7(nUW^7)kfQKl-Djqa0+*=b10qeRf2k$&GJ6G5D}eRKzD*!id{NA>y)rc|2KYVMD?-4zLQqdB+_nu&`SxuWLn9e6rx{>PUzMK(wpbonZyjuSPA|ow;ny}G}d@X?zY$D4Q zRZo1J>TttBcig;ku~3^+^ubqGqU`)HYW8%z;gq%|45L{QMIim6#r5d~nI52Xk@3Mo z+GAB2wk$e3F7tvT=V~fwdyt@U>-&0>Rbb>ZwrlS1lGvRzTtDnv#rI9BwoGmdYI$1A zI);i}GJJ`=Xm$@nRG~3C#^i=sQYPXmWE=mMQ&mg&l%jFlG2UsDAvDUpo99E}V!o5m zmguG>H~(qm&doW_*Q3M;zAit!cdXXZwNMhBFXoGDeBIT%(c;5mq&!oU&|8GUtd;N zrn^@<2@_mt+2?e2cAMBo^!#`^Mi!1OKrD- zpxqB}!SnIFUs%6-SOYWPp-cj;9vB;D`806L``CCd(F43}qrgoxh8cAdZ3XYe-fTRw zv}W0Z)MAMNiyl|}To!*SmAY4o@yP4%_8ymZrZ+`n3sfs)5FR%Fwp`fl{!aZMt=RdXySGHW zoA+Up+hM_a;gYj+Zfwxj8|triNJL+5h>#o_^R9lry*OQE&qhkuW=4iec$@D(ts((FKnFJ?rMQny(06e&-?rm;U-imtnhc2 zMP5JDFf;x+;|&=vTsyb2k#r@Bxx^!|D8afI#LR8Bhj=-2m{}q5*|3){{9gPz42t9f zb}$$2Ci*rkixbxA4%u$ObStzvd8K!H1PD{7@6VF&6_pA(KxooHuN=!mX-z+WD0~Qz zu|hI&xXVS??;>+>hyGYc#o{@$+$1BbiqpJ~so~K^e?fdc;d{9SvvNtgFSIy}2 zAvh^euo9KY2_*t;&{#&2=@l;-PExFF6q3J)@PVW|P<@0T}y^9?8Sjk(tP{81=GD>`@ zpzY93&ExGhN)|m=+x>PeBFUx#7=SDb7u})hRI?UUjE^pA|Y8}5P-z6$s^pq%CjG_A!^CW9fcMHEbg;ArUrVB$2(NP>QC^O#ytQ* z2fT{@)%iLs5fo*W*+Fw5uqwT1({cH)0^!hv?2yw)1qY{?R}JTQn_86RLH zG%w}s7;|fSzBp|1X3)@ETjoN65&u8fZV(HE&lO-7y@yytb6p7K<`$+hTMxi^L|L|t zjH%fZ)?pf_Jbyeu79CZ=CO3Ym1pK1@f6)Bc-9D7HX-BC1Q z@U!MX8_WxP(jIN)lBJQxRCsuHk{Myicz(OP&-TY=L%Ed!zp%yQbC|Qp^VAt0UJnf? z1{YvP{l7nhQDs)SCCdet;9!oJ<|$-lvL&y&ES-<6n>;==^c%-U+1ua#vuO>rzwfXM zn>y7|3extXSRGkqqA^8Cd_tel+prcj)Vcr1ClXUKqPn?)(j4xyF_bUHBW2*ox{*uI zz8?K$4lNwU|!tzaD zE1H#T%Dl1apI>nky*cU9YkYc9-7Pn*aY=J@e=a+d_Wr^xp5?^$Q4w4N<#F&pFM==% zKUv?GpQPdvJ8UBRqmro3ZCH(9LFys$TZ9%mju^-$<$+x4P- zx@&T{Z0={m#;fhWB0D0bwo%R!lH~?AJb13sD+^dW2yVg-+)w0?t$&Hm&o~zo%60}E z-p`huW-jwRUWz-9tXRc(>^=5-tPQw7*3m#*4)b? zub>}V_dWgK*`GD(2`k?r_}Y=w{vOdauZDiSW_E~TDY!gz2Pr0d9BT!(eAWE!MDdt` z^DYfeNiuUBornnr* zkjYmnu`~R@#lsOgK(H@c^Q*;^iDB)8&X&*IT171BQY6ED?9pyLq4{_B7&#xlqpy7Q zAGc4FLZw!=;bj8!0 z{;p(r_q*bArWd^q9mt@m8@B78oL{V%d7HjdP-hzuy%^wyOK54+WOTf(ncSt+;-9;o z-+{}Zzb&Im4#UhGp2UeX#{|x$ioI-oW+KZTDrZ}9?)ZB36TyUG0^6NXX=TgIMq0}o zPKDA>?+#tCVxS^7{*F&Yi*gigkuoxm$N2#k&}*ydjC{hUnh> z-M``Yo%Z1~C0k);tp6)%+Q`5c*jN%PN;LEY4l^53EsZ?46eP(#r>kl*#O0zay!_wX`1%K= zsrA-9p^y4#jqa?B?Llks07N-0^8*bv2)P+Rw{dY51ad?Kso>ZvvFRE%0S(hbO?a|v z0dw~8w#yQP`-nJ_ddn>Ym^rMcI(Jh-DERcPm6>1tQ@1Iv4_YrRG{7dq((*L6G|x4^ zms^7dg4k@zI3E*4#?;#MhLxWxi-93tST!4SlKq3<(Y~ZZzPTd7;DUh1JXXTR(@x*U z>To|fM*w;|{FpC2D}36iYU~&0-XeXX0k&xNXB#x@95yQAlg?+YbiSSP^KZ@li3a7a z(VDfF!77dubv0R6NA}jQL=*Bp{(e3zI?}p285C27_tD)*()r5GpY!8GddP0YDDVD| z`mKXFs$2x(PPE9_0Aj9Hlt~qNi&Y_*`KvcNtgg+o+aV7k@Vcnvnsn`lCwtEO_J?~( z{`7v)#lEziva~^=jRaaf2D5nnaQa8HZ?}egcHAEeKEh|iW=vn4r*KT|Kh7X&@kCLL z4X^`@B#HbZn|r1nDcG8=)WgzQt5vta$tS#0>aK%0Qhu#-zDF_ zf-iZrjZ4tXOM=U88Z=I*;*VCcbk;`w?$so$g*>N93Hf+jT)A<*zG(=vniEynU09dj z;V>AV`DM?LkM*&!0B|7y2EETe@oPlSSq1rO?<_l0Vv*OxjpqYjbsZtJ_UBpH|--dZVp%IHOe% z-0!ltz^%`r+Wt97l=lQ&67hfF%myx~iOaMsB$`L*gJL_$2@aj(HK5lMe7JP&=RKm9 z_ivpG@ob!mS@{zhIcpHH+GMR8P-+lZI(bZu-mS-%t&RHoRgIK2k6iY1lAT?CW)X9i z#1|J=b3^tHTv~nf``O(O+ofmw>+|^yj&n|wnr#NR51cEgAu8V;6DNqtHD8iGNS7b^>fzFKVFC{GaL4OB66DdN~hJ;ndoM&AzX#^J~=f}0)W!qru))QgRcuN)w z5j(0nv*ehx^DxBVIJy(`3f9n6X`tEGpfAFhoAS8k9=%53Qk40^7TFCzQ5Ox9>Cwa` z(MEPC`%ltPCrKih8Cqsc?BWwPW-b)MD-G!9-f&M4R%;xZqR(_`du#g_%S3LyuKi-u zs33$rF+YqZE+d>E@sdBY22RY;3{Fe}w_6tU_$M-$GnA3SAHlP{ckW&K_~EbZlEKvV zxrt9kfux<4G+`W)0MmzXxaqP!Rx&l>HBIbcXFYF3HthL@*d1?(+8F2t5OUqC#O*v;SUFS)UAq>dvaB^%}1a9uaTkD1PfQ%~Kf zO{KaH#v>LEi#X!gA$oR7?Yh7Ux6<-ywvF_)NPQy~jOC?j%ln_I@O3qLpfit~`(|v8 zk_{KrcK!n-h_z+PEh$bdF(yk|F756plD7OFtv%X_)Ys7+J097*6G~s`bNoK&EZOv& zD#mGym_2OyErw3sasRK`OJ1jzn7YHDTdrc{Zt{PHSx#H}HDWh?ZJrPm^iFZ}2GH8HBAWP*`_)F9oK3pkP-7;}fON~r5N9Nvz|+49CgY)a*Y=y6ZS^j&gBMv{e-2Isv@K+l@ zh#@uMRZScpm}fBTP}$tNMR9$Ibt_S#IC5HKZ7*utkSC71S(AMYfyr6B#O=&!aLIgf zG){yc*DuC{`O1zJf54nb-C$1GyGYS9uu)Yi`SzDaJJ4$0eq!NVZ#laVg=icQje;bC z%)~(4GPgQ1rZ!p-F=t!PLDt{aFG#fUR>jyxKZ-j3@LKoCLhB%&n#>=Eo`(4?-azZI z+9`c2N}VJ^0$kt*g=2fD0gd+7fRmJRS z(HM=qG2HbR7q!^j#HrJLk=N4sL-L(Inaq@V6 zHD-oG1u{T2-O(qLmPB=N4(-4N*<4alDyendnx}eHO9_Gz>w_nRG5H3C^_$`x7}3fn zTJiF2!z1R2mjzb7i+~`_8=(b1?YF3=NmzNI&VEedR_dMxaEPf`(7jq>Me%@w@6leA zNtAF@cy8>`8@a<#frb6gVKv(xGaQ0(Voof6UI4k-!3rg|!b>ZCu`%`KNfN;~ou-9jq$ocztTaR?FH2Fwnu00x_R6jC z9VzqNtfJJc_I2x4NU}bo5N^+ibZaaR=MbJdp9P*T@ z4~Aop_>@}YVRt2$?znU6fnd_8BL?v>qIvQr1FkkO!C~_F=_*Z5>u{*EKrmOLX)365 z#c&%T=!=jC6W`H(7x6aOGQ`u!Ou4gQgfbjb80SwcyuR1S!m(?%z8@DL{`7sscBdUwKRUd5?{3EZOQ!7%BPZ@U;K`aLJ3 zRT(ic;nrK!%A`}ms>vd`DNH-|p&Qkyb%zU^Cv+MNhw?#KL=-4ZAAS?Ponl9~R{G-% zD_5?VwWXb}N9HFN!a0nv#4F_6PKM+pj?c5vbs(civg@f^F5#F71xM)zF8UmJ zMx&z`VPVOm!T@k6(G6G82FXS{&ZPG2>&h6_Tizy$Y>L`E_UDi nDOT&x(o7xQq8mo6!+=}ig`3~Hqx?@UqX6a?E}MKZa*6vt&eH32 literal 0 HcmV?d00001 diff --git a/dist/icons/color/browser/chrome.svg b/dist/icons/color/browser/chrome.svg new file mode 100644 index 000000000..dcc3b1106 --- /dev/null +++ b/dist/icons/color/browser/chrome.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/dist/icons/color/browser/chromium.png b/dist/icons/color/browser/chromium.png new file mode 100644 index 0000000000000000000000000000000000000000..7a3cb15fcb2247674d9a9ceca46b8f1e0fc8d722 GIT binary patch literal 5190 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 \ No newline at end of file diff --git a/dist/icons/color/browser/coc-coc.png b/dist/icons/color/browser/coc-coc.png new file mode 100644 index 0000000000000000000000000000000000000000..f917dbcaba869554ee23b358d436878620cf84eb GIT binary patch literal 18330 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 pZ&4&fKz5o!GpAD% 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 \ No newline at end of file diff --git a/dist/icons/color/browser/dolphin.png b/dist/icons/color/browser/dolphin.png new file mode 100644 index 0000000000000000000000000000000000000000..d53805f980fc79cbd38e1e3c97fc19c9f1ad7955 GIT binary patch literal 5689 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 lHU9Xk+ \ No newline at end of file diff --git a/dist/icons/color/browser/electron.png b/dist/icons/color/browser/electron.png new file mode 100644 index 0000000000000000000000000000000000000000..e17799028cdf2bda86713855a518033760662f5f GIT binary patch literal 4667 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 literal 0 HcmV?d00001 diff --git a/dist/icons/color/browser/electron.svg b/dist/icons/color/browser/electron.svg new file mode 100644 index 000000000..a766fedd9 --- /dev/null +++ b/dist/icons/color/browser/electron.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/dist/icons/color/browser/falkon.png b/dist/icons/color/browser/falkon.png new file mode 100644 index 0000000000000000000000000000000000000000..d7fe06de5f600c07add1c6e644bd559e5c088ea3 GIT binary patch literal 13611 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 \ No newline at end of file diff --git a/dist/icons/color/browser/firefox-reality.png b/dist/icons/color/browser/firefox-reality.png new file mode 100644 index 0000000000000000000000000000000000000000..9a901a445ced22890ccec8c395df438819538640 GIT binary patch literal 16015 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 JPDHLkV1ficQ>6d^ literal 0 HcmV?d00001 diff --git a/dist/icons/color/browser/firefox-reality.svg b/dist/icons/color/browser/firefox-reality.svg new file mode 100644 index 000000000..a157540ab --- /dev/null +++ b/dist/icons/color/browser/firefox-reality.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/dist/icons/color/browser/firefox.png b/dist/icons/color/browser/firefox.png new file mode 100644 index 0000000000000000000000000000000000000000..fc7123205acd4d6be2dd946924997b3231aece9c GIT binary patch literal 15035 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 \ No newline at end of file diff --git a/dist/icons/color/browser/gsa.svg b/dist/icons/color/browser/gsa.svg new file mode 100644 index 000000000..05d397a8c --- /dev/null +++ b/dist/icons/color/browser/gsa.svg @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/dist/icons/color/browser/icecat.png b/dist/icons/color/browser/icecat.png new file mode 100644 index 0000000000000000000000000000000000000000..ad1953ae47a3e0001b3745a883f5b60e9e010425 GIT binary patch literal 24923 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 e$G^wF$NvY?rEzb}#~|_m0000 + + + + + \ No newline at end of file diff --git a/dist/icons/color/browser/konqueror.png b/dist/icons/color/browser/konqueror.png new file mode 100644 index 0000000000000000000000000000000000000000..8d28831181cd4b82cc9963e44d3e777acf517bcb GIT binary patch literal 15036 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 S_^*Wk0000 \ No newline at end of file diff --git a/dist/icons/color/browser/maxthon.png b/dist/icons/color/browser/maxthon.png new file mode 100644 index 0000000000000000000000000000000000000000..987020e9f9a1f1e15830d0ae5f10a19dfd7a5f2a GIT binary patch literal 4754 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 literal 0 HcmV?d00001 diff --git a/dist/icons/color/browser/midori.png b/dist/icons/color/browser/midori.png new file mode 100644 index 0000000000000000000000000000000000000000..681d94faa343d95c8ae3afce04dd3a1c4986d2d4 GIT binary patch literal 14611 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 \ No newline at end of file diff --git a/dist/icons/color/browser/netsurf.png b/dist/icons/color/browser/netsurf.png new file mode 100644 index 0000000000000000000000000000000000000000..0e0e3717f80c1de36b1e7252d8fcec62b9527fbf GIT binary patch literal 12702 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 Ye{?7#A4v=9Gynhq07*qoM6N<$f}+7drT_o{ literal 0 HcmV?d00001 diff --git a/dist/icons/color/browser/netsurf.svg b/dist/icons/color/browser/netsurf.svg new file mode 100644 index 000000000..67aa01bc7 --- /dev/null +++ b/dist/icons/color/browser/netsurf.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/dist/icons/color/browser/opera-gx.png b/dist/icons/color/browser/opera-gx.png new file mode 100644 index 0000000000000000000000000000000000000000..250cc25292c18a87cdd0e40efa66f7c5b096aaa3 GIT binary patch literal 4922 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 literal 0 HcmV?d00001 diff --git a/dist/icons/color/browser/opera-gx.svg b/dist/icons/color/browser/opera-gx.svg new file mode 100644 index 000000000..aeb51a519 --- /dev/null +++ b/dist/icons/color/browser/opera-gx.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/dist/icons/color/browser/opera-mini.png b/dist/icons/color/browser/opera-mini.png new file mode 100644 index 0000000000000000000000000000000000000000..bf220034fdd55c7becd23dea46812ee7176b0a74 GIT binary patch literal 9242 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 \ No newline at end of file diff --git a/dist/icons/color/browser/palemoon.png b/dist/icons/color/browser/palemoon.png new file mode 100644 index 0000000000000000000000000000000000000000..8696c06004a5ee5284e638f59a7fff044d25321b GIT binary patch literal 23124 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

25}x73--MeS41PcUE{sfV?Q6MgWB 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 literal 0 HcmV?d00001 diff --git a/dist/icons/color/browser/puffin.png b/dist/icons/color/browser/puffin.png new file mode 100644 index 0000000000000000000000000000000000000000..f511493551197712e21fb92ab56ad287dcdb0cd6 GIT binary patch literal 15274 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 literal 0 HcmV?d00001 diff --git a/dist/icons/color/browser/safari.png b/dist/icons/color/browser/safari.png new file mode 100644 index 0000000000000000000000000000000000000000..6fe6f54f00207697bbda4004288c14f5510b6f7a GIT binary patch literal 21132 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 \ No newline at end of file diff --git a/dist/icons/color/browser/samsung-internet.png b/dist/icons/color/browser/samsung-internet.png new file mode 100644 index 0000000000000000000000000000000000000000..543645cbe8fda19cd9f3c817730eea1785e08ea0 GIT binary patch literal 5192 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 \ No newline at end of file diff --git a/dist/icons/color/browser/seamonkey.png b/dist/icons/color/browser/seamonkey.png new file mode 100644 index 0000000000000000000000000000000000000000..55929783eec1970e46e5d049f90d8caab32a7c69 GIT binary patch literal 16454 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 g<7Q4*&oF07*qoM6N<$f@-RfM*si- literal 0 HcmV?d00001 diff --git a/dist/icons/color/browser/silk.png b/dist/icons/color/browser/silk.png new file mode 100644 index 0000000000000000000000000000000000000000..161e5c446cc1e5ce180832656348ca07a0f988a9 GIT binary patch literal 9184 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 qa literal 0 HcmV?d00001 diff --git a/dist/icons/color/browser/sogou-mobile.png b/dist/icons/color/browser/sogou-mobile.png new file mode 100644 index 0000000000000000000000000000000000000000..33bb210401ad0919f1a64b35fc69bb0fd178cc3b GIT binary patch literal 7704 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 z zAWhhem9a6EQti_0%FOn~f$guusNA}py+rUME}VrK!l@N$)rGPCFiqXVr3t6YhkFA zn-OSkHVHx;5x3%`L25;(BiJc7K+I>C z^`g@WQO86a)94RQ8l+WrehYWtg2uKb7ZhFo4pFyLaZGc&$0YRsJW0Fk9M-C%&<2fd zD{WA8cmzcEK&bKzJ>v|+1ge+w#B6~G0JZ7D8j0O;y>5LmE$;#knrVg3{3 zNNS_D!!O&X;Q@W{Kx3QA10R&#)C;x~ME7MA=#FF|9E-Z${cb|PvuTjK{pLfrWRC^q zX(vD$+fZIe*#$ef*Ka-oVOO`iO#);w97~3Sq(P`QVm|YVc8mvC2)W=v02*6U0eIko zQUK^+yf$J#1A(ZcrQ%qY7b7OAKRPK8s*jql-J&@gl#H)sqf-Rng?tE>CFX+{3P6dN zH8W@SAjD4C4ajnEtVpw9Q~F0H0YcA)-u<{$FoRyvocBxSQBVp`IJRoc5}7_`w#*n= ze*!}6fL(yB1ji~Fz70r-9`wHZQGM8a*%~#)cERlN3g!}A_KW5!-0)&^@&T?gE4YO0 o_A*0e$xK0r^d|?U8 \ No newline at end of file diff --git a/dist/icons/color/browser/vivaldi.png b/dist/icons/color/browser/vivaldi.png new file mode 100644 index 0000000000000000000000000000000000000000..64f0d32e710cda6a85c308202c6318a30df6d070 GIT binary patch literal 7634 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 AF8}}l literal 0 HcmV?d00001 diff --git a/dist/icons/color/browser/vivaldi.svg b/dist/icons/color/browser/vivaldi.svg new file mode 100644 index 000000000..2084b9758 --- /dev/null +++ b/dist/icons/color/browser/vivaldi.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/dist/icons/color/browser/webkit.png b/dist/icons/color/browser/webkit.png new file mode 100644 index 0000000000000000000000000000000000000000..cbc0f1b7b287ec6ee7a7bd845c3ac0403851c9b0 GIT binary patch literal 11500 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 SfS!H;0000 \ No newline at end of file diff --git a/dist/icons/color/browser/yandex.png b/dist/icons/color/browser/yandex.png new file mode 100644 index 0000000000000000000000000000000000000000..896456d205b1a84d5b510ed1c85115c7a2cdb0d2 GIT binary patch literal 10997 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 \ No newline at end of file diff --git a/src/icons/mono/LICENSE.md b/dist/icons/mono/LICENSE.md similarity index 100% rename from src/icons/mono/LICENSE.md rename to dist/icons/mono/LICENSE.md diff --git a/src/icons/mono/browser/alipay.svg b/dist/icons/mono/browser/alipay.svg similarity index 100% rename from src/icons/mono/browser/alipay.svg rename to dist/icons/mono/browser/alipay.svg diff --git a/src/icons/mono/browser/android-browser.svg b/dist/icons/mono/browser/android-browser.svg similarity index 100% rename from src/icons/mono/browser/android-browser.svg rename to dist/icons/mono/browser/android-browser.svg diff --git a/src/icons/mono/browser/avast-secure-browser.svg b/dist/icons/mono/browser/avast-secure-browser.svg similarity index 100% rename from src/icons/mono/browser/avast-secure-browser.svg rename to dist/icons/mono/browser/avast-secure-browser.svg diff --git a/src/icons/mono/browser/baidu-browser.svg b/dist/icons/mono/browser/baidu-browser.svg similarity index 100% rename from src/icons/mono/browser/baidu-browser.svg rename to dist/icons/mono/browser/baidu-browser.svg diff --git a/src/icons/mono/browser/brave.svg b/dist/icons/mono/browser/brave.svg similarity index 100% rename from src/icons/mono/browser/brave.svg rename to dist/icons/mono/browser/brave.svg diff --git a/src/icons/mono/browser/chrome-headless.svg b/dist/icons/mono/browser/chrome-headless.svg similarity index 100% rename from src/icons/mono/browser/chrome-headless.svg rename to dist/icons/mono/browser/chrome-headless.svg diff --git a/src/icons/mono/browser/chrome-webview.svg b/dist/icons/mono/browser/chrome-webview.svg similarity index 100% rename from src/icons/mono/browser/chrome-webview.svg rename to dist/icons/mono/browser/chrome-webview.svg diff --git a/src/icons/mono/browser/chrome.svg b/dist/icons/mono/browser/chrome.svg similarity index 100% rename from src/icons/mono/browser/chrome.svg rename to dist/icons/mono/browser/chrome.svg diff --git a/src/icons/mono/browser/chromium.svg b/dist/icons/mono/browser/chromium.svg similarity index 100% rename from src/icons/mono/browser/chromium.svg rename to dist/icons/mono/browser/chromium.svg diff --git a/src/icons/mono/browser/duckduckgo.svg b/dist/icons/mono/browser/duckduckgo.svg similarity index 100% rename from src/icons/mono/browser/duckduckgo.svg rename to dist/icons/mono/browser/duckduckgo.svg diff --git a/src/icons/mono/browser/edge.svg b/dist/icons/mono/browser/edge.svg similarity index 100% rename from src/icons/mono/browser/edge.svg rename to dist/icons/mono/browser/edge.svg diff --git a/src/icons/mono/browser/electron.svg b/dist/icons/mono/browser/electron.svg similarity index 100% rename from src/icons/mono/browser/electron.svg rename to dist/icons/mono/browser/electron.svg diff --git a/src/icons/mono/browser/facebook.svg b/dist/icons/mono/browser/facebook.svg similarity index 100% rename from src/icons/mono/browser/facebook.svg rename to dist/icons/mono/browser/facebook.svg diff --git a/src/icons/mono/browser/firefox-focus.svg b/dist/icons/mono/browser/firefox-focus.svg similarity index 100% rename from src/icons/mono/browser/firefox-focus.svg rename to dist/icons/mono/browser/firefox-focus.svg diff --git a/src/icons/mono/browser/firefox-reality.svg b/dist/icons/mono/browser/firefox-reality.svg similarity index 100% rename from src/icons/mono/browser/firefox-reality.svg rename to dist/icons/mono/browser/firefox-reality.svg diff --git a/src/icons/mono/browser/firefox.svg b/dist/icons/mono/browser/firefox.svg similarity index 100% rename from src/icons/mono/browser/firefox.svg rename to dist/icons/mono/browser/firefox.svg diff --git a/src/icons/mono/browser/gsa.svg b/dist/icons/mono/browser/gsa.svg similarity index 100% rename from src/icons/mono/browser/gsa.svg rename to dist/icons/mono/browser/gsa.svg diff --git a/src/icons/mono/browser/huawei-browser.svg b/dist/icons/mono/browser/huawei-browser.svg similarity index 100% rename from src/icons/mono/browser/huawei-browser.svg rename to dist/icons/mono/browser/huawei-browser.svg diff --git a/src/icons/mono/browser/icecat.svg b/dist/icons/mono/browser/icecat.svg similarity index 100% rename from src/icons/mono/browser/icecat.svg rename to dist/icons/mono/browser/icecat.svg diff --git a/src/icons/mono/browser/ie.svg b/dist/icons/mono/browser/ie.svg similarity index 100% rename from src/icons/mono/browser/ie.svg rename to dist/icons/mono/browser/ie.svg diff --git a/src/icons/mono/browser/instagram.svg b/dist/icons/mono/browser/instagram.svg similarity index 100% rename from src/icons/mono/browser/instagram.svg rename to dist/icons/mono/browser/instagram.svg diff --git a/src/icons/mono/browser/jasmine.svg b/dist/icons/mono/browser/jasmine.svg similarity index 100% rename from src/icons/mono/browser/jasmine.svg rename to dist/icons/mono/browser/jasmine.svg diff --git a/src/icons/mono/browser/kakaotalk.svg b/dist/icons/mono/browser/kakaotalk.svg similarity index 100% rename from src/icons/mono/browser/kakaotalk.svg rename to dist/icons/mono/browser/kakaotalk.svg diff --git a/src/icons/mono/browser/klarna.svg b/dist/icons/mono/browser/klarna.svg similarity index 100% rename from src/icons/mono/browser/klarna.svg rename to dist/icons/mono/browser/klarna.svg diff --git a/src/icons/mono/browser/line.svg b/dist/icons/mono/browser/line.svg similarity index 100% rename from src/icons/mono/browser/line.svg rename to dist/icons/mono/browser/line.svg diff --git a/src/icons/mono/browser/linkedin.svg b/dist/icons/mono/browser/linkedin.svg similarity index 100% rename from src/icons/mono/browser/linkedin.svg rename to dist/icons/mono/browser/linkedin.svg diff --git a/src/icons/mono/browser/miui-browser.svg b/dist/icons/mono/browser/miui-browser.svg similarity index 100% rename from src/icons/mono/browser/miui-browser.svg rename to dist/icons/mono/browser/miui-browser.svg diff --git a/src/icons/mono/browser/mobile-chrome.svg b/dist/icons/mono/browser/mobile-chrome.svg similarity index 100% rename from src/icons/mono/browser/mobile-chrome.svg rename to dist/icons/mono/browser/mobile-chrome.svg diff --git a/src/icons/mono/browser/mobile-firefox.svg b/dist/icons/mono/browser/mobile-firefox.svg similarity index 100% rename from src/icons/mono/browser/mobile-firefox.svg rename to dist/icons/mono/browser/mobile-firefox.svg diff --git a/src/icons/mono/browser/mobile-safari.svg b/dist/icons/mono/browser/mobile-safari.svg similarity index 100% rename from src/icons/mono/browser/mobile-safari.svg rename to dist/icons/mono/browser/mobile-safari.svg diff --git a/src/icons/mono/browser/mozilla.svg b/dist/icons/mono/browser/mozilla.svg similarity index 100% rename from src/icons/mono/browser/mozilla.svg rename to dist/icons/mono/browser/mozilla.svg diff --git a/src/icons/mono/browser/naver.svg b/dist/icons/mono/browser/naver.svg similarity index 100% rename from src/icons/mono/browser/naver.svg rename to dist/icons/mono/browser/naver.svg diff --git a/src/icons/mono/browser/nokia-browser.svg b/dist/icons/mono/browser/nokia-browser.svg similarity index 100% rename from src/icons/mono/browser/nokia-browser.svg rename to dist/icons/mono/browser/nokia-browser.svg diff --git a/src/icons/mono/browser/oculus-browser.svg b/dist/icons/mono/browser/oculus-browser.svg similarity index 100% rename from src/icons/mono/browser/oculus-browser.svg rename to dist/icons/mono/browser/oculus-browser.svg diff --git a/src/icons/mono/browser/opera-coast.svg b/dist/icons/mono/browser/opera-coast.svg similarity index 100% rename from src/icons/mono/browser/opera-coast.svg rename to dist/icons/mono/browser/opera-coast.svg diff --git a/src/icons/mono/browser/opera-gx.svg b/dist/icons/mono/browser/opera-gx.svg similarity index 100% rename from src/icons/mono/browser/opera-gx.svg rename to dist/icons/mono/browser/opera-gx.svg diff --git a/src/icons/mono/browser/opera-mini.svg b/dist/icons/mono/browser/opera-mini.svg similarity index 100% rename from src/icons/mono/browser/opera-mini.svg rename to dist/icons/mono/browser/opera-mini.svg diff --git a/src/icons/mono/browser/opera-mobi.svg b/dist/icons/mono/browser/opera-mobi.svg similarity index 100% rename from src/icons/mono/browser/opera-mobi.svg rename to dist/icons/mono/browser/opera-mobi.svg diff --git a/src/icons/mono/browser/opera-tablet.svg b/dist/icons/mono/browser/opera-tablet.svg similarity index 100% rename from src/icons/mono/browser/opera-tablet.svg rename to dist/icons/mono/browser/opera-tablet.svg diff --git a/src/icons/mono/browser/opera-touch.svg b/dist/icons/mono/browser/opera-touch.svg similarity index 100% rename from src/icons/mono/browser/opera-touch.svg rename to dist/icons/mono/browser/opera-touch.svg diff --git a/src/icons/mono/browser/opera.svg b/dist/icons/mono/browser/opera.svg similarity index 100% rename from src/icons/mono/browser/opera.svg rename to dist/icons/mono/browser/opera.svg diff --git a/src/icons/mono/browser/qqbrowser.svg b/dist/icons/mono/browser/qqbrowser.svg similarity index 100% rename from src/icons/mono/browser/qqbrowser.svg rename to dist/icons/mono/browser/qqbrowser.svg diff --git a/src/icons/mono/browser/qqbrowserlite.svg b/dist/icons/mono/browser/qqbrowserlite.svg similarity index 100% rename from src/icons/mono/browser/qqbrowserlite.svg rename to dist/icons/mono/browser/qqbrowserlite.svg diff --git a/src/icons/mono/browser/safari.svg b/dist/icons/mono/browser/safari.svg similarity index 100% rename from src/icons/mono/browser/safari.svg rename to dist/icons/mono/browser/safari.svg diff --git a/src/icons/mono/browser/sailfish-browser.svg b/dist/icons/mono/browser/sailfish-browser.svg similarity index 100% rename from src/icons/mono/browser/sailfish-browser.svg rename to dist/icons/mono/browser/sailfish-browser.svg diff --git a/src/icons/mono/browser/samsung-internet.svg b/dist/icons/mono/browser/samsung-internet.svg similarity index 100% rename from src/icons/mono/browser/samsung-internet.svg rename to dist/icons/mono/browser/samsung-internet.svg diff --git a/src/icons/mono/browser/smart-lenovo-browser.svg b/dist/icons/mono/browser/smart-lenovo-browser.svg similarity index 100% rename from src/icons/mono/browser/smart-lenovo-browser.svg rename to dist/icons/mono/browser/smart-lenovo-browser.svg diff --git a/src/icons/mono/browser/snapchat.svg b/dist/icons/mono/browser/snapchat.svg similarity index 100% rename from src/icons/mono/browser/snapchat.svg rename to dist/icons/mono/browser/snapchat.svg diff --git a/src/icons/mono/browser/sogou-explorer.svg b/dist/icons/mono/browser/sogou-explorer.svg similarity index 100% rename from src/icons/mono/browser/sogou-explorer.svg rename to dist/icons/mono/browser/sogou-explorer.svg diff --git a/src/icons/mono/browser/sogou-mobile.svg b/dist/icons/mono/browser/sogou-mobile.svg similarity index 100% rename from src/icons/mono/browser/sogou-mobile.svg rename to dist/icons/mono/browser/sogou-mobile.svg diff --git a/src/icons/mono/browser/tesla.svg b/dist/icons/mono/browser/tesla.svg similarity index 100% rename from src/icons/mono/browser/tesla.svg rename to dist/icons/mono/browser/tesla.svg diff --git a/src/icons/mono/browser/tiktok.svg b/dist/icons/mono/browser/tiktok.svg similarity index 100% rename from src/icons/mono/browser/tiktok.svg rename to dist/icons/mono/browser/tiktok.svg diff --git a/src/icons/mono/browser/twitter.svg b/dist/icons/mono/browser/twitter.svg similarity index 100% rename from src/icons/mono/browser/twitter.svg rename to dist/icons/mono/browser/twitter.svg diff --git a/src/icons/mono/browser/vivaldi.svg b/dist/icons/mono/browser/vivaldi.svg similarity index 100% rename from src/icons/mono/browser/vivaldi.svg rename to dist/icons/mono/browser/vivaldi.svg diff --git a/src/icons/mono/browser/vivo-browser.svg b/dist/icons/mono/browser/vivo-browser.svg similarity index 100% rename from src/icons/mono/browser/vivo-browser.svg rename to dist/icons/mono/browser/vivo-browser.svg diff --git a/src/icons/mono/browser/wechat.svg b/dist/icons/mono/browser/wechat.svg similarity index 100% rename from src/icons/mono/browser/wechat.svg rename to dist/icons/mono/browser/wechat.svg diff --git a/src/icons/mono/browser/weibo.svg b/dist/icons/mono/browser/weibo.svg similarity index 100% rename from src/icons/mono/browser/weibo.svg rename to dist/icons/mono/browser/weibo.svg diff --git a/src/icons/mono/browser/yandex.svg b/dist/icons/mono/browser/yandex.svg similarity index 100% rename from src/icons/mono/browser/yandex.svg rename to dist/icons/mono/browser/yandex.svg diff --git a/src/icons/mono/device/acer.svg b/dist/icons/mono/device/acer.svg similarity index 100% rename from src/icons/mono/device/acer.svg rename to dist/icons/mono/device/acer.svg diff --git a/src/icons/mono/device/amazon.svg b/dist/icons/mono/device/amazon.svg similarity index 100% rename from src/icons/mono/device/amazon.svg rename to dist/icons/mono/device/amazon.svg diff --git a/src/icons/mono/device/apple.svg b/dist/icons/mono/device/apple.svg similarity index 100% rename from src/icons/mono/device/apple.svg rename to dist/icons/mono/device/apple.svg diff --git a/src/icons/mono/device/asus.svg b/dist/icons/mono/device/asus.svg similarity index 100% rename from src/icons/mono/device/asus.svg rename to dist/icons/mono/device/asus.svg diff --git a/src/icons/mono/device/att.svg b/dist/icons/mono/device/att.svg similarity index 100% rename from src/icons/mono/device/att.svg rename to dist/icons/mono/device/att.svg diff --git a/src/icons/mono/device/blackberry.svg b/dist/icons/mono/device/blackberry.svg similarity index 100% rename from src/icons/mono/device/blackberry.svg rename to dist/icons/mono/device/blackberry.svg diff --git a/src/icons/mono/device/dell.svg b/dist/icons/mono/device/dell.svg similarity index 100% rename from src/icons/mono/device/dell.svg rename to dist/icons/mono/device/dell.svg diff --git a/src/icons/mono/device/facebook.svg b/dist/icons/mono/device/facebook.svg similarity index 100% rename from src/icons/mono/device/facebook.svg rename to dist/icons/mono/device/facebook.svg diff --git a/src/icons/mono/device/fairphone.svg b/dist/icons/mono/device/fairphone.svg similarity index 100% rename from src/icons/mono/device/fairphone.svg rename to dist/icons/mono/device/fairphone.svg diff --git a/src/icons/mono/device/google.svg b/dist/icons/mono/device/google.svg similarity index 100% rename from src/icons/mono/device/google.svg rename to dist/icons/mono/device/google.svg diff --git a/src/icons/mono/device/hp.svg b/dist/icons/mono/device/hp.svg similarity index 100% rename from src/icons/mono/device/hp.svg rename to dist/icons/mono/device/hp.svg diff --git a/src/icons/mono/device/huawei.svg b/dist/icons/mono/device/huawei.svg similarity index 100% rename from src/icons/mono/device/huawei.svg rename to dist/icons/mono/device/huawei.svg diff --git a/src/icons/mono/device/lenovo.svg b/dist/icons/mono/device/lenovo.svg similarity index 100% rename from src/icons/mono/device/lenovo.svg rename to dist/icons/mono/device/lenovo.svg diff --git a/src/icons/mono/device/lg.svg b/dist/icons/mono/device/lg.svg similarity index 100% rename from src/icons/mono/device/lg.svg rename to dist/icons/mono/device/lg.svg diff --git a/src/icons/mono/device/meizu.svg b/dist/icons/mono/device/meizu.svg similarity index 100% rename from src/icons/mono/device/meizu.svg rename to dist/icons/mono/device/meizu.svg diff --git a/src/icons/mono/device/microsoft.svg b/dist/icons/mono/device/microsoft.svg similarity index 100% rename from src/icons/mono/device/microsoft.svg rename to dist/icons/mono/device/microsoft.svg diff --git a/src/icons/mono/device/motorola.svg b/dist/icons/mono/device/motorola.svg similarity index 100% rename from src/icons/mono/device/motorola.svg rename to dist/icons/mono/device/motorola.svg diff --git a/src/icons/mono/device/nintendo.svg b/dist/icons/mono/device/nintendo.svg similarity index 100% rename from src/icons/mono/device/nintendo.svg rename to dist/icons/mono/device/nintendo.svg diff --git a/src/icons/mono/device/nokia.svg b/dist/icons/mono/device/nokia.svg similarity index 100% rename from src/icons/mono/device/nokia.svg rename to dist/icons/mono/device/nokia.svg diff --git a/src/icons/mono/device/nvidia.svg b/dist/icons/mono/device/nvidia.svg similarity index 100% rename from src/icons/mono/device/nvidia.svg rename to dist/icons/mono/device/nvidia.svg diff --git a/src/icons/mono/device/oneplus.svg b/dist/icons/mono/device/oneplus.svg similarity index 100% rename from src/icons/mono/device/oneplus.svg rename to dist/icons/mono/device/oneplus.svg diff --git a/src/icons/mono/device/oppo.svg b/dist/icons/mono/device/oppo.svg similarity index 100% rename from src/icons/mono/device/oppo.svg rename to dist/icons/mono/device/oppo.svg diff --git a/src/icons/mono/device/panasonic.svg b/dist/icons/mono/device/panasonic.svg similarity index 100% rename from src/icons/mono/device/panasonic.svg rename to dist/icons/mono/device/panasonic.svg diff --git a/src/icons/mono/device/roku.svg b/dist/icons/mono/device/roku.svg similarity index 100% rename from src/icons/mono/device/roku.svg rename to dist/icons/mono/device/roku.svg diff --git a/src/icons/mono/device/samsung.svg b/dist/icons/mono/device/samsung.svg similarity index 100% rename from src/icons/mono/device/samsung.svg rename to dist/icons/mono/device/samsung.svg diff --git a/src/icons/mono/device/siemens.svg b/dist/icons/mono/device/siemens.svg similarity index 100% rename from src/icons/mono/device/siemens.svg rename to dist/icons/mono/device/siemens.svg diff --git a/src/icons/mono/device/sony.svg b/dist/icons/mono/device/sony.svg similarity index 100% rename from src/icons/mono/device/sony.svg rename to dist/icons/mono/device/sony.svg diff --git a/src/icons/mono/device/tesla.svg b/dist/icons/mono/device/tesla.svg similarity index 100% rename from src/icons/mono/device/tesla.svg rename to dist/icons/mono/device/tesla.svg diff --git a/src/icons/mono/device/vivo.svg b/dist/icons/mono/device/vivo.svg similarity index 100% rename from src/icons/mono/device/vivo.svg rename to dist/icons/mono/device/vivo.svg diff --git a/src/icons/mono/device/vodafone.svg b/dist/icons/mono/device/vodafone.svg similarity index 100% rename from src/icons/mono/device/vodafone.svg rename to dist/icons/mono/device/vodafone.svg diff --git a/src/icons/mono/device/xiaomi.svg b/dist/icons/mono/device/xiaomi.svg similarity index 100% rename from src/icons/mono/device/xiaomi.svg rename to dist/icons/mono/device/xiaomi.svg diff --git a/src/icons/mono/device/zebra.svg b/dist/icons/mono/device/zebra.svg similarity index 100% rename from src/icons/mono/device/zebra.svg rename to dist/icons/mono/device/zebra.svg diff --git a/src/icons/mono/os/android.svg b/dist/icons/mono/os/android.svg similarity index 100% rename from src/icons/mono/os/android.svg rename to dist/icons/mono/os/android.svg diff --git a/src/icons/mono/os/arch.svg b/dist/icons/mono/os/arch.svg similarity index 100% rename from src/icons/mono/os/arch.svg rename to dist/icons/mono/os/arch.svg diff --git a/src/icons/mono/os/blackberry.svg b/dist/icons/mono/os/blackberry.svg similarity index 100% rename from src/icons/mono/os/blackberry.svg rename to dist/icons/mono/os/blackberry.svg diff --git a/src/icons/mono/os/centos.svg b/dist/icons/mono/os/centos.svg similarity index 100% rename from src/icons/mono/os/centos.svg rename to dist/icons/mono/os/centos.svg diff --git a/src/icons/mono/os/chrome_os.svg b/dist/icons/mono/os/chrome-os.svg similarity index 100% rename from src/icons/mono/os/chrome_os.svg rename to dist/icons/mono/os/chrome-os.svg diff --git a/src/icons/mono/os/chromecast.svg b/dist/icons/mono/os/chromecast.svg similarity index 100% rename from src/icons/mono/os/chromecast.svg rename to dist/icons/mono/os/chromecast.svg diff --git a/src/icons/mono/os/debian.svg b/dist/icons/mono/os/debian.svg similarity index 100% rename from src/icons/mono/os/debian.svg rename to dist/icons/mono/os/debian.svg diff --git a/src/icons/mono/os/deepin.svg b/dist/icons/mono/os/deepin.svg similarity index 100% rename from src/icons/mono/os/deepin.svg rename to dist/icons/mono/os/deepin.svg diff --git a/src/icons/mono/os/elementary_os.svg b/dist/icons/mono/os/elementary-os.svg similarity index 100% rename from src/icons/mono/os/elementary_os.svg rename to dist/icons/mono/os/elementary-os.svg diff --git a/src/icons/mono/os/fedora.svg b/dist/icons/mono/os/fedora.svg similarity index 100% rename from src/icons/mono/os/fedora.svg rename to dist/icons/mono/os/fedora.svg diff --git a/src/icons/mono/os/firefox.svg b/dist/icons/mono/os/firefox.svg similarity index 100% rename from src/icons/mono/os/firefox.svg rename to dist/icons/mono/os/firefox.svg diff --git a/src/icons/mono/os/freebsd.svg b/dist/icons/mono/os/freebsd.svg similarity index 100% rename from src/icons/mono/os/freebsd.svg rename to dist/icons/mono/os/freebsd.svg diff --git a/src/icons/mono/os/gentoo.svg b/dist/icons/mono/os/gentoo.svg similarity index 100% rename from src/icons/mono/os/gentoo.svg rename to dist/icons/mono/os/gentoo.svg diff --git a/src/icons/mono/os/gnu.svg b/dist/icons/mono/os/gnu.svg similarity index 100% rename from src/icons/mono/os/gnu.svg rename to dist/icons/mono/os/gnu.svg diff --git a/src/icons/mono/os/harmonyos.svg b/dist/icons/mono/os/harmonyos.svg similarity index 100% rename from src/icons/mono/os/harmonyos.svg rename to dist/icons/mono/os/harmonyos.svg diff --git a/src/icons/mono/os/ios.svg b/dist/icons/mono/os/ios.svg similarity index 100% rename from src/icons/mono/os/ios.svg rename to dist/icons/mono/os/ios.svg diff --git a/src/icons/mono/os/kaios.svg b/dist/icons/mono/os/kaios.svg similarity index 100% rename from src/icons/mono/os/kaios.svg rename to dist/icons/mono/os/kaios.svg diff --git a/src/icons/mono/os/linux.svg b/dist/icons/mono/os/linux.svg similarity index 100% rename from src/icons/mono/os/linux.svg rename to dist/icons/mono/os/linux.svg diff --git a/src/icons/mono/os/macos.svg b/dist/icons/mono/os/macos.svg similarity index 100% rename from src/icons/mono/os/macos.svg rename to dist/icons/mono/os/macos.svg diff --git a/src/icons/mono/os/manjaro.svg b/dist/icons/mono/os/manjaro.svg similarity index 100% rename from src/icons/mono/os/manjaro.svg rename to dist/icons/mono/os/manjaro.svg diff --git a/src/icons/mono/os/mint.svg b/dist/icons/mono/os/mint.svg similarity index 100% rename from src/icons/mono/os/mint.svg rename to dist/icons/mono/os/mint.svg diff --git a/src/icons/mono/os/netbsd.svg b/dist/icons/mono/os/netbsd.svg similarity index 100% rename from src/icons/mono/os/netbsd.svg rename to dist/icons/mono/os/netbsd.svg diff --git a/src/icons/mono/os/nintendo.svg b/dist/icons/mono/os/nintendo.svg similarity index 100% rename from src/icons/mono/os/nintendo.svg rename to dist/icons/mono/os/nintendo.svg diff --git a/src/icons/mono/os/openbsd.svg b/dist/icons/mono/os/openbsd.svg similarity index 100% rename from src/icons/mono/os/openbsd.svg rename to dist/icons/mono/os/openbsd.svg diff --git a/src/icons/mono/os/playstation.svg b/dist/icons/mono/os/playstation.svg similarity index 100% rename from src/icons/mono/os/playstation.svg rename to dist/icons/mono/os/playstation.svg diff --git a/src/icons/mono/os/raspbian.svg b/dist/icons/mono/os/raspbian.svg similarity index 100% rename from src/icons/mono/os/raspbian.svg rename to dist/icons/mono/os/raspbian.svg diff --git a/src/icons/mono/os/redhat.svg b/dist/icons/mono/os/redhat.svg similarity index 100% rename from src/icons/mono/os/redhat.svg rename to dist/icons/mono/os/redhat.svg diff --git a/src/icons/mono/os/sailfish.svg b/dist/icons/mono/os/sailfish.svg similarity index 100% rename from src/icons/mono/os/sailfish.svg rename to dist/icons/mono/os/sailfish.svg diff --git a/src/icons/mono/os/slackware.svg b/dist/icons/mono/os/slackware.svg similarity index 100% rename from src/icons/mono/os/slackware.svg rename to dist/icons/mono/os/slackware.svg diff --git a/src/icons/mono/os/suse.svg b/dist/icons/mono/os/suse.svg similarity index 100% rename from src/icons/mono/os/suse.svg rename to dist/icons/mono/os/suse.svg diff --git a/src/icons/mono/os/ubuntu.svg b/dist/icons/mono/os/ubuntu.svg similarity index 100% rename from src/icons/mono/os/ubuntu.svg rename to dist/icons/mono/os/ubuntu.svg diff --git a/src/icons/mono/os/windows.svg b/dist/icons/mono/os/windows.svg similarity index 100% rename from src/icons/mono/os/windows.svg rename to dist/icons/mono/os/windows.svg diff --git a/src/icons/mono/os/xbox.svg b/dist/icons/mono/os/xbox.svg similarity index 100% rename from src/icons/mono/os/xbox.svg rename to dist/icons/mono/os/xbox.svg diff --git a/src/icons/ua-parser-icons.js b/src/icons/ua-parser-icons.js deleted file mode 100644 index e69de29bb..000000000 From aad163ffc530474aa748eade44f587a39ac97b69 Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Tue, 29 Oct 2024 21:24:16 +0700 Subject: [PATCH 39/64] Change `withFeatureCheck()` return value to also include `PromiseLike` as an anticipation --- src/main/ua-parser.d.ts | 2 +- test/dts-test.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/ua-parser.d.ts b/src/main/ua-parser.d.ts index b83783180..03be97a52 100644 --- a/src/main/ua-parser.d.ts +++ b/src/main/ua-parser.d.ts @@ -8,7 +8,7 @@ declare namespace UAParser { is(val: string): boolean; toString(): string; withClientHints(): PromiseLike | T; - withFeatureCheck(): T; + withFeatureCheck(): PromiseLike | T; } interface IBrowser extends IData { diff --git a/test/dts-test.ts b/test/dts-test.ts index edf1d47d6..0f05a8aa2 100644 --- a/test/dts-test.ts +++ b/test/dts-test.ts @@ -32,8 +32,8 @@ expectType<'crawler' | 'cli' | 'email' | 'fetcher' | 'inapp' | 'mediaplayer' | ' expectType(browser.is('')); expectType(browser.toString()); expectType>(browser.withClientHints()); -expectType((browser.withClientHints()).withFeatureCheck()); -expectType((browser.withClientHints()).withFeatureCheck().is('')); +expectType>((browser.withClientHints()).withFeatureCheck()); +expectType(((browser.withClientHints()).withFeatureCheck()).is('')); expectType(parser.getCPU()); expectType(parser.getDevice()); From 1e0175c001b60a0d809a6e4388954492a9cacc19 Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Tue, 29 Oct 2024 22:29:51 +0700 Subject: [PATCH 40/64] Update version to `2.0.0-rc.1` --- CHANGELOG.md | 20 +++ README.md | 83 ++--------- dist/ua-parser.min.js | 4 +- dist/ua-parser.pack.js | 4 +- package-lock.json | 4 +- package.json | 2 +- src/enums/ua-parser-enums.js | 2 +- src/enums/ua-parser-enums.mjs | 15 +- src/extensions/ua-parser-extensions.js | 2 +- src/extensions/ua-parser-extensions.mjs | 177 +++++++++++++----------- src/helpers/ua-parser-helpers.js | 2 +- src/helpers/ua-parser-helpers.mjs | 51 ++++++- src/main/ua-parser.js | 4 +- src/main/ua-parser.mjs | 76 +++++++--- 14 files changed, 255 insertions(+), 191 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 80dfe6423..63d6bf0f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,25 @@ # UAParser.js Changelog +## Version 2.0.0-rc.1 + +- Fix Python Request mistakenly identified as Meta Quest +- Add new browser: Helio +- Add new device: itel, Nothing, Pico, TCL +- Add new engine: ArkWeb +- Add new OS: OpenHarmony, Pico +- Improve browser detection: Quark +- Improve device detection: Xiaomi, Amazon Echo Show, Google Chromecast, Samsung Galaxy Watch +- `ua-parser-js/helpers` submodule: + - Add new method: + - `getDeviceVendor()` to guess for a device vendor based on its model name + - `isElectron()` to check if current window is running inside Electron + - `isFromEU()` to check if current window is from an EU (European Union) country + - `isStandalonePWA()` to check if current window is a standalone PWA + - Rename `isChromiumBased()` to `isChromeFamily()` + - Update `isAppleSilicon()` to also checks for WebGL renderer info +- `ua-parser-js/extensions` submodule: + - Restore `bots` as a compilation of all these browser types: `clis`, `crawlers`, `fetchers`, and `modules` + ## Version 2.0.0-beta.3 - Breaking: diff --git a/README.md b/README.md index 57e0473bf..701add0cd 100644 --- a/README.md +++ b/README.md @@ -19,81 +19,14 @@ The most comprehensive, compact, & up-to-date isomorphic JavaScript library to d user's Browser, Engine, OS, CPU, and Device type/model. Runs either in browser (client-side) or node.js (server-side). -# Overview - -```js -import { UAParser } from 'ua-parser-js'; - -// 1. Problem: -// Imagine getting this wild user-agent string from a visitor: -const ua = `Mozilla/5.0 (Linux; Android 10; STK-LX1 -Build/HONORSTK-LX1; wv) AppleWebKit/537.36 (KHTML, -like Gecko) Version/4.0 Chrome/110.0.5481.153 Mobile -Safari/537.36 musical_ly_2022803040 JsSdk/1.0 -NetType/WIFI Channel/huaweiadsglobal_int -AppName/musical_ly app_version/28.3.4 ByteLocale/en -ByteFullLocale/en Region/IQ Spark/1.2.7-alpha.8 -AppVersion/28.3.4 PIA/1.5.11 BytedanceWebview/d8a21c6`; -// Note: this is a real user-agent (what???) - -// 2. Solution: -// Just pass the complex user-agent string to `UAParser` -const parser = new UAParser(ua); - -// 3. Result: -// And voila! -console.log(parser.getBrowser()); -// { name : "TikTok", version : "28.3.4", major : "28", type: undefined } - -console.log(parser.getCPU()); -// { architecture : undefined } - -console.log(parser.getEngine()); -// { name : "Blink", version : "110.0.5481.153" } - -console.log(parser.getDevice()); -// { type : "mobile", vendor : "Huawei", model : "STK-LX1" } - -console.log(parser.getOS()); -// { name : "Android", version : "10" } - -console.log(parser.getResult()); -/* -{ - ua: "Mozilla/5.0 (Linux; Android 10; STK-LX1 Build/HONORSTK-LX1; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/110.0.5481.153 Mobile Safari/537.36 musical_ly_2022803040 JsSdk/1.0 NetType/WIFI Channel/huaweiadsglobal_int AppName/musical_ly app_version/28.3.4 ByteLocale/en ByteFullLocale/en Region/IQ Spark/1.2.7-alpha.8 AppVersion/28.3.4 PIA/1.5.11 BytedanceWebview/d8a21c6", - browser: { - name: "TikTok", - version: "28.3.4", - major: "28" - }, - cpu: {}, - device: { - type: "mobile", - model: "STK-LX1", - vendor: "Huawei" - }, - engine: { - name: "Blink", - version: "110.0.5481.153" - }, - os: { - name: "Android", - version: "10" - } -} -*/ - -// 4. Conclusion: -// The visitor is browsing from a TikTok app using an Android-powered Huawei device -// Phew! Thanks, UAParser.js! -``` +# Demo * Live demo: https://uaparser.dev # Documentation - * v1.0: https://github.com/faisalman/ua-parser-js/tree/1.0.38#documentation - * v2.0: https://docs.uaparser.dev + * `version 1.x` : https://github.com/faisalman/ua-parser-js/tree/1.0.x#documentation + * `version 2.x` : https://docs.uaparser.dev Before upgrading from `v0.7` / `v1.0`, please read [CHANGELOG](CHANGELOG.md) to see what's new & breaking. @@ -234,7 +167,7 @@ see what's new & breaking. ✅ ✅ ✅ - ⚠️ + ⛔️ ✅ @@ -257,9 +190,9 @@ see what's new & breaking. Price FREE (License) FREE (License) - $12 (License) - $25 (License) - $500 (License) + $14 (License) + $29 (License) + $588 (License) @@ -287,3 +220,5 @@ Made with [contributors-img](https://contrib.rocks). + +Support the open-source versions of UAParser.js on [OpenCollective](https://opencollective.com/ua-parser-js) or [GitHub Sponsors](https://github.com/sponsors/faisalman). diff --git a/dist/ua-parser.min.js b/dist/ua-parser.min.js index 8819c5a6f..4187195e4 100644 --- a/dist/ua-parser.min.js +++ b/dist/ua-parser.min.js @@ -1,4 +1,4 @@ -/* UAParser.js v2.0.0-beta.3 +/* UAParser.js v2.0.0-rc.1 Copyright © 2012-2024 Faisal Salman AGPLv3 License */ -(function(window,undefined){"use strict";var LIBVERSION="2.0.0-beta.3",EMPTY="",UNKNOWN="?",FUNC_TYPE="function",UNDEF_TYPE="undefined",OBJ_TYPE="object",STR_TYPE="string",MAJOR="major",MODEL="model",NAME="name",TYPE="type",VENDOR="vendor",VERSION="version",ARCHITECTURE="architecture",CONSOLE="console",MOBILE="mobile",TABLET="tablet",SMARTTV="smarttv",WEARABLE="wearable",XR="xr",EMBEDDED="embedded",USER_AGENT="user-agent",UA_MAX_LENGTH=500,BRANDS="brands",FORMFACTORS="formFactors",FULLVERLIST="fullVersionList",PLATFORM="platform",PLATFORMVER="platformVersion",BITNESS="bitness",CH_HEADER="sec-ch-ua",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,FORMFACTORS,BITNESS],UA_BROWSER="browser",UA_CPU="cpu",UA_DEVICE="device",UA_ENGINE="engine",UA_OS="os",UA_RESULT="result",AMAZON="Amazon",APPLE="Apple",ASUS="ASUS",BLACKBERRY="BlackBerry",GOOGLE="Google",HUAWEI="Huawei",LENOVO="Lenovo",LG="LG",MICROSOFT="Microsoft",MOTOROLA="Motorola",SAMSUNG="Samsung",SHARP="Sharp",SONY="Sony",XIAOMI="Xiaomi",ZEBRA="Zebra",PREFIX_MOBILE="Mobile ",SUFFIX_BROWSER=" Browser",CHROME="Chrome",EDGE="Edge",FIREFOX="Firefox",OPERA="Opera",FACEBOOK="Facebook",SOGOU="Sogou",WINDOWS="Windows";var isWindow=typeof window!==UNDEF_TYPE,NAVIGATOR=isWindow&&window.navigator?window.navigator:undefined,NAVIGATOR_UADATA=NAVIGATOR&&NAVIGATOR.userAgentData?NAVIGATOR.userAgentData:undefined;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]:[])}}}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={};for(var i=0;i0){for(var i in str1){if(lowerize(str1[i])==lowerize(str2))return true}return false}return isString(str1)?lowerize(str2).indexOf(lowerize(str1))!==-1:false},isExtensions=function(obj,deep){for(var prop in obj){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(",");for(var i=0;i-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 isString(str)?str.toLowerCase():str},majorize=function(version){return isString(version)?strip(/[^\d\.]/g,version).split(".")[0]:undefined},setProps=function(arr){for(var i in arr){var propName=arr[i];if(typeof propName==OBJ_TYPE&&propName.length==2){this[propName[0]]=propName[1]}else{this[propName]=undefined}}return this},strip=function(pattern,str){return isString(str)?str.replace(pattern,EMPTY):str},stripQuotes=function(str){return strip(/\\?\"/g,str)},trim=function(str,len){if(isString(str)){str=strip(/^\s\s*/,str);return typeof len===UNDEF_TYPE?str:str.substring(0,UA_MAX_LENGTH)}};var rgxMapper=function(ua,arrays){if(!ua||!arrays)return;var i=0,j,k,p,q,matches,match;while(i0){if(q.length===2){if(typeof q[1]==FUNC_TYPE){this[q[0]]=q[1].call(this,match)}else{this[q[0]]=q[1]}}else if(q.length===3){if(typeof q[1]===FUNC_TYPE&&!(q[1].exec&&q[1].test)){this[q[0]]=match?q[1].call(this,match,q[2]):undefined}else{this[q[0]]=match?match.replace(q[1],q[2]):undefined}}else if(q.length===4){this[q[0]]=match?q[3].call(this,match.replace(q[1],q[2])):undefined}}else{this[q]=match?match:undefined}}}}i+=2}},strMapper=function(str,map){for(var i in map){if(typeof map[i]===OBJ_TYPE&&map[i].length>0){for(var j=0;j2){this.set(MODEL,"iPad").set(TYPE,TABLET)}break;case UA_OS:if(!this.get(NAME)&&NAVIGATOR_UADATA&&NAVIGATOR_UADATA[PLATFORM]){this.set(NAME,NAVIGATOR_UADATA[PLATFORM])}break;case UA_RESULT:var data=this.data;var detect=function(itemType){return data[itemType].getItem().detectFeature().get()};this.set(UA_BROWSER,detect(UA_BROWSER)).set(UA_CPU,detect(UA_CPU)).set(UA_DEVICE,detect(UA_DEVICE)).set(UA_ENGINE,detect(UA_ENGINE)).set(UA_OS,detect(UA_OS))}}return this};this.parseUA=function(){if(this.itemType!=UA_RESULT){rgxMapper.call(this.data,this.ua,this.rgxMap)}if(this.itemType==UA_BROWSER){this.set(MAJOR,majorize(this.get(VERSION)))}return this};this.parseCH=function(){var uaCH=this.uaCH,rgxMap=this.rgxMap;switch(this.itemType){case UA_BROWSER:var brands=uaCH[FULLVERLIST]||uaCH[BRANDS],prevName;if(brands){for(var i in brands){var brandName=strip(/(Google|Microsoft) /,brands[i].brand||brands[i]),brandVersion=brands[i].version;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}}}break;case UA_CPU:var archName=uaCH[ARCHITECTURE];if(archName){if(archName&&uaCH[BITNESS]=="64")archName+="64";rgxMapper.call(this.data,archName+";",rgxMap)}break;case UA_DEVICE:if(uaCH[MOBILE]){this.set(TYPE,MOBILE)}if(uaCH[MODEL]){this.set(MODEL,uaCH[MODEL])}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=13?"11":"10";this.set(NAME,osName).set(VERSION,osVersion)}if(this.get(NAME)==WINDOWS&&uaCH[MODEL]=="Xbox"){this.set(NAME,"Xbox").set(VERSION,undefined)}break;case UA_RESULT:var data=this.data;var parse=function(itemType){return data[itemType].getItem().setCH(uaCH).parseCH().get()};this.set(UA_BROWSER,parse(UA_BROWSER)).set(UA_CPU,parse(UA_CPU)).set(UA_DEVICE,parse(UA_DEVICE)).set(UA_ENGINE,parse(UA_ENGINE)).set(UA_OS,parse(UA_OS))}return this};setProps.call(this,[["itemType",itemType],["ua",ua],["uaCH",uaCH],["rgxMap",rgxMap],["data",createIData(this,itemType)]]);return this}function UAParser(ua,extensions,headers){if(typeof ua===OBJ_TYPE){if(isExtensions(ua,true)){if(typeof extensions===OBJ_TYPE){headers=extensions}extensions=ua}else{headers=ua;extensions=undefined}ua=undefined}else if(typeof ua===STR_TYPE&&!isExtensions(extensions,true)){headers=extensions;extensions=undefined}if(!(this instanceof UAParser)){return new UAParser(ua,extensions,headers).getResult()}var userAgent=typeof ua===STR_TYPE?ua:NAVIGATOR&&NAVIGATOR.userAgent?NAVIGATOR.userAgent:headers&&headers[USER_AGENT]?headers[USER_AGENT]:EMPTY,httpUACH=new UACHData(headers,true),regexMap=extensions?extend(defaultRegexes,extensions):defaultRegexes,createItemFunc=function(itemType){if(itemType==UA_RESULT){return function(){return new UAItem(itemType,userAgent,regexMap,httpUACH).set("ua",userAgent).set(UA_BROWSER,this.getBrowser()).set(UA_CPU,this.getCPU()).set(UA_DEVICE,this.getDevice()).set(UA_ENGINE,this.getEngine()).set(UA_OS,this.getOS()).get()}}else{return function(){return new UAItem(itemType,userAgent,regexMap[itemType],httpUACH).parseUA().get()}}};setProps.call(this,[["getBrowser",createItemFunc(UA_BROWSER)],["getCPU",createItemFunc(UA_CPU)],["getDevice",createItemFunc(UA_DEVICE)],["getEngine",createItemFunc(UA_ENGINE)],["getOS",createItemFunc(UA_OS)],["getResult",createItemFunc(UA_RESULT)],["getUA",function(){return userAgent}],["setUA",function(ua){if(isString(ua))userAgent=ua.length>UA_MAX_LENGTH?trim(ua,UA_MAX_LENGTH):ua;return this}]]).setUA(userAgent);return this}UAParser.VERSION=LIBVERSION;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]);if(typeof exports!==UNDEF_TYPE){if(typeof module!==UNDEF_TYPE&&module.exports){exports=module.exports=UAParser}exports.UAParser=UAParser}else{if(typeof define===FUNC_TYPE&&define.amd){define(function(){return UAParser})}else if(isWindow){window.UAParser=UAParser}}var $=isWindow&&(window.jQuery||window.Zepto);if($&&!$.ua){var parser=new UAParser;$.ua=parser.getResult();$.ua.get=function(){return parser.getUA()};$.ua.set=function(ua){parser.setUA(ua);var result=parser.getResult();for(var prop in result){$.ua[prop]=result[prop]}}}})(typeof window==="object"?window:this); \ No newline at end of file +(function(window,undefined){"use strict";var LIBVERSION="2.0.0-rc.1",EMPTY="",UNKNOWN="?",FUNC_TYPE="function",UNDEF_TYPE="undefined",OBJ_TYPE="object",STR_TYPE="string",MAJOR="major",MODEL="model",NAME="name",TYPE="type",VENDOR="vendor",VERSION="version",ARCHITECTURE="architecture",CONSOLE="console",MOBILE="mobile",TABLET="tablet",SMARTTV="smarttv",WEARABLE="wearable",XR="xr",EMBEDDED="embedded",USER_AGENT="user-agent",UA_MAX_LENGTH=500,BRANDS="brands",FORMFACTORS="formFactors",FULLVERLIST="fullVersionList",PLATFORM="platform",PLATFORMVER="platformVersion",BITNESS="bitness",CH_HEADER="sec-ch-ua",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,FORMFACTORS,BITNESS],UA_BROWSER="browser",UA_CPU="cpu",UA_DEVICE="device",UA_ENGINE="engine",UA_OS="os",UA_RESULT="result",AMAZON="Amazon",APPLE="Apple",ASUS="ASUS",BLACKBERRY="BlackBerry",GOOGLE="Google",HUAWEI="Huawei",LENOVO="Lenovo",LG="LG",MICROSOFT="Microsoft",MOTOROLA="Motorola",SAMSUNG="Samsung",SHARP="Sharp",SONY="Sony",XIAOMI="Xiaomi",ZEBRA="Zebra",PREFIX_MOBILE="Mobile ",SUFFIX_BROWSER=" Browser",CHROME="Chrome",CHROMECAST="Chromecast",EDGE="Edge",FIREFOX="Firefox",OPERA="Opera",FACEBOOK="Facebook",SOGOU="Sogou",WINDOWS="Windows";var isWindow=typeof window!==UNDEF_TYPE,NAVIGATOR=isWindow&&window.navigator?window.navigator:undefined,NAVIGATOR_UADATA=NAVIGATOR&&NAVIGATOR.userAgentData?NAVIGATOR.userAgentData:undefined;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]:[])}}}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={};for(var i=0;i0){for(var i in str1){if(lowerize(str1[i])==lowerize(str2))return true}return false}return isString(str1)?lowerize(str2).indexOf(lowerize(str1))!==-1:false},isExtensions=function(obj,deep){for(var prop in obj){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(",");for(var i=0;i-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 isString(str)?str.toLowerCase():str},majorize=function(version){return isString(version)?strip(/[^\d\.]/g,version).split(".")[0]:undefined},setProps=function(arr){for(var i in arr){var propName=arr[i];if(typeof propName==OBJ_TYPE&&propName.length==2){this[propName[0]]=propName[1]}else{this[propName]=undefined}}return this},strip=function(pattern,str){return isString(str)?str.replace(pattern,EMPTY):str},stripQuotes=function(str){return strip(/\\?\"/g,str)},trim=function(str,len){if(isString(str)){str=strip(/^\s\s*/,str);return typeof len===UNDEF_TYPE?str:str.substring(0,UA_MAX_LENGTH)}};var rgxMapper=function(ua,arrays){if(!ua||!arrays)return;var i=0,j,k,p,q,matches,match;while(i0){if(q.length===2){if(typeof q[1]==FUNC_TYPE){this[q[0]]=q[1].call(this,match)}else{this[q[0]]=q[1]}}else if(q.length===3){if(typeof q[1]===FUNC_TYPE&&!(q[1].exec&&q[1].test)){this[q[0]]=match?q[1].call(this,match,q[2]):undefined}else{this[q[0]]=match?match.replace(q[1],q[2]):undefined}}else if(q.length===4){this[q[0]]=match?q[3].call(this,match.replace(q[1],q[2])):undefined}}else{this[q]=match?match:undefined}}}}i+=2}},strMapper=function(str,map){for(var i in map){if(typeof map[i]===OBJ_TYPE&&map[i].length>0){for(var j=0;j2){this.set(MODEL,"iPad").set(TYPE,TABLET)}break;case UA_OS:if(!this.get(NAME)&&NAVIGATOR_UADATA&&NAVIGATOR_UADATA[PLATFORM]){this.set(NAME,NAVIGATOR_UADATA[PLATFORM])}break;case UA_RESULT:var data=this.data;var detect=function(itemType){return data[itemType].getItem().detectFeature().get()};this.set(UA_BROWSER,detect(UA_BROWSER)).set(UA_CPU,detect(UA_CPU)).set(UA_DEVICE,detect(UA_DEVICE)).set(UA_ENGINE,detect(UA_ENGINE)).set(UA_OS,detect(UA_OS))}}return this};this.parseUA=function(){if(this.itemType!=UA_RESULT){rgxMapper.call(this.data,this.ua,this.rgxMap)}if(this.itemType==UA_BROWSER){this.set(MAJOR,majorize(this.get(VERSION)))}return this};this.parseCH=function(){var uaCH=this.uaCH,rgxMap=this.rgxMap;switch(this.itemType){case UA_BROWSER:var brands=uaCH[FULLVERLIST]||uaCH[BRANDS],prevName;if(brands){for(var i in brands){var brandName=strip(/(Google|Microsoft) /,brands[i].brand||brands[i]),brandVersion=brands[i].version;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}}}break;case UA_CPU:var archName=uaCH[ARCHITECTURE];if(archName){if(archName&&uaCH[BITNESS]=="64")archName+="64";rgxMapper.call(this.data,archName+";",rgxMap)}break;case UA_DEVICE:if(uaCH[MOBILE]){this.set(TYPE,MOBILE)}if(uaCH[MODEL]){this.set(MODEL,uaCH[MODEL])}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=13?"11":"10";this.set(NAME,osName).set(VERSION,osVersion)}if(this.get(NAME)==WINDOWS&&uaCH[MODEL]=="Xbox"){this.set(NAME,"Xbox").set(VERSION,undefined)}break;case UA_RESULT:var data=this.data;var parse=function(itemType){return data[itemType].getItem().setCH(uaCH).parseCH().get()};this.set(UA_BROWSER,parse(UA_BROWSER)).set(UA_CPU,parse(UA_CPU)).set(UA_DEVICE,parse(UA_DEVICE)).set(UA_ENGINE,parse(UA_ENGINE)).set(UA_OS,parse(UA_OS))}return this};setProps.call(this,[["itemType",itemType],["ua",ua],["uaCH",uaCH],["rgxMap",rgxMap],["data",createIData(this,itemType)]]);return this}function UAParser(ua,extensions,headers){if(typeof ua===OBJ_TYPE){if(isExtensions(ua,true)){if(typeof extensions===OBJ_TYPE){headers=extensions}extensions=ua}else{headers=ua;extensions=undefined}ua=undefined}else if(typeof ua===STR_TYPE&&!isExtensions(extensions,true)){headers=extensions;extensions=undefined}if(!(this instanceof UAParser)){return new UAParser(ua,extensions,headers).getResult()}var userAgent=typeof ua===STR_TYPE?ua:NAVIGATOR&&NAVIGATOR.userAgent?NAVIGATOR.userAgent:headers&&headers[USER_AGENT]?headers[USER_AGENT]:EMPTY,httpUACH=new UACHData(headers,true),regexMap=extensions?extend(defaultRegexes,extensions):defaultRegexes,createItemFunc=function(itemType){if(itemType==UA_RESULT){return function(){return new UAItem(itemType,userAgent,regexMap,httpUACH).set("ua",userAgent).set(UA_BROWSER,this.getBrowser()).set(UA_CPU,this.getCPU()).set(UA_DEVICE,this.getDevice()).set(UA_ENGINE,this.getEngine()).set(UA_OS,this.getOS()).get()}}else{return function(){return new UAItem(itemType,userAgent,regexMap[itemType],httpUACH).parseUA().get()}}};setProps.call(this,[["getBrowser",createItemFunc(UA_BROWSER)],["getCPU",createItemFunc(UA_CPU)],["getDevice",createItemFunc(UA_DEVICE)],["getEngine",createItemFunc(UA_ENGINE)],["getOS",createItemFunc(UA_OS)],["getResult",createItemFunc(UA_RESULT)],["getUA",function(){return userAgent}],["setUA",function(ua){if(isString(ua))userAgent=ua.length>UA_MAX_LENGTH?trim(ua,UA_MAX_LENGTH):ua;return this}]]).setUA(userAgent);return this}UAParser.VERSION=LIBVERSION;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]);if(typeof exports!==UNDEF_TYPE){if(typeof module!==UNDEF_TYPE&&module.exports){exports=module.exports=UAParser}exports.UAParser=UAParser}else{if(typeof define===FUNC_TYPE&&define.amd){define(function(){return UAParser})}else if(isWindow){window.UAParser=UAParser}}var $=isWindow&&(window.jQuery||window.Zepto);if($&&!$.ua){var parser=new UAParser;$.ua=parser.getResult();$.ua.get=function(){return parser.getUA()};$.ua.set=function(ua){parser.setUA(ua);var result=parser.getResult();for(var prop in result){$.ua[prop]=result[prop]}}}})(typeof window==="object"?window:this); \ No newline at end of file diff --git a/dist/ua-parser.pack.js b/dist/ua-parser.pack.js index 5b538966c..e22b892ce 100644 --- a/dist/ua-parser.pack.js +++ b/dist/ua-parser.pack.js @@ -1,4 +1,4 @@ -/* UAParser.js v2.0.0-beta.3 +/* UAParser.js v2.0.0-rc.1 Copyright © 2012-2024 Faisal Salman AGPLv3 License */ -!function(i,c){"use strict";function e(i){for(var e={},t=0;t_?Si(i,_):i),this}]]).setUA(o),this}Ui.VERSION="2.0.0-beta.3",Ui.BROWSER=e([f,v,p,m]),Ui.CPU=e([x]),Ui.DEVICE=e([h,g,m,k,y,t,r,o,a]),Ui.ENGINE=Ui.OS=e([f,v]),typeof exports!==b?(typeof module!==b&&module.exports&&(exports=module.exports=Ui),exports.UAParser=Ui):typeof define===u&&define.amd?define(function(){return Ui}):ui&&(i.UAParser=Ui);var Hi,Ei=ui&&(i.jQuery||i.Zepto);Ei&&!Ei.ua&&(Hi=new Ui,Ei.ua=Hi.getResult(),Ei.ua.get=function(){return Hi.getUA()},Ei.ua.set=function(i){Hi.setUA(i);var e,t=Hi.getResult();for(e in t)Ei.ua[e]=t[e]})}("object"==typeof window?window:this); \ No newline at end of file +!function(i,c){"use strict";function e(i){for(var e={},t=0;tS?Ti(i,S):i),this}]]).setUA(o),this}Ui.VERSION="2.0.0-rc.1",Ui.BROWSER=e([m,v,h,f]),Ui.CPU=e([k]),Ui.DEVICE=e([p,g,f,x,y,t,r,o,d]),Ui.ENGINE=Ui.OS=e([m,v]),typeof exports!==b?(typeof module!==b&&module.exports&&(exports=module.exports=Ui),exports.UAParser=Ui):typeof define===l&&define.amd?define(function(){return Ui}):ui&&(i.UAParser=Ui);var ji,Ei=ui&&(i.jQuery||i.Zepto);Ei&&!Ei.ua&&(ji=new Ui,Ei.ua=ji.getResult(),Ei.ua.get=function(){return ji.getUA()},Ei.ua.set=function(i){ji.setUA(i);var e,t=ji.getResult();for(e in t)Ei.ua[e]=t[e]})}("object"==typeof window?window:this); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index c1e325174..1c4d590fc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ua-parser-js", - "version": "2.0.0-beta.3", + "version": "2.0.0-rc.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "ua-parser-js", - "version": "2.0.0-beta.3", + "version": "2.0.0-rc.1", "funding": [ { "type": "opencollective", diff --git a/package.json b/package.json index 6a7d31ac2..7674e9273 100755 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "title": "UAParser.js", "name": "ua-parser-js", - "version": "2.0.0-beta.3", + "version": "2.0.0-rc.1", "author": "Faisal Salman (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": [ diff --git a/src/enums/ua-parser-enums.js b/src/enums/ua-parser-enums.js index e80a0d57a..4fc06b4d0 100644 --- a/src/enums/ua-parser-enums.js +++ b/src/enums/ua-parser-enums.js @@ -1,5 +1,5 @@ /////////////////////////////////////////////// -/* Enums for UAParser.js v2.0.0-beta.3 +/* Enums for UAParser.js v2.0.0-rc.1 https://github.com/faisalman/ua-parser-js Author: Faisal Salman AGPLv3 License */ diff --git a/src/enums/ua-parser-enums.mjs b/src/enums/ua-parser-enums.mjs index 539cf3059..52df47f6e 100644 --- a/src/enums/ua-parser-enums.mjs +++ b/src/enums/ua-parser-enums.mjs @@ -3,7 +3,7 @@ // Source: /src/enums/ua-parser-enums.js /////////////////////////////////////////////// -/* Enums for UAParser.js v2.0.0-beta.3 +/* Enums for UAParser.js v2.0.0-rc.1 https://github.com/faisalman/ua-parser-js Author: Faisal Salman AGPLv3 License */ @@ -12,8 +12,8 @@ /*jshint esversion: 6 */ const Browser = Object.freeze({ - _2345_EXPLORER: '2345Explorer', - _360: '360 Browser', + '2345_EXPLORER': '2345Explorer', + '360': '360 Browser', ALIPAY: 'Alipay', AMAYA: 'Amaya', ANDROID: 'Android Browser', @@ -56,6 +56,7 @@ const Browser = Object.freeze({ FLOW: 'Flow', GO: 'GoBrowser', GOOGLE_SEARCH: 'GSA', + HELIO: 'Helio', HEYTAP: 'HeyTap', HUAWEI: 'Huawei Browser', ICAB: 'iCab', @@ -161,6 +162,7 @@ const BrowserType = Object.freeze({ }); const CPU = Object.freeze({ + '68K': '68k', ARM : 'arm', ARM_64: 'arm64', ARM_HF: 'armhf', @@ -171,7 +173,6 @@ const CPU = Object.freeze({ IRIX_64: 'irix64', MIPS: 'mips', MIPS_64: 'mips64', - M68K: '68k', PA_RISC: 'pa-risc', PPC: 'ppc', SPARC: 'sparc', @@ -212,6 +213,7 @@ const Vendor = Object.freeze({ HTC: 'HTC', HUAWEI: 'Huawei', INFINIX: 'Infinix', + ITEL: 'itel', JOLLA: 'Jolla', KOBO: 'Kobo', LENOVO: 'Lenovo', @@ -222,6 +224,7 @@ const Vendor = Object.freeze({ NEXIAN: 'Nexian', NINTENDO: 'Nintendo', NOKIA: 'Nokia', + NOTHING: 'Nothing', NVIDIA: 'Nvidia', ONEPLUS: 'OnePlus', OPPO: 'OPPO', @@ -239,6 +242,7 @@ const Vendor = Object.freeze({ SIEMENS: 'Siemens', SONY: 'Sony', SPRINT: 'Sprint', + TCL: 'TCL', TECHNISAT: 'TechniSAT', TECNO: 'Tecno', TESLA: 'Tesla', @@ -255,6 +259,7 @@ const Vendor = Object.freeze({ const Engine = Object.freeze({ AMAYA: 'Amaya', + ARKWEB: 'ArkWeb', BLINK: 'Blink', EDGEHTML: 'EdgeHTML', FLOW: 'Flow', @@ -321,6 +326,7 @@ const OS = Object.freeze({ NETRANGE: 'NetRange', NETTV: 'NetTV', NINTENDO: 'Nintendo', + OPENHARMONY: 'OpenHarmony', OPENBSD: 'OpenBSD', OPENVMS: 'OpenVMS', OS2: 'OS/2', @@ -347,7 +353,6 @@ const OS = Object.freeze({ UBUNTU: 'Ubuntu', UNIX: 'Unix', VECTORLINUX: 'VectorLinux', - VIERA: 'Viera', WATCHOS: 'watchOS', WEBOS: 'WebOS', WINDOWS: 'Windows', diff --git a/src/extensions/ua-parser-extensions.js b/src/extensions/ua-parser-extensions.js index a50145daf..124fe9923 100644 --- a/src/extensions/ua-parser-extensions.js +++ b/src/extensions/ua-parser-extensions.js @@ -1,5 +1,5 @@ /////////////////////////////////////////////// -/* Extensions for UAParser.js v2.0.0-beta.3 +/* Extensions for UAParser.js v2.0.0-rc.1 https://github.com/faisalman/ua-parser-js Author: Faisal Salman AGPLv3 License */ diff --git a/src/extensions/ua-parser-extensions.mjs b/src/extensions/ua-parser-extensions.mjs index 192889056..bf12ddf64 100644 --- a/src/extensions/ua-parser-extensions.mjs +++ b/src/extensions/ua-parser-extensions.mjs @@ -3,7 +3,7 @@ // Source: /src/extensions/ua-parser-extensions.js /////////////////////////////////////////////// -/* Extensions for UAParser.js v2.0.0-beta.3 +/* Extensions for UAParser.js v2.0.0-rc.1 https://github.com/faisalman/ua-parser-js Author: Faisal Salman AGPLv3 License */ @@ -23,6 +23,7 @@ const CLI = 'cli'; const EMAIL = 'email'; const FETCHER = 'fetcher'; const INAPP = 'inapp'; +const MEDIAPLAYER = 'mediaplayer'; const MODULE = 'module'; ////////////////////// @@ -42,45 +43,48 @@ const CLIs = Object.freeze({ 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 - // MJ12bot - https://mj12bot.com/ - // SemrushBot - http://www.semrush.com/bot.html - [/((?:amazon|apple|bing|duckduck|facebook|gpt|mj12|semrush)bot)\/([\w\.]+)/i], - [NAME, VERSION, [TYPE, CRAWLER]], + [ + // AhrefsBot - https://ahrefs.com/robot + // Amazonbot - https://developer.amazon.com/amazonbot + // Applebot - http://apple.com/go/applebot + // Bingbot - http://www.bing.com/bingbot.htm + // Dotbot - https://moz.com/help/moz-procedures/crawlers/dotbot + // DuckDuckBot - http://duckduckgo.com/duckduckbot.html + // FacebookBot - https://developers.facebook.com/docs/sharing/bot/ + // GPTBot - https://platform.openai.com/docs/gptbot + // MJ12bot - https://mj12bot.com/ + // OpenAI Search - https://platform.openai.com/docs/bots + // SemrushBot - http://www.semrush.com/bot.html + /((?:ahrefs|amazon|apple|bing|dot|duckduck|facebook|gpt|mj12|oai-search|semrush)bot)\/([\w\.]+)/i, - // Baiduspider https://help.baidu.com/question?prod_id=99&class=0&id=3001 - [/(baiduspider)[-imagevdonsfcpr]{0,6}\/([\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, - // Bytespider - // Yahoo! Slurp - http://help.yahoo.com/help/us/ysearch/slurp - [/((?:bytespider|(?=yahoo! )slurp))/i], - [NAME, [TYPE, CRAWLER]], + // ClaudeBot + /(claude(?:bot|-web))\/([\w\.]+)/i, - // ClaudeBot - [/(claude(?:bot|-web))\/([\w\.]+)/i], - [NAME, VERSION, [TYPE, CRAWLER]], + // Coc Coc Bot - https://help.coccoc.com/en/search-engine + /(coccocbot-(?:image|web))\/([\w\.]+)/i, + + // Googlebot - http://www.google.com/bot.html + /(google(?:bot|other)(?:-image|-video|-news|-extended)?|(?:storebot-)?google(?:-inspectiontool)?)\/?([\w\.]*)/i, + + // Sogou Spider + /(sogou (?:pic|head|web|orion|news) spider)\/([\w\.]+)/i, + + // Yahoo! Japan - https://support.yahoo-net.jp/PccSearch/s/article/H000007955 + /(y!?j-(?:asr|br[uw]|dscv|mmp|vsidx|wsc))\/([\w\.]+)/i, + + // 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 + ], - // 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]] + // Bytespider + // Yahoo! Slurp - http://help.yahoo.com/help/us/ysearch/slurp + [/((?:bytespider|(?=yahoo! )slurp))/i], + [NAME, [TYPE, CRAWLER]] ] }); @@ -181,29 +185,30 @@ const Emails = Object.freeze({ 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]], - + [ + // AhrefsSiteAudit - https://ahrefs.com/robot/site-audit + // ChatGPT-User - https://platform.openai.com/docs/plugins/bot + // BingPreview / Mastodon / Pinterestbot / Redditbot / Rogerbot / Telegrambot / Twitterbot / UptimeRobot + /(ahrefssiteaudit|bingpreview|chatgpt-user|mastodon|(?:discord|linkedin|pinterest|reddit|roger|telegram|twitter|uptimero)bot)\/([\w\.]+)/i, - // Slackbot - https://api.slack.com/robots - [/(slack(?:bot)?(?:-imgproxy|-linkexpanding)?) ([\w\.]+)/i], - [NAME, VERSION, [TYPE, FETCHER]], + // Slackbot - https://api.slack.com/robots + /(slack(?:bot)?(?:-imgproxy|-linkexpanding)?) ([\w\.]+)/i, + + // WhatsApp + /(whatsapp)\/([\w\.]+)[\/ ][ianw]/i, - // WhatsApp - [/(whatsapp)\/([\w\.]+)[\/ ][ianw]/i], - [NAME, VERSION, [TYPE, FETCHER]], + // Yahoo! Japan + /(y!?j-dlc)\/([\w\.]+)/i, - // Yandex Bots - https://yandex.com/bots - [ + // Yandex Bots - https://yandex.com/bots /(yandex(?:calendar|direct(?:dyn)?|searchshop)|yadirectfetcher)\/([\w\.]+)/i, /(yandex(?:sitelinks|userproxy))/i ], - [NAME, VERSION, [TYPE, FETCHER]] + [NAME, VERSION, [TYPE, FETCHER]], + + // Google Bots / Snapchat + [/(feedfetcher-google|google-read-aloud|(?=bot; )snapchat)/i], + [NAME, [TYPE, FETCHER]], ] }); @@ -213,7 +218,11 @@ const Fetchers = Object.freeze({ const InApps = Object.freeze({ browser : [ - [/chatlyio\/([\d\.]+)/i], [VERSION, 'Slack', [TYPE, INAPP]] + // Slack + [/chatlyio\/([\d\.]+)/i], [VERSION, 'Slack', [TYPE, INAPP]], + + // Yahoo! Japan + [/jp\.co\.yahoo\.android\.yjtop\/([\d\.]+)/i], [VERSION, 'Yahoo! Japan', [TYPE, INAPP]] ] }); @@ -226,13 +235,13 @@ const MediaPlayers = Object.freeze({ /(apple(?:coremedia|))\/([\w\._]+)/i, // Generic Apple CoreMedia /(coremedia) v([\w\._]+)/i - ], [NAME, VERSION], [ + ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [ /(aqualung|lyssna|bsplayer)\/([\w\.-]+)/i // Aqualung/Lyssna/BSPlayer - ], [NAME, VERSION], [ + ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [ /(ares|ossproxy)\s([\w\.-]+)/i // Ares/OSSProxy - ], [NAME, VERSION], [ + ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [ /(audacious|audimusicstream|amarok|bass|core|dalvik|gnomemplayer|music on console|nsplayer|psp-internetradioplayer|videos)\/([\w\.-]+)/i, // Audacious/AudiMusicStream/Amarok/BASS/OpenCORE/Dalvik/GnomeMplayer/MoC @@ -240,90 +249,90 @@ const MediaPlayers = Object.freeze({ /(clementine|music player daemon)\s([\w\.-]+)/i, // Clementine/MPD /(lg player|nexplayer)\s([\d\.]+)/i, /player\/(nexplayer|lg player)\s([\w\.-]+)/i // NexPlayer/LG Player - ], [NAME, VERSION], [ + ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [ /(nexplayer)\s([\w\.-]+)/i // Nexplayer - ], [NAME, VERSION], [ + ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [ /(flrp)\/([\w\.-]+)/i // Flip Player - ], [[NAME, 'Flip Player'], VERSION], [ + ], [[NAME, 'Flip Player'], VERSION, [TYPE, MEDIAPLAYER]], [ /(fstream|nativehost|queryseekspider|ia-archiver|facebookexternalhit)/i // FStream/NativeHost/QuerySeekSpider/IA Archiver/facebookexternalhit - ], [NAME], [ + ], [NAME, [TYPE, MEDIAPLAYER]], [ /(gstreamer) souphttpsrc.+libsoup\/([\w\.-]+)/i // Gstreamer - ], [NAME, VERSION], [ + ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [ /(htc streaming player)\s[\w_]+\s\/\s([\d\.]+)/i, // HTC Streaming Player /(java|python-urllib|python-requests|wget|libcurl)\/([\w\.-_]+)/i, // Java/urllib/requests/wget/cURL /(lavf)([\d\.]+)/i // Lavf (FFMPEG) - ], [NAME, VERSION], [ + ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [ /(htc_one_s)\/([\d\.]+)/i, // HTC One S - ], [[NAME, /_/g, ' '], VERSION], [ + ], [[NAME, /_/g, ' '], VERSION, [TYPE, MEDIAPLAYER]], [ /(mplayer)(?:\s|\/)(?:(?:sherpya-){0,1}svn)(?:-|\s)(r\d+(?:-\d+[\w\.-]+))/i, // MPlayer SVN - ], [NAME, VERSION], [ + ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [ /(mplayer)(?:\s|\/)([\w\.-]+)/i, // MPlayer /(mplayer) unknown-([\w\.\-]+)/i // MPlayer UNKNOWN - ], [NAME, VERSION], [ + ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [ /(mplayer)/i, // MPlayer (no other info) /(yourmuze)/i, // YourMuze /(media player classic|nero showtime)/i // Media Player Classic/Nero ShowTime - ], [NAME], [ + ], [NAME, [TYPE, MEDIAPLAYER]], [ /(nero (?:home|scout))\/([\w\.-]+)/i // Nero Home/Nero Scout - ], [NAME, VERSION], [ + ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [ /(nokia\d+)\/([\w\.-]+)/i // Nokia - ], [NAME, VERSION], [ + ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [ /\s(songbird)\/([\w\.-]+)/i // Songbird/Philips-Songbird - ], [NAME, VERSION], [ + ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [ /(winamp)3 version ([\w\.-]+)/i, // Winamp /(winamp)\s([\w\.-]+)/i, /(winamp)mpeg\/([\w\.-]+)/i - ], [NAME, VERSION], [ + ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [ /(ocms-bot|tapinradio|tunein radio|unknown|winamp|inlight radio)/i // OCMS-bot/tap in radio/tunein/unknown/winamp (no other info) // inlight radio - ], [NAME], [ + ], [NAME, [TYPE, MEDIAPLAYER]], [ /(quicktime|rma|radioapp|radioclientapplication|soundtap|totem|stagefright|streamium)\/([\w\.-]+)/i // QuickTime/RealMedia/RadioApp/RadioClientApplication/ // SoundTap/Totem/Stagefright/Streamium - ], [NAME, VERSION], [ + ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [ /(smp)([\d\.]+)/i // SMP - ], [NAME, VERSION], [ + ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [ /(vlc) media player - version ([\w\.]+)/i, // VLC Videolan /(vlc)\/([\w\.-]+)/i, /(xbmc|gvfs|xine|xmms|irapp)\/([\w\.-]+)/i, // XBMC/gvfs/Xine/XMMS/irapp /(foobar2000)\/([\d\.]+)/i, // Foobar2000 /(itunes)\/([\d\.]+)/i // iTunes - ], [NAME, VERSION], [ + ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [ /(wmplayer)\/([\w\.-]+)/i, // Windows Media Player /(windows-media-player)\/([\w\.-]+)/i - ], [[NAME, /-/g, ' '], VERSION], [ + ], [[NAME, /-/g, ' '], VERSION, [TYPE, MEDIAPLAYER]], [ /windows\/([\w\.-]+) upnp\/[\d\.]+ dlnadoc\/[\d\.]+ (home media server)/i, // Windows Media Server - ], [VERSION, [NAME, 'Windows']], [ + ], [VERSION, [NAME, 'Windows'], [TYPE, MEDIAPLAYER]], [ /(com\.riseupradioalarm)\/([\d\.]*)/i // RiseUP Radio Alarm - ], [NAME, VERSION], [ + ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [ /(rad.io)\s([\d\.]+)/i, // Rad.io /(radio.(?:de|at|fr))\s([\d\.]+)/i - ], [[NAME, 'rad.io'], VERSION] + ], [[NAME, 'rad.io'], VERSION, [TYPE, MEDIAPLAYER]] ] }); @@ -338,7 +347,21 @@ const Modules = Object.freeze({ ] }); +////////// +// BOTS +///////// + +const Bots = Object.freeze({ + browser : [ + ...CLIs.browser, + ...Crawlers.browser, + ...Fetchers.browser, + ...Modules.browser + ] +}); + export { + Bots, CLIs, Crawlers, ExtraDevices, diff --git a/src/helpers/ua-parser-helpers.js b/src/helpers/ua-parser-helpers.js index 8582fe5b4..61c63bbb6 100644 --- a/src/helpers/ua-parser-helpers.js +++ b/src/helpers/ua-parser-helpers.js @@ -1,5 +1,5 @@ /////////////////////////////////////////////// -/* Helpers for UAParser.js v2.0.0-beta.3 +/* Helpers for UAParser.js v2.0.0-rc.1 https://github.com/faisalman/ua-parser-js Author: Faisal Salman AGPLv3 License */ diff --git a/src/helpers/ua-parser-helpers.mjs b/src/helpers/ua-parser-helpers.mjs index 95d6c0f17..886d0dc31 100644 --- a/src/helpers/ua-parser-helpers.mjs +++ b/src/helpers/ua-parser-helpers.mjs @@ -3,7 +3,7 @@ // Source: /src/helpers/ua-parser-helpers.js /////////////////////////////////////////////// -/* Helpers for UAParser.js v2.0.0-beta.3 +/* Helpers for UAParser.js v2.0.0-rc.1 https://github.com/faisalman/ua-parser-js Author: Faisal Salman AGPLv3 License */ @@ -11,16 +11,55 @@ /*jshint esversion: 6 */ -import { CPU, OS, Engine } from '../enums/ua-parser-enums.mjs'; +import { CPU, OS, Engine } from './enums/ua-parser-enums.mjs'; +import { UAParser } from './main/ua-parser.mjs'; +import { isFromEU } from 'detect-europe-js'; -const isAppleSilicon = (res) => res.os.is(OS.MACOS) && res.cpu.is(CPU.ARM); +const getDeviceVendor = (model) => UAParser(`Mozilla/5.0 (Linux; Android 10; ${model}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.0.0 Safari/537.36`).device.vendor; -const isChromiumBased = (res) => res.engine.is(Engine.BLINK); +const isAppleSilicon = (res) => { + if (res.os.is(OS.MACOS)) { + if (res.cpu.is(CPU.ARM)) { + return true; + } + try { + const canvas = document.createElement('canvas'); + const webgl = canvas.getContext('webgl2') || canvas.getContext('webgl') || canvas.getContext('experimental-webgl'); + const debug = webgl.getExtension('WEBGL_debug_renderer_info'); + const renderer = webgl.getParameter(debug.UNMASKED_RENDERER_WEBGL); + if (renderer.match(/apple m\d/i)) { + return true; + } + } catch { + return false; + } + } + return false; +} + +const isChromeFamily = (res) => res.engine.is(Engine.BLINK); + +const isElectron = () => !!(process?.versions?.hasOwnProperty('electron') || // node.js + / electron\//i.test(navigator?.userAgent)); // browser 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); +const isStandalonePWA = () => window && (window.matchMedia('(display-mode: standalone)').matches || + // iOS + navigator.standalone || + // Android + document.referrer.startsWith('android-app://') || + // Windows + window.Windows || + /trident.+(msapphost|webview)\//i.test(navigator.userAgent) || + document.referrer.startsWith('app-info://platform/microsoft-store')); + export { + getDeviceVendor, isAppleSilicon, - isChromiumBased, - isFrozenUA + isChromeFamily, + isElectron, + isFromEU, + isFrozenUA, + isStandalonePWA } \ No newline at end of file diff --git a/src/main/ua-parser.js b/src/main/ua-parser.js index 0eb24efd1..07d59086a 100755 --- a/src/main/ua-parser.js +++ b/src/main/ua-parser.js @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////////// -/* UAParser.js v2.0.0-beta.3 +/* UAParser.js v2.0.0-rc.1 Copyright © 2012-2024 Faisal Salman AGPLv3 License *//* Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data. @@ -19,7 +19,7 @@ // Constants ///////////// - var LIBVERSION = '2.0.0-beta.3', + var LIBVERSION = '2.0.0-rc.1', EMPTY = '', UNKNOWN = '?', FUNC_TYPE = 'function', diff --git a/src/main/ua-parser.mjs b/src/main/ua-parser.mjs index e0e4f4ed3..e9861fc5c 100644 --- a/src/main/ua-parser.mjs +++ b/src/main/ua-parser.mjs @@ -3,12 +3,12 @@ // Source: /src/main/ua-parser.js ///////////////////////////////////////////////////////////////////////////////// -/* UAParser.js v2.0.0-beta.3 +/* UAParser.js v2.0.0-rc.1 Copyright © 2012-2024 Faisal Salman AGPLv3 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,7 +21,7 @@ // Constants ///////////// - var LIBVERSION = '2.0.0-beta.3', + var LIBVERSION = '2.0.0-rc.1', EMPTY = '', UNKNOWN = '?', FUNC_TYPE = 'function', @@ -84,6 +84,7 @@ PREFIX_MOBILE = 'Mobile ', SUFFIX_BROWSER = ' Browser', CHROME = 'Chrome', + CHROMECAST = 'Chromecast', EDGE = 'Edge', FIREFOX = 'Firefox', OPERA = 'Opera', @@ -329,11 +330,13 @@ /(?: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|duckduckgo|klar)\/([-\w\.]+)/i, - // Rekonq/Puffin/Brave/Whale/QQBrowserLite/QQ//Vivaldi/DuckDuckGo/Klar + /(flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi|iridium|phantomjs|bowser|qupzilla|falkon|rekonq|puffin|brave|whale(?!.+naver)|qqbrowserlite|duckduckgo|klar|helio)\/([-\w\.]+)/i, + // Rekonq/Puffin/Brave/Whale/QQBrowserLite/QQ//Vivaldi/DuckDuckGo/Klar/Helio /(heytap|ovi)browser\/([\d\.]+)/i, // HeyTap/Ovi /(weibo)__([\d\.]+)/i // Weibo ], [NAME, VERSION], [ + /quark(?:pc)?\/([-\w\.]+)/i // Quark + ], [VERSION, [NAME, 'Quark']], [ /\bddg\/([\w\.]+)/i // DuckDuckGo ], [VERSION, [NAME, 'DuckDuckGo']], [ /(?:\buc? ?browser|(?:juc.+)ucweb)[\/ ]?([\w\.]+)/i // UCBrowser @@ -499,8 +502,8 @@ // Samsung /\b(sch-i[89]0\d|shw-m380s|sm-[ptx]\w{2,4}|gt-[pn]\d{2,4}|sgh-t8[56]9|nexus 10)/i ], [MODEL, [VENDOR, SAMSUNG], [TYPE, TABLET]], [ - /\b((?:s[cgp]h|gt|sm)-\w+|sc[g-]?[\d]+a?|galaxy nexus)/i, - /samsung[- ]([-\w]+)/i, + /\b((?:s[cgp]h|gt|sm)-(?![lr])\w+|sc[g-]?[\d]+a?|galaxy nexus)/i, + /samsung[- ]((?!sm-[lr])[-\w]+)/i, /sec-(sgh\w+)/i ], [MODEL, [VENDOR, SAMSUNG], [TYPE, MOBILE]], [ @@ -531,7 +534,7 @@ /\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 + /\b(mi[-_ ]?(?:a\d|one|one[_ ]plus|note lte|max|cc)?[_ ]?(?:\d?\w?)[_ ]?(?:plus|se|lite|pro)?)(?: 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 @@ -599,7 +602,7 @@ // Amazon /(alexa)webm/i, - /(kf[a-z]{2}wi|aeo[c-r]{2})( bui|\))/i, // Kindle Fire without Silk / Echo Show + /(kf[a-z]{2}wi|aeo(?!bc)\w\w)( bui|\))/i, // Kindle Fire without Silk / Echo Show /(kf[a-z]+)( bui|\)).+silk\//i // Kindle Fire HD ], [MODEL, [VENDOR, AMAZON], [TYPE, TABLET]], [ /((?:sd|kf)[0349hijorstuw]+)( bui|\)).+silk\//i // Fire Phone @@ -628,6 +631,17 @@ /(alcatel|geeksphone|nexian|panasonic(?!(?:;|\.))|sony(?!-bra))[-_ ]?([-\w]*)/i // Alcatel/GeeksPhone/Nexian/Panasonic/Sony ], [VENDOR, [MODEL, /_/g, ' '], [TYPE, MOBILE]], [ + // TCL + /tcl (xess p17aa)/i, + /droid [\w\.]+; ((?:8[14]9[16]|9(?:0(?:48|60|8[01])|1(?:3[27]|66)|2(?:6[69]|9[56])|466))[gqswx])(_\w(\w|\w\w))?(\)| bui)/i + ], [MODEL, [VENDOR, 'TCL'], [TYPE, TABLET]], [ + /droid [\w\.]+; (418(?:7d|8v)|5087z|5102l|61(?:02[dh]|25[adfh]|27[ai]|56[dh]|59k|65[ah])|a509dl|t(?:43(?:0w|1[adepqu])|50(?:6d|7[adju])|6(?:09dl|10k|12b|71[efho]|76[hjk])|7(?:66[ahju]|67[hw]|7[045][bh]|71[hk]|73o|76[ho]|79w|81[hks]?|82h|90[bhsy]|99b)|810[hs]))(_\w(\w|\w\w))?(\)| bui)/i + ], [MODEL, [VENDOR, 'TCL'], [TYPE, MOBILE]], [ + + // itel + /(itel) ((\w+))/i + ], [[VENDOR, lowerize], MODEL, [TYPE, strMapper, { 'tablet' : ['p10001l', 'w7001'], '*' : 'mobile' }]], [ + // Acer /droid.+; ([ab][1-7]-?[0178a]\d\d?)/i ], [MODEL, [VENDOR, 'Acer'], [TYPE, TABLET]], [ @@ -641,6 +655,10 @@ /; ((?:power )?armor(?:[\w ]{0,8}))(?: bui|\))/i ], [MODEL, [VENDOR, 'Ulefone'], [TYPE, MOBILE]], [ + // Nothing + /droid.+; (a(?:015|06[35]|142p?))/i + ], [MODEL, [VENDOR, 'Nothing'], [TYPE, MOBILE]], [ + // MIXED /(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus|dell|meizu|motorola|polytron|infinix|tecno)[-_ ]?([-\w]*)/i, // BlackBerry/BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron @@ -685,8 +703,14 @@ ], [[VENDOR, LG], [TYPE, SMARTTV]], [ /(apple) ?tv/i // Apple TV ], [VENDOR, [MODEL, APPLE+' TV'], [TYPE, SMARTTV]], [ - /crkey/i // Google Chromecast - ], [[MODEL, CHROME+'cast'], [VENDOR, GOOGLE], [TYPE, SMARTTV]], [ + /crkey.*devicetype\/chromecast/i // Google Chromecast Third Generation + ], [[MODEL, CHROMECAST+' Third Generation'], [VENDOR, GOOGLE], [TYPE, SMARTTV]], [ + /crkey.*devicetype\/([^/]*)/i // Google Chromecast with specific device type + ], [[MODEL, /^/, 'Chromecast '], [VENDOR, GOOGLE], [TYPE, SMARTTV]], [ + /fuchsia.*crkey/i // Google Chromecast Nest Hub + ], [[MODEL, CHROMECAST+' Nest Hub'], [VENDOR, GOOGLE], [TYPE, SMARTTV]], [ + /crkey/i // Google Chromecast, Linux-based or unknown + ], [[MODEL, CHROMECAST], [VENDOR, GOOGLE], [TYPE, SMARTTV]], [ /droid.+aft(\w+)( bui|\))/i // Fire TV ], [MODEL, [VENDOR, AMAZON], [TYPE, SMARTTV]], [ /\(dtv[\);].+(aquos)/i, @@ -722,6 +746,8 @@ // WEARABLES /////////////////// + /\b(sm-[lr]\d\d[05][fnuw]?s?)\b/i // Samsung Galaxy Watch + ], [MODEL, [VENDOR, SAMSUNG], [TYPE, WEARABLE]], [ /((pebble))app/i // Pebble ], [VENDOR, MODEL, [TYPE, WEARABLE]], [ /(watch)(?: ?os[,\/]|\d,\d\/)[\d\.]+/i // Apple Watch @@ -735,7 +761,9 @@ /droid.+; (glass) \d/i // Google Glass ], [MODEL, [VENDOR, GOOGLE], [TYPE, XR]], [ - /(quest( \d| pro)?)/i // Oculus Quest + /(pico) (4|neo3(?: link|pro)?)/i // Pico + ], [VENDOR, MODEL, [TYPE, XR]], [ + /; (quest( \d| pro)?)/i // Oculus Quest ], [MODEL, [VENDOR, FACEBOOK], [TYPE, XR]], [ /////////////////// @@ -768,6 +796,9 @@ /windows.+ edge\/([\w\.]+)/i // EdgeHTML ], [VERSION, [NAME, EDGE+'HTML']], [ + /(arkweb)\/([\w\.]+)/i // ArkWeb + ], [NAME, VERSION], [ + /webkit\/537\.36.+chrome\/(?!27)([\w\.]+)/i // Blink ], [VERSION, [NAME, 'Blink']], [ @@ -804,10 +835,22 @@ /(macintosh|mac_powerpc\b)(?!.+haiku)/i // Mac OS ], [[NAME, 'macOS'], [VERSION, /_/g, '.']], [ + // Google Chromecast + /android ([\d\.]+).*crkey/i // Google Chromecast, Android-based + ], [VERSION, [NAME, CHROMECAST + ' Android']], [ + /fuchsia.*crkey\/([\d\.]+)/i // Google Chromecast, Fuchsia-based + ], [VERSION, [NAME, CHROMECAST + ' Fuchsia']], [ + /crkey\/([\d\.]+).*devicetype\/smartspeaker/i // Google Chromecast, Linux-based Smart Speaker + ], [VERSION, [NAME, CHROMECAST + ' SmartSpeaker']], [ + /linux.*crkey\/([\d\.]+)/i // Google Chromecast, Legacy Linux-based + ], [VERSION, [NAME, CHROMECAST + ' Linux']], [ + /crkey\/([\d\.]+)/i // Google Chromecast, unknown + ], [VERSION, [NAME, CHROMECAST]], [ + // Mobile OSes /droid ([\w\.]+)\b.+(android[- ]x86|harmonyos)/i // Android-x86/HarmonyOS - ], [VERSION, NAME], [ // Android/WebOS/QNX/Bada/RIM/Maemo/MeeGo/Sailfish OS - /(android|webos|qnx|bada|rim tablet os|maemo|meego|sailfish)[-\/ ]?([\w\.]*)/i, + ], [VERSION, NAME], [ // Android/WebOS/QNX/Bada/RIM/Maemo/MeeGo/Sailfish OS/OpenHarmony + /(android|webos|qnx|bada|rim tablet os|maemo|meego|sailfish|openharmony)[-\/ ]?([\w\.]*)/i, /(blackberry)\w*\/([\w\.]*)/i, // Blackberry /(tizen|kaios)[\/ ]([\w\.]+)/i, // Tizen/KaiOS /\((series40);/i // Series 40 @@ -824,9 +867,7 @@ /watch(?: ?os[,\/]|\d,\d\/)([\d\.]+)/i // watchOS ], [VERSION, [NAME, 'watchOS']], [ - // Google Chromecast - /crkey\/([\d\.]+)/i // Google Chromecast - ], [VERSION, [NAME, CHROME+'cast']], [ + // Google ChromeOS /(cros) [\w]+(?:\)| ([\w\.]+)\b)/i // Chromium OS ], [[NAME, "Chrome OS"], VERSION],[ @@ -838,6 +879,7 @@ // Console /(nintendo|playstation) (\w+)/i, // Nintendo/Playstation /(xbox); +xbox ([^\);]+)/i, // Microsoft Xbox (360, One, X, S, Series X, Series S) + /(pico) .+os([\w\.]+)/i, // Pico // Other /\b(joli|palm)\b ?(?:os)?\/?([\w\.]*)/i, // Joli/Palm From 7a754ef227cbee03d1da1fd1e518a10978cbc27a Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Sat, 2 Nov 2024 12:27:42 +0700 Subject: [PATCH 41/64] Update browser.type="inapp" for InApp browsers --- src/main/ua-parser.js | 19 ++++++---- test/mocha-test.js | 2 +- test/specs/browser-all.json | 69 ++++++++++++++++++++++++------------- 3 files changed, 59 insertions(+), 31 deletions(-) diff --git a/src/main/ua-parser.js b/src/main/ua-parser.js index 07d59086a..8290e5cdf 100755 --- a/src/main/ua-parser.js +++ b/src/main/ua-parser.js @@ -40,6 +40,7 @@ WEARABLE = 'wearable', XR = 'xr', EMBEDDED = 'embedded', + INAPP = 'inapp', USER_AGENT = 'user-agent', UA_MAX_LENGTH = 500, BRANDS = 'brands', @@ -385,13 +386,12 @@ /(tesla)(?: qtcarbrowser|\/(20\d\d\.[-\w\.]+))/i, // Tesla /m?(qqbrowser|2345Explorer)[\/ ]?([\w\.]+)/i // QQBrowser/2345 Browser ], [NAME, VERSION], [ - /(lbbrowser|rekonq)/i, // LieBao Browser/Rekonq - /\[(linkedin)app\]/i // LinkedIn App for iOS & Android + /(lbbrowser|rekonq)/i // LieBao Browser/Rekonq ], [NAME], [ // WebView /((?:fban\/fbios|fb_iab\/fb4a)(?!.+fbav)|;fbav\/([\w\.]+);)/i // Facebook App for iOS & Android - ], [[NAME, FACEBOOK], VERSION], [ + ], [[NAME, FACEBOOK], VERSION, [TYPE, INAPP]], [ /(Klarna)\/([\w\.]+)/i, // Klarna Shopping Browser for iOS & Android /(kakao(?:talk|story))[\/ ]([\w\.]+)/i, // Kakao App /(naver)\(.*?(\d+\.[\w\.]+).*\)/i, // Naver InApp @@ -399,12 +399,17 @@ /\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], [ + /(instagram|snapchat)[\/ ]([-\w\.]+)/i // Instagram/Snapchat + ], [NAME, VERSION, [TYPE, INAPP]], [ /\bgsa\/([\w\.]+) .*safari\//i // Google Search Appliance on iOS - ], [VERSION, [NAME, 'GSA']], [ + ], [VERSION, [NAME, 'GSA'], [TYPE, INAPP]], [ /musical_ly(?:.+app_?version\/|_)([\w\.]+)/i // TikTok - ], [VERSION, [NAME, 'TikTok']], [ + ], [VERSION, [NAME, 'TikTok'], [TYPE, INAPP]], [ + /\[(linkedin)app\]/i // LinkedIn App for iOS & Android + ], [NAME, [TYPE, INAPP]], [ + + /(chromium)[\/ ]([-\w\.]+)/i // Chromium + ], [NAME, VERSION], [ /headlesschrome(?:\/([\w\.]+)| )/i // Chrome Headless ], [VERSION, [NAME, CHROME+' Headless']], [ diff --git a/test/mocha-test.js b/test/mocha-test.js index 7b5e71173..68213ac9b 100644 --- a/test/mocha-test.js +++ b/test/mocha-test.js @@ -17,7 +17,7 @@ var methods = [ title : 'getBrowser', label : 'browser', list : browsers, - properties : ['name', 'major', 'version'] + properties : ['name', 'major', 'version', 'type'] }, { title : 'getCPU', diff --git a/test/specs/browser-all.json b/test/specs/browser-all.json index d8638b06f..a69e84892 100644 --- a/test/specs/browser-all.json +++ b/test/specs/browser-all.json @@ -16,7 +16,8 @@ { "name" : "Alipay", "version" : "10.2.51.7100", - "major" : "10" + "major" : "10", + "type" : "inapp" } }, { @@ -26,7 +27,8 @@ { "name" : "Alipay", "version" : "10.3.50.9999", - "major" : "10" + "major" : "10", + "type" : "inapp" } }, { @@ -536,7 +538,8 @@ { "name" : "Facebook", "version" : "35.0.0.48.273", - "major" : "35" + "major" : "35", + "type" : "inapp" } }, { @@ -546,7 +549,8 @@ { "name" : "Facebook", "version" : "91.0.0.41.73", - "major" : "91" + "major" : "91", + "type" : "inapp" } }, { @@ -556,7 +560,8 @@ { "name" : "Facebook", "version" : "undefined", - "major" : "undefined" + "major" : "undefined", + "type" : "inapp" } }, { @@ -566,7 +571,8 @@ { "name" : "Klarna", "version" : "23.36.223", - "major" : "23" + "major" : "23", + "type" : "inapp" } }, { @@ -576,7 +582,8 @@ { "name" : "Klarna", "version" : "23.36.215", - "major" : "23" + "major" : "23", + "type" : "inapp" } }, { @@ -586,7 +593,8 @@ { "name" : "Instagram", "version" : "142.0.0.22.109", - "major" : "142" + "major" : "142", + "type" : "inapp" } }, { @@ -975,7 +983,8 @@ { "name" : "Line", "version" : "6.5.1", - "major" : "6" + "major" : "6", + "type" : "inapp" } }, { @@ -985,7 +994,8 @@ { "name" : "Line", "version" : "8.4.1", - "major" : "8" + "major" : "8", + "type" : "inapp" } }, { @@ -2056,7 +2066,8 @@ { "name" : "GSA", "version" : "30.1.161623614", - "major" : "30" + "major" : "30", + "type" : "inapp" } }, { @@ -2152,7 +2163,8 @@ "ua" : "Mozilla/5.0 (iPhone; CPU iPhone OS 15_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 [LinkedInApp]", "expect" : { - "name" : "LinkedIn" + "name" : "LinkedIn", + "type" : "inapp" } }, { @@ -2257,7 +2269,8 @@ "expect" : { "name" : "KAKAOTALK", "version": "2409760", - "major" : "2409760" + "major" : "2409760", + "type" : "inapp" } }, { @@ -2266,7 +2279,8 @@ "expect" : { "name" : "KAKAOSTORY", "version": "6.8.3_21046", - "major" : "6" + "major" : "6", + "type" : "inapp" } }, { @@ -2275,7 +2289,8 @@ "expect" : { "name" : "KAKAOTALK", "version": "9.7.6", - "major" : "9" + "major" : "9", + "type" : "inapp" } }, { @@ -2284,7 +2299,8 @@ "expect" : { "name" : "NAVER", "version": "11.11.2", - "major" : "11" + "major" : "11", + "type" : "inapp" } }, { @@ -2293,7 +2309,8 @@ "expect" : { "name" : "NAVER", "version": "10.25.0", - "major" : "10" + "major" : "10", + "type" : "inapp" } }, { @@ -2302,7 +2319,8 @@ "expect" : { "name" : "TikTok", "version": "21.9.4", - "major" : "21" + "major" : "21", + "type" : "inapp" } }, { @@ -2311,7 +2329,8 @@ "expect" : { "name" : "TikTok", "version": "21.1.0", - "major" : "21" + "major" : "21", + "type" : "inapp" } }, { @@ -2320,7 +2339,8 @@ "expect" : { "name" : "TikTok", "version": "28.3.4", - "major" : "28" + "major" : "28", + "type" : "inapp" } }, { @@ -2360,7 +2380,8 @@ { "name" : "Snapchat", "version" : "12.33.0.36", - "major" : "12" + "major" : "12", + "type" : "inapp" } }, { @@ -2370,7 +2391,8 @@ { "name" : "Twitter", "version" : "undefined", - "major" : "undefined" + "major" : "undefined", + "type" : "inapp" } }, { @@ -2380,7 +2402,8 @@ { "name" : "Twitter", "version" : "10.34", - "major" : "10" + "major" : "10", + "type" : "inapp" } } ] \ No newline at end of file From 5a1d0319f811e71c09b41e99d4f37d37f59fca48 Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Sat, 2 Nov 2024 13:15:33 +0700 Subject: [PATCH 42/64] Add new helper method: `isBot()` to detect whether current browser is a bot --- src/helpers/ua-parser-helpers.d.ts | 2 ++ src/helpers/ua-parser-helpers.js | 3 +++ test/mocha-test-helpers.js | 20 +++++++++++++++++++- 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/helpers/ua-parser-helpers.d.ts b/src/helpers/ua-parser-helpers.d.ts index e8dd9d358..7074c229d 100644 --- a/src/helpers/ua-parser-helpers.d.ts +++ b/src/helpers/ua-parser-helpers.d.ts @@ -6,6 +6,7 @@ import { IResult } from "../main/ua-parser"; declare function getDeviceVendor(model: string): string | undefined; declare function isAppleSilicon(res: IResult): boolean; +declare function isBot(res: IResult): boolean; declare function isChromeFamily(res: IResult): boolean; declare function isElectron(): boolean; declare function isFromEU(): boolean; @@ -15,6 +16,7 @@ declare function isStandalonePWA(): boolean; export { getDeviceVendor, isAppleSilicon, + isBot, isChromeFamily, isElectron, isFromEU, diff --git a/src/helpers/ua-parser-helpers.js b/src/helpers/ua-parser-helpers.js index 61c63bbb6..d5e35a00c 100644 --- a/src/helpers/ua-parser-helpers.js +++ b/src/helpers/ua-parser-helpers.js @@ -33,6 +33,8 @@ const isAppleSilicon = (res) => { return false; } +const isBot = (res) => ['cli', 'crawler', 'fetcher', 'module'].includes(res.browser.type); + const isChromeFamily = (res) => res.engine.is(Engine.BLINK); const isElectron = () => !!(process?.versions?.hasOwnProperty('electron') || // node.js @@ -53,6 +55,7 @@ const isStandalonePWA = () => window && (window.matchMedia('(display-mode: stand module.exports = { getDeviceVendor, isAppleSilicon, + isBot, isChromeFamily, isElectron, isFromEU, diff --git a/test/mocha-test-helpers.js b/test/mocha-test-helpers.js index da9ae2c85..ab61cd939 100644 --- a/test/mocha-test-helpers.js +++ b/test/mocha-test-helpers.js @@ -1,6 +1,7 @@ const assert = require('assert'); const { UAParser } = require('../src/main/ua-parser'); -const { getDeviceVendor, isAppleSilicon, isChromeFamily } = require('../src/helpers/ua-parser-helpers'); +const { getDeviceVendor, isAppleSilicon, isBot, isChromeFamily } = require('../src/helpers/ua-parser-helpers'); +const { Bots, Emails } = require('../src/extensions/ua-parser-extensions'); describe('getDeviceVendor', () => { it('Can guess the device vendor from a model name', () => { @@ -31,6 +32,23 @@ describe('isAppleSilicon', () => { }); }); +describe('isBot', () => { + it('Can detect Bots', () => { + + // non-real ua + const ahrefsBot = 'Mozilla/5.0 (compatible; AhrefsBot/7.0; +http://ahrefs.com/robot/)'; + const firefox = 'Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/111.0'; + const scrapy = 'Scrapy/1.5.0 (+https://scrapy.org)'; + const thunderbird = 'Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.13.0'; + + const botParser = new UAParser(firefox, { Bots, Emails }); + assert.equal(isBot(botParser.getResult()), false); + assert.equal(isBot(botParser.setUA(ahrefsBot).getResult()), true); + assert.equal(isBot(botParser.setUA(scrapy).getResult()), true); + assert.equal(isBot(botParser.setUA(thunderbird).getResult()), false); + }); +}); + describe('isChromeFamily', () => { it('Can detect Chromium-based browser', () => { From 10b81836f106a8c0c245bfba464e5bebbe4f5878 Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Sat, 2 Nov 2024 18:26:35 +0700 Subject: [PATCH 43/64] Improve browser detection: SRWare Iron --- src/main/ua-parser.js | 4 +++- test/specs/browser-all.json | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/main/ua-parser.js b/src/main/ua-parser.js index 8290e5cdf..95914f135 100755 --- a/src/main/ua-parser.js +++ b/src/main/ua-parser.js @@ -328,7 +328,7 @@ /(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 + // Blink/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|qupzilla|falkon|rekonq|puffin|brave|whale(?!.+naver)|qqbrowserlite|duckduckgo|klar|helio)\/([-\w\.]+)/i, // Rekonq/Puffin/Brave/Whale/QQBrowserLite/QQ//Vivaldi/DuckDuckGo/Klar/Helio /(heytap|ovi)browser\/([\d\.]+)/i, // HeyTap/Ovi @@ -388,6 +388,8 @@ ], [NAME, VERSION], [ /(lbbrowser|rekonq)/i // LieBao Browser/Rekonq ], [NAME], [ + /ome\/([\w\.]+) \w* ?(iron) saf/i // Iron + ], [VERSION, NAME], [ // WebView /((?:fban\/fbios|fb_iab\/fb4a)(?!.+fbav)|;fbav\/([\w\.]+);)/i // Facebook App for iOS & Android diff --git a/test/specs/browser-all.json b/test/specs/browser-all.json index a69e84892..edf0d8b0e 100644 --- a/test/specs/browser-all.json +++ b/test/specs/browser-all.json @@ -856,6 +856,26 @@ "major" : "22" } }, + { + "desc" : "Iron", + "ua" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Iron Safari/537.36", + "expect" : + { + "name" : "Iron", + "version" : "129.0.0.0", + "major" : "129" + } + }, + { + "desc" : "Iron", + "ua" : "Mozilla/5.0 (Linux; Android 11; Pixel 4 XL) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Mobile Iron Safari/537.36", + "expect" : + { + "name" : "Iron", + "version" : "113.0.0.0", + "major" : "113" + } + }, { "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", From b7c2f541d9ce000f031e04efd150df96d625a1eb Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Sat, 2 Nov 2024 19:53:09 +0700 Subject: [PATCH 44/64] Add new browsers: Slimjet & SlimBoat https://www.slimjet.com/ --- src/enums/ua-parser-enums.js | 2 ++ src/main/ua-parser.js | 2 +- test/specs/browser-all.json | 22 +++++++++++++++++++++- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/enums/ua-parser-enums.js b/src/enums/ua-parser-enums.js index 4fc06b4d0..be4b2afb6 100644 --- a/src/enums/ua-parser-enums.js +++ b/src/enums/ua-parser-enums.js @@ -122,7 +122,9 @@ const Browser = Object.freeze({ SILK: 'Silk', SKYFIRE: 'Skyfire', SLEIPNIR: 'Sleipnir', + SLIMBOAT: 'SlimBoat', SLIMBROWSER: 'SlimBrowser', + SLIMJET: 'Slimjet', SNAPCHAT: 'Snapchat', SOGOU_EXPLORER: 'Sogou Explorer', SOGOU_MOBILE: 'Sogou Mobile', diff --git a/src/main/ua-parser.js b/src/main/ua-parser.js index 95914f135..937d197d3 100755 --- a/src/main/ua-parser.js +++ b/src/main/ua-parser.js @@ -325,7 +325,7 @@ /(lunascape|maxthon|netfront|jasmine|blazer|sleipnir)[\/ ]?([\w\.]*)/i, // Lunascape/Maxthon/Netfront/Jasmine/Blazer/Sleipnir // Trident based - /(avant|iemobile|slim)\s?(?:browser)?[\/ ]?([\w\.]*)/i, // Avant/IEMobile/SlimBrowser + /(avant|iemobile|slim(?:browser|boat|jet))[\/ ]?([\d\.]*)/i, // Avant/IEMobile/SlimBrowser/SlimBoat/Slimjet /(?:ms|\()(ie) ([\w\.]+)/i, // Internet Explorer // Blink/Webkit/KHTML based // Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS/Bowser/QupZilla/Falkon diff --git a/test/specs/browser-all.json b/test/specs/browser-all.json index edf0d8b0e..b8fd74be5 100644 --- a/test/specs/browser-all.json +++ b/test/specs/browser-all.json @@ -1629,16 +1629,36 @@ "major" : "2" } }, + { + "desc" : "SlimBoat", + "ua" : "Mozilla/5.0 (Windows NT 5.2) AppleWebKit/534.34 (KHTML, like Gecko) SlimBoat/1.1.23 Chrome/11.0.696.7 Version/5.1 Safari/534.34", + "expect" : + { + "name" : "SlimBoat", + "version" : "1.1.23", + "major" : "1" + } + }, { "desc" : "SlimBrowser", "ua" : "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SlimBrowser)", "expect" : { - "name" : "Slim", + "name" : "SlimBrowser", "version" : "undefined", "major" : "undefined" } }, + { + "desc" : "Slimjet", + "ua" : "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.75 Safari/537.36 Slimjet/20.0.2.0", + "expect" : + { + "name" : "Slimjet", + "version" : "20.0.2.0", + "major" : "20" + } + }, { "desc" : "Swiftfox", "ua" : "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1) Gecko/20061024 Firefox/2.0 (Swiftfox)", From d571859b2e1f0d323a584eefdd637e4af1696582 Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Sat, 2 Nov 2024 20:08:10 +0700 Subject: [PATCH 45/64] Improve browser detection: `Comodo Dragon`, or simply `Dragon` --- src/enums/ua-parser-enums.js | 2 +- src/main/ua-parser.js | 6 ++---- test/specs/browser-all.json | 12 +++++++++++- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/enums/ua-parser-enums.js b/src/enums/ua-parser-enums.js index be4b2afb6..4ba852563 100644 --- a/src/enums/ua-parser-enums.js +++ b/src/enums/ua-parser-enums.js @@ -32,11 +32,11 @@ const Browser = Object.freeze({ CHROMIUM: 'Chromium', COBALT: 'Cobalt', COC_COC: 'Coc Coc', - COMODO_DRAGON: 'Comodo Dragon', CONKEROR: 'Conkeror', DILLO: 'Dillo', DOLPHIN: 'Dolphin', DORIS: 'Doris', + DRAGON: 'Dragon', DUCKDUCKGO: 'DuckDuckGo', EDGE: 'Edge', EPIPHANY: 'Epiphany', diff --git a/src/main/ua-parser.js b/src/main/ua-parser.js index 937d197d3..7120be2f4 100755 --- a/src/main/ua-parser.js +++ b/src/main/ua-parser.js @@ -329,8 +329,8 @@ /(?:ms|\()(ie) ([\w\.]+)/i, // Internet Explorer // Blink/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|qupzilla|falkon|rekonq|puffin|brave|whale(?!.+naver)|qqbrowserlite|duckduckgo|klar|helio)\/([-\w\.]+)/i, - // Rekonq/Puffin/Brave/Whale/QQBrowserLite/QQ//Vivaldi/DuckDuckGo/Klar/Helio + /(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)\/([-\w\.]+)/i, + // Rekonq/Puffin/Brave/Whale/QQBrowserLite/QQ//Vivaldi/DuckDuckGo/Klar/Helio/Dragon /(heytap|ovi)browser\/([\d\.]+)/i, // HeyTap/Ovi /(weibo)__([\d\.]+)/i // Weibo ], [NAME, VERSION], [ @@ -376,8 +376,6 @@ ], [[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 diff --git a/test/specs/browser-all.json b/test/specs/browser-all.json index b8fd74be5..abafca798 100644 --- a/test/specs/browser-all.json +++ b/test/specs/browser-all.json @@ -406,11 +406,21 @@ "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", + "name" : "Dragon", "version" : "16.1.1.0", "major" : "16" } }, + { + "desc" : "Comodo Dragon", + "ua" : "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Dragon/98.0.4758.102 Chrome/98.0.4758.102 Safari/537.36", + "expect" : + { + "name" : "Dragon", + "version" : "98.0.4758.102", + "major" : "98" + } + }, { "desc" : "Conkeror", "ua" : "Mozilla/5.0 (X11; Linux x86_64; rv:6.0.1) Gecko/20110831 conkeror/0.9.3", From 2624a92b39cc89cbae7cf3deb35cab9b806d4c94 Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Sun, 3 Nov 2024 01:15:06 +0700 Subject: [PATCH 46/64] Improve browser detection: `2345` & `360` --- src/enums/ua-parser-enums.js | 4 +-- src/main/ua-parser.js | 9 ++--- test/specs/browser-all.json | 66 +++++++++++++++++++++++++++++------- 3 files changed, 60 insertions(+), 19 deletions(-) diff --git a/src/enums/ua-parser-enums.js b/src/enums/ua-parser-enums.js index 4ba852563..a81f623c5 100644 --- a/src/enums/ua-parser-enums.js +++ b/src/enums/ua-parser-enums.js @@ -8,8 +8,8 @@ /*jshint esversion: 6 */ const Browser = Object.freeze({ - '2345_EXPLORER': '2345Explorer', - '360': '360 Browser', + '2345': '2345', + '360': '360', ALIPAY: 'Alipay', AMAYA: 'Amaya', ANDROID: 'Android Browser', diff --git a/src/main/ua-parser.js b/src/main/ua-parser.js index 7120be2f4..babc7e5cd 100755 --- a/src/main/ua-parser.js +++ b/src/main/ua-parser.js @@ -368,8 +368,8 @@ ], [VERSION, [NAME, 'MIUI' + SUFFIX_BROWSER]], [ /fxios\/([\w\.-]+)/i // Firefox for iOS ], [VERSION, [NAME, PREFIX_MOBILE + FIREFOX]], [ - /\bqihu|(qi?ho?o?|360)browser/i // 360 - ], [[NAME, '360' + SUFFIX_BROWSER]], [ + /\bqihoobrowser\/?([\w\.]*)/i // 360 + ], [VERSION, [NAME, '360']], [ /\b(qq)\/([\w\.]+)/i // QQ ], [[NAME, /(.+)/, '$1Browser'], VERSION], [ /(oculus|sailfish|huawei|vivo|pico)browser\/([\w\.]+)/i @@ -382,11 +382,12 @@ ], [[NAME, SOGOU + ' Mobile'], VERSION], [ /(electron)\/([\w\.]+) safari/i, // Electron-based App /(tesla)(?: qtcarbrowser|\/(20\d\d\.[-\w\.]+))/i, // Tesla - /m?(qqbrowser|2345Explorer)[\/ ]?([\w\.]+)/i // QQBrowser/2345 Browser + /m?(qqbrowser|2345(?=browser|chrome|explorer))\w*[\/ ]?v?([\w\.]+)/i // QQ/2345 ], [NAME, VERSION], [ /(lbbrowser|rekonq)/i // LieBao Browser/Rekonq ], [NAME], [ - /ome\/([\w\.]+) \w* ?(iron) saf/i // Iron + /ome\/([\w\.]+) \w* ?(iron) saf/i, // Iron + /ome\/([\w\.]+).+qihu (360)[es]e/i // 360 ], [VERSION, NAME], [ // WebView diff --git a/test/specs/browser-all.json b/test/specs/browser-all.json index abafca798..db978de7c 100644 --- a/test/specs/browser-all.json +++ b/test/specs/browser-all.json @@ -1,12 +1,62 @@ [ + { + "desc" : "2345 Browser", + "ua" : "Mozilla/5.0 (Linux; Android 7.0; MI NOTE Pro Build/NRD90M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/61.0.3163.98 Mobile Safari/537.36 Mb2345Browser/15.6.2", + "expect" : + { + "name" : "2345", + "version" : "15.6.2", + "major" : "15" + } + }, + { + "desc" : "2345 Chrome", + "ua" : "Mozilla/5.0 (Windows NT 6.3) AppleWebKit/537.36 (KHTML like Gecko) Chrome/39.0.2171.99 Safari/537.36 2345chrome v3.0.0.9739", + "expect" : + { + "name" : "2345", + "version" : "3.0.0.9739", + "major" : "3" + } + }, + { + "desc" : "2345 Explorer", + "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", + "expect" : + { + "name" : "2345", + "version" : "9.2.1.17116", + "major" : "9" + } + }, { "desc" : "360 Browser on iOS", "ua" : "Mozilla/5.0 (iPhone; CPU iPhone OS 12_4_1 like Mac OS X) AppleWebKit/607.3.9 (KHTML, like Gecko) Mobile/16G102 QHBrowser/317 QihooBrowser/4.0.10", "expect" : { - "name" : "360 Browser", - "version" : "undefined", - "major" : "undefined" + "name" : "360", + "version" : "4.0.10", + "major" : "4" + } + }, + { + "desc" : "360 Secure Browser on Windows 10", + "ua" : "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36 QIHU 360SE", + "expect" : + { + "name" : "360", + "version" : "86.0.4240.198", + "major" : "86" + } + }, + { + "desc" : "360 Speed Browser on Windows 10", + "ua" : "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36 QIHU 360EE", + "expect" : + { + "name" : "360", + "version" : "86.0.4240.198", + "major" : "86" } }, { @@ -2148,16 +2198,6 @@ "name" : "LBBROWSER" } }, - { - "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", - "expect" : - { - "name" : "2345Explorer", - "version" : "9.2.1.17116", - "major" : "9" - } - }, { "desc" : "QQBrowserLite", "ua" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/602.2.14 (KHTML, like Gecko) Version/10.0.1 Safari/602.2.14 QQBrowserLite/1.1.0", From 2dc1be1a50c354d1723cf21bc21ad5b3d88969e9 Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Sun, 3 Nov 2024 01:34:55 +0700 Subject: [PATCH 47/64] Add new browser: `115 Browser` http://pc.115.com/ --- src/enums/ua-parser-enums.js | 1 + src/main/ua-parser.js | 2 +- test/specs/browser-all.json | 10 ++++++++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/enums/ua-parser-enums.js b/src/enums/ua-parser-enums.js index a81f623c5..5cbf3ac17 100644 --- a/src/enums/ua-parser-enums.js +++ b/src/enums/ua-parser-enums.js @@ -8,6 +8,7 @@ /*jshint esversion: 6 */ const Browser = Object.freeze({ + '115': '115', '2345': '2345', '360': '360', ALIPAY: 'Alipay', diff --git a/src/main/ua-parser.js b/src/main/ua-parser.js index babc7e5cd..c0d7907d0 100755 --- a/src/main/ua-parser.js +++ b/src/main/ua-parser.js @@ -331,7 +331,7 @@ // Blink/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|qupzilla|falkon|rekonq|puffin|brave|whale(?!.+naver)|qqbrowserlite|duckduckgo|klar|helio|(?=comodo_)?dragon)\/([-\w\.]+)/i, // Rekonq/Puffin/Brave/Whale/QQBrowserLite/QQ//Vivaldi/DuckDuckGo/Klar/Helio/Dragon - /(heytap|ovi)browser\/([\d\.]+)/i, // HeyTap/Ovi + /(heytap|ovi|115)browser\/([\d\.]+)/i, // HeyTap/Ovi/115 /(weibo)__([\d\.]+)/i // Weibo ], [NAME, VERSION], [ /quark(?:pc)?\/([-\w\.]+)/i // Quark diff --git a/test/specs/browser-all.json b/test/specs/browser-all.json index db978de7c..ebf10d9cd 100644 --- a/test/specs/browser-all.json +++ b/test/specs/browser-all.json @@ -1,4 +1,14 @@ [ + { + "desc" : "115 Browser", + "ua" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_16_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36 115Browser/24.3.0.3", + "expect" : + { + "name" : "115", + "version" : "24.3.0.3", + "major" : "24" + } + }, { "desc" : "2345 Browser", "ua" : "Mozilla/5.0 (Linux; Android 7.0; MI NOTE Pro Build/NRD90M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/61.0.3163.98 Mobile Safari/537.36 Mb2345Browser/15.6.2", From 246c0388950ce2ff789294953ec955301e4ef661 Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Sun, 3 Nov 2024 11:17:30 +0700 Subject: [PATCH 48/64] Improve browser detection: `Maxthon` --- src/main/ua-parser.js | 2 ++ test/specs/browser-all.json | 62 ++++++++++++++++++++++++++++++++++++- 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/src/main/ua-parser.js b/src/main/ua-parser.js index c0d7907d0..b2beb6828 100755 --- a/src/main/ua-parser.js +++ b/src/main/ua-parser.js @@ -321,6 +321,8 @@ // Mixed /\bb[ai]*d(?:uhd|[ub]*[aekoprswx]{5,6})[\/ ]?([\w\.]+)/i // Baidu ], [VERSION, [NAME, 'Baidu']], [ + /\b(?:mxbrowser|mxios|myie2)\/?([-\w\.]*)\b/i // Maxthon + ], [VERSION, [NAME, 'Maxthon']], [ /(kindle)\/([\w\.]+)/i, // Kindle /(lunascape|maxthon|netfront|jasmine|blazer|sleipnir)[\/ ]?([\w\.]*)/i, // Lunascape/Maxthon/Netfront/Jasmine/Blazer/Sleipnir diff --git a/test/specs/browser-all.json b/test/specs/browser-all.json index ebf10d9cd..25bb48fd4 100644 --- a/test/specs/browser-all.json +++ b/test/specs/browser-all.json @@ -1119,7 +1119,57 @@ } }, { - "desc" : "Maxthon", + "desc" : "Maxthon on Android", + "ua" : "Mozilla/5.0 (Linux; Android 5.1.1; KFAUWI Build/LVY48F; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/100.0.4896.127 Safari/537.36 MxBrowser/4.3.5.2000", + "expect" : + { + "name" : "Maxthon", + "version" : "4.3.5.2000", + "major" : "4" + } + }, + { + "desc" : "Maxthon on iOS", + "ua" : "Mozilla/5.0 (iPad; CPU OS 13_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/10.0 Mobile/15E148 Safari/602.1 MXiOS/5.4.5.2", + "expect" : + { + "name" : "Maxthon", + "version" : "5.4.5.2", + "major" : "5" + } + }, + { + "desc" : "Maxthon on Linux", + "ua" : "Mozilla/5.0 (X11; Linux i686; Ubuntu 14.04.3 LTS) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.0 Maxthon/1.0.5.3 Safari/537.36", + "expect" : + { + "name" : "Maxthon", + "version" : "1.0.5.3", + "major" : "1" + } + }, + { + "desc" : "Maxthon on macOS", + "ua" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/604.5.6 (KHTML, like Gecko) Version/11.0.3 Safari/604.5.6 Maxthon/5.1.102", + "expect" : + { + "name" : "Maxthon", + "version" : "5.1.102", + "major" : "5" + } + }, + { + "desc" : "Maxthon on Windows Server 2003", + "ua" : "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; MyIE2; .NET CLR 1.1.4322)", + "expect" : + { + "name" : "Maxthon", + "version" : "undefined", + "major" : "undefined" + } + }, + { + "desc" : "Maxthon on Windows XP", "ua" : "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; SV1; Maxthon; .NET CLR 1.1.4322)", "expect" : { @@ -1128,6 +1178,16 @@ "major" : "undefined" } }, + { + "desc" : "Maxthon on Windows 10", + "ua" : "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36 Maxthon/5.2.7.2000", + "expect" : + { + "name" : "Maxthon", + "version" : "5.2.7.2000", + "major" : "5" + } + }, { "desc" : "Midori", "ua" : "Midori/0.2.2 (X11; Linux i686; U; en-us) WebKit/531.2+", From 2223a2b2d4e48e4d209ab508ede2f8b7dd7c6381 Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Sun, 3 Nov 2024 11:31:22 +0700 Subject: [PATCH 49/64] Add new browser: `LibreWolf` https://librewolf.net/ --- src/enums/ua-parser-enums.js | 1 + src/main/ua-parser.js | 2 +- test/specs/browser-all.json | 20 ++++++++++++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/enums/ua-parser-enums.js b/src/enums/ua-parser-enums.js index 5cbf3ac17..048110746 100644 --- a/src/enums/ua-parser-enums.js +++ b/src/enums/ua-parser-enums.js @@ -75,6 +75,7 @@ const Browser = Object.freeze({ KLARNA: 'Klarna', KINDLE: 'Kindle', LENOVO: 'Smart Lenovo Browser', + LIBREWOLF: 'LibreWolf', LIEBAO: 'LBBROWSER', LINE: 'Line', LINKEDIN: 'LinkedIn', diff --git a/src/main/ua-parser.js b/src/main/ua-parser.js index b2beb6828..242f42a5c 100755 --- a/src/main/ua-parser.js +++ b/src/main/ua-parser.js @@ -446,7 +446,7 @@ ], [[NAME, PREFIX_MOBILE + FIREFOX], VERSION], [ /(navigator|netscape\d?)\/([-\w\.]+)/i // Netscape ], [[NAME, 'Netscape'], VERSION], [ - /(wolvic)\/([\w\.]+)/i // Wolvic + /(wolvic|librewolf)\/([\w\.]+)/i // Wolvic/LibreWolf ], [NAME, VERSION], [ /mobile vr; rv:([\w\.]+)\).+firefox/i // Firefox Reality ], [VERSION, [NAME, FIREFOX+' Reality']], [ diff --git a/test/specs/browser-all.json b/test/specs/browser-all.json index 25bb48fd4..869859786 100644 --- a/test/specs/browser-all.json +++ b/test/specs/browser-all.json @@ -1066,6 +1066,26 @@ "major" : "9" } }, + { + "desc" : "LibreWolf", + "ua" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:91.0) Gecko/20100101 LibreWolf/91.0", + "expect" : + { + "name" : "LibreWolf", + "version" : "91.0", + "major" : "91" + } + }, + { + "desc" : "LibreWolf", + "ua" : "Mozilla/5.0 (X11; Linux x86_64; rv:97.0) Gecko/20100101 Firefox/97.0 LibreWolf/97.0.1", + "expect" : + { + "name" : "LibreWolf", + "version" : "97.0.1", + "major" : "97" + } + }, { "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", From 5097b8093e98f5fdaabc16fe4c8682a69771d6eb Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Mon, 4 Nov 2024 11:10:44 +0700 Subject: [PATCH 50/64] [submodule:enums] Add some of Chromecast OS variants --- src/enums/ua-parser-enums.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/enums/ua-parser-enums.js b/src/enums/ua-parser-enums.js index 048110746..ea4d112b4 100644 --- a/src/enums/ua-parser-enums.js +++ b/src/enums/ua-parser-enums.js @@ -291,6 +291,10 @@ const OS = Object.freeze({ CENTOS: 'CentOS', CHROME_OS: 'Chrome OS', CHROMECAST: 'Chromecast', + CHROMECAST_ANDROID: 'Chromecast Android', + CHROMECAST_FUCHSIA: 'Chromecast Fuchsia', + CHROMECAST_LINUX: 'Chromecast Linux', + CHROMECAST_SMARTSPEAKER: 'Chromecast SmartSpeaker', CONTIKI: 'Contiki', DEBIAN: 'Debian', DEEPIN: 'Deepin', From e954f19b5c9627a6f91f85eb1ac7d7ea48b21c5b Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Tue, 5 Nov 2024 10:46:48 +0700 Subject: [PATCH 51/64] Move `isFrozenUA()` & `isStandalonePWA()` to its own npm module --- package.json | 4 +++- src/helpers/ua-parser-helpers.js | 16 +++------------- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/package.json b/package.json index 7674e9273..c0f93cd79 100755 --- a/package.json +++ b/package.json @@ -211,7 +211,9 @@ "test:playwright": "playwright test" }, "dependencies": { - "detect-europe-js": "^0.1.1" + "detect-europe-js": "^0.1.1", + "is-standalone-pwa": "^0.1.0", + "ua-is-frozen": "^0.1.1" }, "devDependencies": { "@babel/parser": "7.15.8", diff --git a/src/helpers/ua-parser-helpers.js b/src/helpers/ua-parser-helpers.js index d5e35a00c..c8f6925b7 100644 --- a/src/helpers/ua-parser-helpers.js +++ b/src/helpers/ua-parser-helpers.js @@ -7,9 +7,11 @@ /*jshint esversion: 6 */ -const { CPU, OS, Engine } = require('../enums/ua-parser-enums'); const { UAParser } = require('../main/ua-parser'); +const { CPU, OS, Engine } = require('../enums/ua-parser-enums'); const { isFromEU } = require('detect-europe-js'); +const { isFrozenUA } = require('ua-is-frozen'); +const { isStandalonePWA } = require('is-standalone-pwa'); const getDeviceVendor = (model) => UAParser(`Mozilla/5.0 (Linux; Android 10; ${model}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.0.0 Safari/537.36`).device.vendor; @@ -40,18 +42,6 @@ const isChromeFamily = (res) => res.engine.is(Engine.BLINK); const isElectron = () => !!(process?.versions?.hasOwnProperty('electron') || // node.js / electron\//i.test(navigator?.userAgent)); // browser -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); - -const isStandalonePWA = () => window && (window.matchMedia('(display-mode: standalone)').matches || - // iOS - navigator.standalone || - // Android - document.referrer.startsWith('android-app://') || - // Windows - window.Windows || - /trident.+(msapphost|webview)\//i.test(navigator.userAgent) || - document.referrer.startsWith('app-info://platform/microsoft-store')); - module.exports = { getDeviceVendor, isAppleSilicon, From 0808d1d940379a83529325acd7cbed4ce48a8074 Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Thu, 7 Nov 2024 18:34:07 +0700 Subject: [PATCH 52/64] Fix #759 - Incorrect import path for ESM files in build script --- script/build-esm.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/build-esm.js b/script/build-esm.js index 68b8258a0..98f7ffb8b 100755 --- a/script/build-esm.js +++ b/script/build-esm.js @@ -7,7 +7,7 @@ const generateMJS = (module) => { let text = fs.readFileSync(src, 'utf-8'); replacements.push( - [/const (.+?)\s*=\s*require\(\'\.(.+)\'\)/ig, 'import $1 from \'$2.mjs\''], + [/const (.+?)\s*=\s*require\(\'\.(.+)\'\)/ig, 'import $1 from \'\.$2.mjs\''], [/const (.+?)\s*=\s*require\(\'(.+)\'\)/ig, 'import $1 from \'$2\''], [/module\.exports =/ig, 'export'] ); From a1644b67754d71f152bc5382c35c24b1bef8c338 Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Thu, 7 Nov 2024 20:58:26 +0700 Subject: [PATCH 53/64] Update version to `2.0.0-rc.2` --- .github/ISSUE_TEMPLATE/bug_report.md | 8 +-- CHANGELOG.md | 62 ++++++++++++++++-------- dist/ua-parser.min.js | 4 +- dist/ua-parser.pack.js | 4 +- package-lock.json | 46 ++++++++++++++++-- package.json | 2 +- src/enums/ua-parser-enums.js | 2 +- src/enums/ua-parser-enums.mjs | 16 ++++-- src/extensions/ua-parser-extensions.d.ts | 2 +- src/extensions/ua-parser-extensions.js | 2 +- src/extensions/ua-parser-extensions.mjs | 2 +- src/helpers/ua-parser-helpers.d.ts | 2 +- src/helpers/ua-parser-helpers.js | 2 +- src/helpers/ua-parser-helpers.mjs | 23 +++------ src/main/ua-parser.d.ts | 2 +- src/main/ua-parser.js | 4 +- src/main/ua-parser.mjs | 48 ++++++++++-------- 17 files changed, 150 insertions(+), 81 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 8fadfd144..1705fdbe7 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -10,8 +10,6 @@ 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.dev to confirm - **Describe the bug** A clear and concise description of what the bug is. @@ -23,11 +21,13 @@ Steps to reproduce the behavior: 4. See error **Expected behavior** -A clear and concise description of what you expected to happen. +A clear and concise description of what you expected to happen, or what's referred in the docs https://docs.uaparser.dev/ **Screenshots** If applicable, add screenshots to help explain your problem. +For issues related to detection results, you can send the screenshots of the demo section at https://uaparser.dev/#demo to confirm. + **Desktop (please complete the following information):** - OS: [e.g. iOS] - Browser [e.g. chrome, safari] @@ -40,4 +40,4 @@ If applicable, add screenshots to help explain your problem. - Version [e.g. 22] **Additional context** -Add any other context about the problem here. +Add any other context about the problem here. \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 63d6bf0f7..52575f009 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,46 @@ # UAParser.js Changelog +## Migrating from v1 to v2 + +- What's breaking: + - Licensed under AGPLv3 (open-source) or PRO License (commercial) + - Browser detection on mobile device: `"Chrome" => "Mobile Chrome"`, `"Firefox" => "Mobile Firefox"` + - OS detection: `"Mac OS" => "macOS"`, `"Chromium OS" => "Chrome OS"` +- What's new: + - New device type: `xr`, to identify AR/VR devices + - New browser property: `browser.type`, to identify the type of the browser: `crawler`, `cli`, `email`, `fetcher`, `inapp`, `mediaplayer`, `module` + - New methods in result object (all of `get*()` return value): + - Support for client hints: `withClientHints()` + - Support for feature detection: `withFeatureCheck()` + - Utility for easy comparison: `is()` + - Utility to print full-name: `toString()` + - Parse directly from command line using `npx ua-parser-js` + - Extensions can be passed as a list to `UAParser()` + - Support for ES module & TypeScript `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'`: + - `getDeviceVendor()` to guess for a device vendor based on its model name + - `isAppleSilicon()` to check if the device has Apple Silicon Mac device properties + - `isBot()` to check if the browser is identified as a bot + - `isChromeFamily()` to check if the browser is Chrome-based / has Blink engine (i.e: New Opera, New Edge, Vivaldi, Brave, Arc, etc.) + - `isElectron()` to check if current window is running inside Electron + - `isFromEU()` to check if current window is from an EU (European Union) country + - `isFrozenUA()` to check if a user-agent string match with the reduced/frozen user-agent pattern + - `isStandalonePWA()` to check if current window is a standalone PWA + +-- + +## Version 2.0.0-rc.2 + +- Fix incorrect import path in ESM files +- Add new browser: 115, SlimBoat, Slimjet, LibreWolf +- Improve browser detection: 2345, 360, Dragon, Iron, Maxthon +- `ua-parser-js/enums` submodule: + - Add Chromecast OS variants: Android/Fuchsia/Linux/SmartSpeaker +- `ua-parser-js/helpers` submodule: + - Add new method: `isBot()` to check if the browser is identified as a bot + ## Version 2.0.0-rc.1 - Fix Python Request mistakenly identified as Meta Quest @@ -68,27 +109,6 @@ - Initial work on new major version -## 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"` - - AR/VR devices moved to new device type: `xr` - - New property in `browser`: `type` -- What's new: - - 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()` - - Parse directly from command line using `npx ua-parser-js` - - Extensions can be passed as a list to `UAParser()` - - 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 0.7.38 / 1.0.38 diff --git a/dist/ua-parser.min.js b/dist/ua-parser.min.js index 4187195e4..18512030c 100644 --- a/dist/ua-parser.min.js +++ b/dist/ua-parser.min.js @@ -1,4 +1,4 @@ -/* UAParser.js v2.0.0-rc.1 +/* UAParser.js v2.0.0-rc.2 Copyright © 2012-2024 Faisal Salman AGPLv3 License */ -(function(window,undefined){"use strict";var LIBVERSION="2.0.0-rc.1",EMPTY="",UNKNOWN="?",FUNC_TYPE="function",UNDEF_TYPE="undefined",OBJ_TYPE="object",STR_TYPE="string",MAJOR="major",MODEL="model",NAME="name",TYPE="type",VENDOR="vendor",VERSION="version",ARCHITECTURE="architecture",CONSOLE="console",MOBILE="mobile",TABLET="tablet",SMARTTV="smarttv",WEARABLE="wearable",XR="xr",EMBEDDED="embedded",USER_AGENT="user-agent",UA_MAX_LENGTH=500,BRANDS="brands",FORMFACTORS="formFactors",FULLVERLIST="fullVersionList",PLATFORM="platform",PLATFORMVER="platformVersion",BITNESS="bitness",CH_HEADER="sec-ch-ua",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,FORMFACTORS,BITNESS],UA_BROWSER="browser",UA_CPU="cpu",UA_DEVICE="device",UA_ENGINE="engine",UA_OS="os",UA_RESULT="result",AMAZON="Amazon",APPLE="Apple",ASUS="ASUS",BLACKBERRY="BlackBerry",GOOGLE="Google",HUAWEI="Huawei",LENOVO="Lenovo",LG="LG",MICROSOFT="Microsoft",MOTOROLA="Motorola",SAMSUNG="Samsung",SHARP="Sharp",SONY="Sony",XIAOMI="Xiaomi",ZEBRA="Zebra",PREFIX_MOBILE="Mobile ",SUFFIX_BROWSER=" Browser",CHROME="Chrome",CHROMECAST="Chromecast",EDGE="Edge",FIREFOX="Firefox",OPERA="Opera",FACEBOOK="Facebook",SOGOU="Sogou",WINDOWS="Windows";var isWindow=typeof window!==UNDEF_TYPE,NAVIGATOR=isWindow&&window.navigator?window.navigator:undefined,NAVIGATOR_UADATA=NAVIGATOR&&NAVIGATOR.userAgentData?NAVIGATOR.userAgentData:undefined;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]:[])}}}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={};for(var i=0;i0){for(var i in str1){if(lowerize(str1[i])==lowerize(str2))return true}return false}return isString(str1)?lowerize(str2).indexOf(lowerize(str1))!==-1:false},isExtensions=function(obj,deep){for(var prop in obj){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(",");for(var i=0;i-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 isString(str)?str.toLowerCase():str},majorize=function(version){return isString(version)?strip(/[^\d\.]/g,version).split(".")[0]:undefined},setProps=function(arr){for(var i in arr){var propName=arr[i];if(typeof propName==OBJ_TYPE&&propName.length==2){this[propName[0]]=propName[1]}else{this[propName]=undefined}}return this},strip=function(pattern,str){return isString(str)?str.replace(pattern,EMPTY):str},stripQuotes=function(str){return strip(/\\?\"/g,str)},trim=function(str,len){if(isString(str)){str=strip(/^\s\s*/,str);return typeof len===UNDEF_TYPE?str:str.substring(0,UA_MAX_LENGTH)}};var rgxMapper=function(ua,arrays){if(!ua||!arrays)return;var i=0,j,k,p,q,matches,match;while(i0){if(q.length===2){if(typeof q[1]==FUNC_TYPE){this[q[0]]=q[1].call(this,match)}else{this[q[0]]=q[1]}}else if(q.length===3){if(typeof q[1]===FUNC_TYPE&&!(q[1].exec&&q[1].test)){this[q[0]]=match?q[1].call(this,match,q[2]):undefined}else{this[q[0]]=match?match.replace(q[1],q[2]):undefined}}else if(q.length===4){this[q[0]]=match?q[3].call(this,match.replace(q[1],q[2])):undefined}}else{this[q]=match?match:undefined}}}}i+=2}},strMapper=function(str,map){for(var i in map){if(typeof map[i]===OBJ_TYPE&&map[i].length>0){for(var j=0;j2){this.set(MODEL,"iPad").set(TYPE,TABLET)}break;case UA_OS:if(!this.get(NAME)&&NAVIGATOR_UADATA&&NAVIGATOR_UADATA[PLATFORM]){this.set(NAME,NAVIGATOR_UADATA[PLATFORM])}break;case UA_RESULT:var data=this.data;var detect=function(itemType){return data[itemType].getItem().detectFeature().get()};this.set(UA_BROWSER,detect(UA_BROWSER)).set(UA_CPU,detect(UA_CPU)).set(UA_DEVICE,detect(UA_DEVICE)).set(UA_ENGINE,detect(UA_ENGINE)).set(UA_OS,detect(UA_OS))}}return this};this.parseUA=function(){if(this.itemType!=UA_RESULT){rgxMapper.call(this.data,this.ua,this.rgxMap)}if(this.itemType==UA_BROWSER){this.set(MAJOR,majorize(this.get(VERSION)))}return this};this.parseCH=function(){var uaCH=this.uaCH,rgxMap=this.rgxMap;switch(this.itemType){case UA_BROWSER:var brands=uaCH[FULLVERLIST]||uaCH[BRANDS],prevName;if(brands){for(var i in brands){var brandName=strip(/(Google|Microsoft) /,brands[i].brand||brands[i]),brandVersion=brands[i].version;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}}}break;case UA_CPU:var archName=uaCH[ARCHITECTURE];if(archName){if(archName&&uaCH[BITNESS]=="64")archName+="64";rgxMapper.call(this.data,archName+";",rgxMap)}break;case UA_DEVICE:if(uaCH[MOBILE]){this.set(TYPE,MOBILE)}if(uaCH[MODEL]){this.set(MODEL,uaCH[MODEL])}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=13?"11":"10";this.set(NAME,osName).set(VERSION,osVersion)}if(this.get(NAME)==WINDOWS&&uaCH[MODEL]=="Xbox"){this.set(NAME,"Xbox").set(VERSION,undefined)}break;case UA_RESULT:var data=this.data;var parse=function(itemType){return data[itemType].getItem().setCH(uaCH).parseCH().get()};this.set(UA_BROWSER,parse(UA_BROWSER)).set(UA_CPU,parse(UA_CPU)).set(UA_DEVICE,parse(UA_DEVICE)).set(UA_ENGINE,parse(UA_ENGINE)).set(UA_OS,parse(UA_OS))}return this};setProps.call(this,[["itemType",itemType],["ua",ua],["uaCH",uaCH],["rgxMap",rgxMap],["data",createIData(this,itemType)]]);return this}function UAParser(ua,extensions,headers){if(typeof ua===OBJ_TYPE){if(isExtensions(ua,true)){if(typeof extensions===OBJ_TYPE){headers=extensions}extensions=ua}else{headers=ua;extensions=undefined}ua=undefined}else if(typeof ua===STR_TYPE&&!isExtensions(extensions,true)){headers=extensions;extensions=undefined}if(!(this instanceof UAParser)){return new UAParser(ua,extensions,headers).getResult()}var userAgent=typeof ua===STR_TYPE?ua:NAVIGATOR&&NAVIGATOR.userAgent?NAVIGATOR.userAgent:headers&&headers[USER_AGENT]?headers[USER_AGENT]:EMPTY,httpUACH=new UACHData(headers,true),regexMap=extensions?extend(defaultRegexes,extensions):defaultRegexes,createItemFunc=function(itemType){if(itemType==UA_RESULT){return function(){return new UAItem(itemType,userAgent,regexMap,httpUACH).set("ua",userAgent).set(UA_BROWSER,this.getBrowser()).set(UA_CPU,this.getCPU()).set(UA_DEVICE,this.getDevice()).set(UA_ENGINE,this.getEngine()).set(UA_OS,this.getOS()).get()}}else{return function(){return new UAItem(itemType,userAgent,regexMap[itemType],httpUACH).parseUA().get()}}};setProps.call(this,[["getBrowser",createItemFunc(UA_BROWSER)],["getCPU",createItemFunc(UA_CPU)],["getDevice",createItemFunc(UA_DEVICE)],["getEngine",createItemFunc(UA_ENGINE)],["getOS",createItemFunc(UA_OS)],["getResult",createItemFunc(UA_RESULT)],["getUA",function(){return userAgent}],["setUA",function(ua){if(isString(ua))userAgent=ua.length>UA_MAX_LENGTH?trim(ua,UA_MAX_LENGTH):ua;return this}]]).setUA(userAgent);return this}UAParser.VERSION=LIBVERSION;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]);if(typeof exports!==UNDEF_TYPE){if(typeof module!==UNDEF_TYPE&&module.exports){exports=module.exports=UAParser}exports.UAParser=UAParser}else{if(typeof define===FUNC_TYPE&&define.amd){define(function(){return UAParser})}else if(isWindow){window.UAParser=UAParser}}var $=isWindow&&(window.jQuery||window.Zepto);if($&&!$.ua){var parser=new UAParser;$.ua=parser.getResult();$.ua.get=function(){return parser.getUA()};$.ua.set=function(ua){parser.setUA(ua);var result=parser.getResult();for(var prop in result){$.ua[prop]=result[prop]}}}})(typeof window==="object"?window:this); \ No newline at end of file +(function(window,undefined){"use strict";var LIBVERSION="2.0.0-rc.2",EMPTY="",UNKNOWN="?",FUNC_TYPE="function",UNDEF_TYPE="undefined",OBJ_TYPE="object",STR_TYPE="string",MAJOR="major",MODEL="model",NAME="name",TYPE="type",VENDOR="vendor",VERSION="version",ARCHITECTURE="architecture",CONSOLE="console",MOBILE="mobile",TABLET="tablet",SMARTTV="smarttv",WEARABLE="wearable",XR="xr",EMBEDDED="embedded",INAPP="inapp",USER_AGENT="user-agent",UA_MAX_LENGTH=500,BRANDS="brands",FORMFACTORS="formFactors",FULLVERLIST="fullVersionList",PLATFORM="platform",PLATFORMVER="platformVersion",BITNESS="bitness",CH_HEADER="sec-ch-ua",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,FORMFACTORS,BITNESS],UA_BROWSER="browser",UA_CPU="cpu",UA_DEVICE="device",UA_ENGINE="engine",UA_OS="os",UA_RESULT="result",AMAZON="Amazon",APPLE="Apple",ASUS="ASUS",BLACKBERRY="BlackBerry",GOOGLE="Google",HUAWEI="Huawei",LENOVO="Lenovo",LG="LG",MICROSOFT="Microsoft",MOTOROLA="Motorola",SAMSUNG="Samsung",SHARP="Sharp",SONY="Sony",XIAOMI="Xiaomi",ZEBRA="Zebra",PREFIX_MOBILE="Mobile ",SUFFIX_BROWSER=" Browser",CHROME="Chrome",CHROMECAST="Chromecast",EDGE="Edge",FIREFOX="Firefox",OPERA="Opera",FACEBOOK="Facebook",SOGOU="Sogou",WINDOWS="Windows";var isWindow=typeof window!==UNDEF_TYPE,NAVIGATOR=isWindow&&window.navigator?window.navigator:undefined,NAVIGATOR_UADATA=NAVIGATOR&&NAVIGATOR.userAgentData?NAVIGATOR.userAgentData:undefined;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]:[])}}}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={};for(var i=0;i0){for(var i in str1){if(lowerize(str1[i])==lowerize(str2))return true}return false}return isString(str1)?lowerize(str2).indexOf(lowerize(str1))!==-1:false},isExtensions=function(obj,deep){for(var prop in obj){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(",");for(var i=0;i-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 isString(str)?str.toLowerCase():str},majorize=function(version){return isString(version)?strip(/[^\d\.]/g,version).split(".")[0]:undefined},setProps=function(arr){for(var i in arr){var propName=arr[i];if(typeof propName==OBJ_TYPE&&propName.length==2){this[propName[0]]=propName[1]}else{this[propName]=undefined}}return this},strip=function(pattern,str){return isString(str)?str.replace(pattern,EMPTY):str},stripQuotes=function(str){return strip(/\\?\"/g,str)},trim=function(str,len){if(isString(str)){str=strip(/^\s\s*/,str);return typeof len===UNDEF_TYPE?str:str.substring(0,UA_MAX_LENGTH)}};var rgxMapper=function(ua,arrays){if(!ua||!arrays)return;var i=0,j,k,p,q,matches,match;while(i0){if(q.length===2){if(typeof q[1]==FUNC_TYPE){this[q[0]]=q[1].call(this,match)}else{this[q[0]]=q[1]}}else if(q.length===3){if(typeof q[1]===FUNC_TYPE&&!(q[1].exec&&q[1].test)){this[q[0]]=match?q[1].call(this,match,q[2]):undefined}else{this[q[0]]=match?match.replace(q[1],q[2]):undefined}}else if(q.length===4){this[q[0]]=match?q[3].call(this,match.replace(q[1],q[2])):undefined}}else{this[q]=match?match:undefined}}}}i+=2}},strMapper=function(str,map){for(var i in map){if(typeof map[i]===OBJ_TYPE&&map[i].length>0){for(var j=0;j2){this.set(MODEL,"iPad").set(TYPE,TABLET)}break;case UA_OS:if(!this.get(NAME)&&NAVIGATOR_UADATA&&NAVIGATOR_UADATA[PLATFORM]){this.set(NAME,NAVIGATOR_UADATA[PLATFORM])}break;case UA_RESULT:var data=this.data;var detect=function(itemType){return data[itemType].getItem().detectFeature().get()};this.set(UA_BROWSER,detect(UA_BROWSER)).set(UA_CPU,detect(UA_CPU)).set(UA_DEVICE,detect(UA_DEVICE)).set(UA_ENGINE,detect(UA_ENGINE)).set(UA_OS,detect(UA_OS))}}return this};this.parseUA=function(){if(this.itemType!=UA_RESULT){rgxMapper.call(this.data,this.ua,this.rgxMap)}if(this.itemType==UA_BROWSER){this.set(MAJOR,majorize(this.get(VERSION)))}return this};this.parseCH=function(){var uaCH=this.uaCH,rgxMap=this.rgxMap;switch(this.itemType){case UA_BROWSER:var brands=uaCH[FULLVERLIST]||uaCH[BRANDS],prevName;if(brands){for(var i in brands){var brandName=strip(/(Google|Microsoft) /,brands[i].brand||brands[i]),brandVersion=brands[i].version;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}}}break;case UA_CPU:var archName=uaCH[ARCHITECTURE];if(archName){if(archName&&uaCH[BITNESS]=="64")archName+="64";rgxMapper.call(this.data,archName+";",rgxMap)}break;case UA_DEVICE:if(uaCH[MOBILE]){this.set(TYPE,MOBILE)}if(uaCH[MODEL]){this.set(MODEL,uaCH[MODEL])}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=13?"11":"10";this.set(NAME,osName).set(VERSION,osVersion)}if(this.get(NAME)==WINDOWS&&uaCH[MODEL]=="Xbox"){this.set(NAME,"Xbox").set(VERSION,undefined)}break;case UA_RESULT:var data=this.data;var parse=function(itemType){return data[itemType].getItem().setCH(uaCH).parseCH().get()};this.set(UA_BROWSER,parse(UA_BROWSER)).set(UA_CPU,parse(UA_CPU)).set(UA_DEVICE,parse(UA_DEVICE)).set(UA_ENGINE,parse(UA_ENGINE)).set(UA_OS,parse(UA_OS))}return this};setProps.call(this,[["itemType",itemType],["ua",ua],["uaCH",uaCH],["rgxMap",rgxMap],["data",createIData(this,itemType)]]);return this}function UAParser(ua,extensions,headers){if(typeof ua===OBJ_TYPE){if(isExtensions(ua,true)){if(typeof extensions===OBJ_TYPE){headers=extensions}extensions=ua}else{headers=ua;extensions=undefined}ua=undefined}else if(typeof ua===STR_TYPE&&!isExtensions(extensions,true)){headers=extensions;extensions=undefined}if(!(this instanceof UAParser)){return new UAParser(ua,extensions,headers).getResult()}var userAgent=typeof ua===STR_TYPE?ua:NAVIGATOR&&NAVIGATOR.userAgent?NAVIGATOR.userAgent:headers&&headers[USER_AGENT]?headers[USER_AGENT]:EMPTY,httpUACH=new UACHData(headers,true),regexMap=extensions?extend(defaultRegexes,extensions):defaultRegexes,createItemFunc=function(itemType){if(itemType==UA_RESULT){return function(){return new UAItem(itemType,userAgent,regexMap,httpUACH).set("ua",userAgent).set(UA_BROWSER,this.getBrowser()).set(UA_CPU,this.getCPU()).set(UA_DEVICE,this.getDevice()).set(UA_ENGINE,this.getEngine()).set(UA_OS,this.getOS()).get()}}else{return function(){return new UAItem(itemType,userAgent,regexMap[itemType],httpUACH).parseUA().get()}}};setProps.call(this,[["getBrowser",createItemFunc(UA_BROWSER)],["getCPU",createItemFunc(UA_CPU)],["getDevice",createItemFunc(UA_DEVICE)],["getEngine",createItemFunc(UA_ENGINE)],["getOS",createItemFunc(UA_OS)],["getResult",createItemFunc(UA_RESULT)],["getUA",function(){return userAgent}],["setUA",function(ua){if(isString(ua))userAgent=ua.length>UA_MAX_LENGTH?trim(ua,UA_MAX_LENGTH):ua;return this}]]).setUA(userAgent);return this}UAParser.VERSION=LIBVERSION;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]);if(typeof exports!==UNDEF_TYPE){if(typeof module!==UNDEF_TYPE&&module.exports){exports=module.exports=UAParser}exports.UAParser=UAParser}else{if(typeof define===FUNC_TYPE&&define.amd){define(function(){return UAParser})}else if(isWindow){window.UAParser=UAParser}}var $=isWindow&&(window.jQuery||window.Zepto);if($&&!$.ua){var parser=new UAParser;$.ua=parser.getResult();$.ua.get=function(){return parser.getUA()};$.ua.set=function(ua){parser.setUA(ua);var result=parser.getResult();for(var prop in result){$.ua[prop]=result[prop]}}}})(typeof window==="object"?window:this); \ No newline at end of file diff --git a/dist/ua-parser.pack.js b/dist/ua-parser.pack.js index e22b892ce..0f145e7e3 100644 --- a/dist/ua-parser.pack.js +++ b/dist/ua-parser.pack.js @@ -1,4 +1,4 @@ -/* UAParser.js v2.0.0-rc.1 +/* UAParser.js v2.0.0-rc.2 Copyright © 2012-2024 Faisal Salman AGPLv3 License */ -!function(i,c){"use strict";function e(i){for(var e={},t=0;tS?Ti(i,S):i),this}]]).setUA(o),this}Ui.VERSION="2.0.0-rc.1",Ui.BROWSER=e([m,v,h,f]),Ui.CPU=e([k]),Ui.DEVICE=e([p,g,f,x,y,t,r,o,d]),Ui.ENGINE=Ui.OS=e([m,v]),typeof exports!==b?(typeof module!==b&&module.exports&&(exports=module.exports=Ui),exports.UAParser=Ui):typeof define===l&&define.amd?define(function(){return Ui}):ui&&(i.UAParser=Ui);var ji,Ei=ui&&(i.jQuery||i.Zepto);Ei&&!Ei.ua&&(ji=new Ui,Ei.ua=ji.getResult(),Ei.ua.get=function(){return ji.getUA()},Ei.ua.set=function(i){ji.setUA(i);var e,t=ji.getResult();for(e in t)Ei.ua[e]=t[e]})}("object"==typeof window?window:this); \ No newline at end of file +!function(i,c){"use strict";function e(i){for(var e={},t=0;tT?Ti(i,T):i),this}]]).setUA(o),this}Ui.VERSION="2.0.0-rc.2",Ui.BROWSER=e([m,v,h,f]),Ui.CPU=e([k]),Ui.DEVICE=e([p,g,f,x,y,t,r,o,d]),Ui.ENGINE=Ui.OS=e([m,v]),typeof exports!==b?(typeof module!==b&&module.exports&&(exports=module.exports=Ui),exports.UAParser=Ui):typeof define===l&&define.amd?define(function(){return Ui}):ui&&(i.UAParser=Ui);var ji,Mi=ui&&(i.jQuery||i.Zepto);Mi&&!Mi.ua&&(ji=new Ui,Mi.ua=ji.getResult(),Mi.ua.get=function(){return ji.getUA()},Mi.ua.set=function(i){ji.setUA(i);var e,t=ji.getResult();for(e in t)Mi.ua[e]=t[e]})}("object"==typeof window?window:this); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 1c4d590fc..8d8b2bc24 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ua-parser-js", - "version": "2.0.0-rc.1", + "version": "2.0.0-rc.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "ua-parser-js", - "version": "2.0.0-rc.1", + "version": "2.0.0-rc.2", "funding": [ { "type": "opencollective", @@ -23,7 +23,9 @@ ], "license": "AGPL-3.0-or-later", "dependencies": { - "detect-europe-js": "^0.1.1" + "detect-europe-js": "^0.1.1", + "is-standalone-pwa": "^0.1.0", + "ua-is-frozen": "^0.1.1" }, "bin": { "ua-parser-js": "script/cli.js" @@ -2609,6 +2611,25 @@ "node": ">=8" } }, + "node_modules/is-standalone-pwa": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-standalone-pwa/-/is-standalone-pwa-0.1.0.tgz", + "integrity": "sha512-n5SQqXd0/JEkrKYEB7ZUndwuS7NKskZvk6rZZt6kTE1jiPxtPfPvVhXkfteIKpUfcEP07qsja/Wjz9NDjiZ5gg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/faisalman" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + } + ] + }, "node_modules/isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", @@ -4597,6 +4618,25 @@ "node": "*" } }, + "node_modules/ua-is-frozen": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ua-is-frozen/-/ua-is-frozen-0.1.1.tgz", + "integrity": "sha512-TxhyfblPzcDJXRXu/j+73OI6s1jG6PUZBF/8hjTHoAsjZYKl9IhZzLQlnZHFLe5U2mvL1lMOOmcy647KpUq25A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/faisalman" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + } + ] + }, "node_modules/uglify-js": { "version": "3.12.8", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.12.8.tgz", diff --git a/package.json b/package.json index c0f93cd79..1beaf501a 100755 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "title": "UAParser.js", "name": "ua-parser-js", - "version": "2.0.0-rc.1", + "version": "2.0.0-rc.2", "author": "Faisal Salman (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": [ diff --git a/src/enums/ua-parser-enums.js b/src/enums/ua-parser-enums.js index ea4d112b4..63a391772 100644 --- a/src/enums/ua-parser-enums.js +++ b/src/enums/ua-parser-enums.js @@ -1,5 +1,5 @@ /////////////////////////////////////////////// -/* Enums for UAParser.js v2.0.0-rc.1 +/* Enums for UAParser.js v2.0.0-rc.2 https://github.com/faisalman/ua-parser-js Author: Faisal Salman AGPLv3 License */ diff --git a/src/enums/ua-parser-enums.mjs b/src/enums/ua-parser-enums.mjs index 52df47f6e..6af7ef755 100644 --- a/src/enums/ua-parser-enums.mjs +++ b/src/enums/ua-parser-enums.mjs @@ -3,7 +3,7 @@ // Source: /src/enums/ua-parser-enums.js /////////////////////////////////////////////// -/* Enums for UAParser.js v2.0.0-rc.1 +/* Enums for UAParser.js v2.0.0-rc.2 https://github.com/faisalman/ua-parser-js Author: Faisal Salman AGPLv3 License */ @@ -12,8 +12,9 @@ /*jshint esversion: 6 */ const Browser = Object.freeze({ - '2345_EXPLORER': '2345Explorer', - '360': '360 Browser', + '115': '115', + '2345': '2345', + '360': '360', ALIPAY: 'Alipay', AMAYA: 'Amaya', ANDROID: 'Android Browser', @@ -36,11 +37,11 @@ const Browser = Object.freeze({ CHROMIUM: 'Chromium', COBALT: 'Cobalt', COC_COC: 'Coc Coc', - COMODO_DRAGON: 'Comodo Dragon', CONKEROR: 'Conkeror', DILLO: 'Dillo', DOLPHIN: 'Dolphin', DORIS: 'Doris', + DRAGON: 'Dragon', DUCKDUCKGO: 'DuckDuckGo', EDGE: 'Edge', EPIPHANY: 'Epiphany', @@ -78,6 +79,7 @@ const Browser = Object.freeze({ KLARNA: 'Klarna', KINDLE: 'Kindle', LENOVO: 'Smart Lenovo Browser', + LIBREWOLF: 'LibreWolf', LIEBAO: 'LBBROWSER', LINE: 'Line', LINKEDIN: 'LinkedIn', @@ -126,7 +128,9 @@ const Browser = Object.freeze({ SILK: 'Silk', SKYFIRE: 'Skyfire', SLEIPNIR: 'Sleipnir', + SLIMBOAT: 'SlimBoat', SLIMBROWSER: 'SlimBrowser', + SLIMJET: 'Slimjet', SNAPCHAT: 'Snapchat', SOGOU_EXPLORER: 'Sogou Explorer', SOGOU_MOBILE: 'Sogou Mobile', @@ -291,6 +295,10 @@ const OS = Object.freeze({ CENTOS: 'CentOS', CHROME_OS: 'Chrome OS', CHROMECAST: 'Chromecast', + CHROMECAST_ANDROID: 'Chromecast Android', + CHROMECAST_FUCHSIA: 'Chromecast Fuchsia', + CHROMECAST_LINUX: 'Chromecast Linux', + CHROMECAST_SMARTSPEAKER: 'Chromecast SmartSpeaker', CONTIKI: 'Contiki', DEBIAN: 'Debian', DEEPIN: 'Deepin', diff --git a/src/extensions/ua-parser-extensions.d.ts b/src/extensions/ua-parser-extensions.d.ts index e432b21f6..89f5bd3a5 100644 --- a/src/extensions/ua-parser-extensions.d.ts +++ b/src/extensions/ua-parser-extensions.d.ts @@ -1,4 +1,4 @@ -// Type definitions for Helpers submodule of UAParser.js v2.0.0-beta.3 +// Type definitions for Helpers submodule of UAParser.js v2.0.0-rc.2 // Project: https://github.com/faisalman/ua-parser-js // Definitions by: Faisal Salman diff --git a/src/extensions/ua-parser-extensions.js b/src/extensions/ua-parser-extensions.js index 124fe9923..182bd872d 100644 --- a/src/extensions/ua-parser-extensions.js +++ b/src/extensions/ua-parser-extensions.js @@ -1,5 +1,5 @@ /////////////////////////////////////////////// -/* Extensions for UAParser.js v2.0.0-rc.1 +/* Extensions for UAParser.js v2.0.0-rc.2 https://github.com/faisalman/ua-parser-js Author: Faisal Salman AGPLv3 License */ diff --git a/src/extensions/ua-parser-extensions.mjs b/src/extensions/ua-parser-extensions.mjs index bf12ddf64..21c2dcb9a 100644 --- a/src/extensions/ua-parser-extensions.mjs +++ b/src/extensions/ua-parser-extensions.mjs @@ -3,7 +3,7 @@ // Source: /src/extensions/ua-parser-extensions.js /////////////////////////////////////////////// -/* Extensions for UAParser.js v2.0.0-rc.1 +/* Extensions for UAParser.js v2.0.0-rc.2 https://github.com/faisalman/ua-parser-js Author: Faisal Salman AGPLv3 License */ diff --git a/src/helpers/ua-parser-helpers.d.ts b/src/helpers/ua-parser-helpers.d.ts index 7074c229d..a1e3f20c5 100644 --- a/src/helpers/ua-parser-helpers.d.ts +++ b/src/helpers/ua-parser-helpers.d.ts @@ -1,4 +1,4 @@ -// Type definitions for Helpers submodule of UAParser.js v2.0.0-beta.3 +// Type definitions for Helpers submodule of UAParser.js v2.0.0-rc.2 // Project: https://github.com/faisalman/ua-parser-js // Definitions by: Faisal Salman diff --git a/src/helpers/ua-parser-helpers.js b/src/helpers/ua-parser-helpers.js index c8f6925b7..7234e63d2 100644 --- a/src/helpers/ua-parser-helpers.js +++ b/src/helpers/ua-parser-helpers.js @@ -1,5 +1,5 @@ /////////////////////////////////////////////// -/* Helpers for UAParser.js v2.0.0-rc.1 +/* Helpers for UAParser.js v2.0.0-rc.2 https://github.com/faisalman/ua-parser-js Author: Faisal Salman AGPLv3 License */ diff --git a/src/helpers/ua-parser-helpers.mjs b/src/helpers/ua-parser-helpers.mjs index 886d0dc31..7c6fd0eff 100644 --- a/src/helpers/ua-parser-helpers.mjs +++ b/src/helpers/ua-parser-helpers.mjs @@ -3,7 +3,7 @@ // Source: /src/helpers/ua-parser-helpers.js /////////////////////////////////////////////// -/* Helpers for UAParser.js v2.0.0-rc.1 +/* Helpers for UAParser.js v2.0.0-rc.2 https://github.com/faisalman/ua-parser-js Author: Faisal Salman AGPLv3 License */ @@ -11,9 +11,11 @@ /*jshint esversion: 6 */ -import { CPU, OS, Engine } from './enums/ua-parser-enums.mjs'; -import { UAParser } from './main/ua-parser.mjs'; +import { UAParser } from '../main/ua-parser.mjs'; +import { CPU, OS, Engine } from '../enums/ua-parser-enums.mjs'; import { isFromEU } from 'detect-europe-js'; +import { isFrozenUA } from 'ua-is-frozen'; +import { isStandalonePWA } from 'is-standalone-pwa'; const getDeviceVendor = (model) => UAParser(`Mozilla/5.0 (Linux; Android 10; ${model}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.0.0 Safari/537.36`).device.vendor; @@ -37,26 +39,17 @@ const isAppleSilicon = (res) => { return false; } +const isBot = (res) => ['cli', 'crawler', 'fetcher', 'module'].includes(res.browser.type); + const isChromeFamily = (res) => res.engine.is(Engine.BLINK); const isElectron = () => !!(process?.versions?.hasOwnProperty('electron') || // node.js / electron\//i.test(navigator?.userAgent)); // browser -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); - -const isStandalonePWA = () => window && (window.matchMedia('(display-mode: standalone)').matches || - // iOS - navigator.standalone || - // Android - document.referrer.startsWith('android-app://') || - // Windows - window.Windows || - /trident.+(msapphost|webview)\//i.test(navigator.userAgent) || - document.referrer.startsWith('app-info://platform/microsoft-store')); - export { getDeviceVendor, isAppleSilicon, + isBot, isChromeFamily, isElectron, isFromEU, diff --git a/src/main/ua-parser.d.ts b/src/main/ua-parser.d.ts index 03be97a52..b54f4cdb5 100644 --- a/src/main/ua-parser.d.ts +++ b/src/main/ua-parser.d.ts @@ -1,4 +1,4 @@ -// Type definitions for UAParser.js v2.0.0-beta.3 +// Type definitions for UAParser.js v2.0.0-rc.2 // Project: https://github.com/faisalman/ua-parser-js // Definitions by: Faisal Salman diff --git a/src/main/ua-parser.js b/src/main/ua-parser.js index 242f42a5c..797890213 100755 --- a/src/main/ua-parser.js +++ b/src/main/ua-parser.js @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////////// -/* UAParser.js v2.0.0-rc.1 +/* UAParser.js v2.0.0-rc.2 Copyright © 2012-2024 Faisal Salman AGPLv3 License *//* Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data. @@ -19,7 +19,7 @@ // Constants ///////////// - var LIBVERSION = '2.0.0-rc.1', + var LIBVERSION = '2.0.0-rc.2', EMPTY = '', UNKNOWN = '?', FUNC_TYPE = 'function', diff --git a/src/main/ua-parser.mjs b/src/main/ua-parser.mjs index e9861fc5c..130f21649 100644 --- a/src/main/ua-parser.mjs +++ b/src/main/ua-parser.mjs @@ -3,7 +3,7 @@ // Source: /src/main/ua-parser.js ///////////////////////////////////////////////////////////////////////////////// -/* UAParser.js v2.0.0-rc.1 +/* UAParser.js v2.0.0-rc.2 Copyright © 2012-2024 Faisal Salman AGPLv3 License *//* Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data. @@ -21,7 +21,7 @@ // Constants ///////////// - var LIBVERSION = '2.0.0-rc.1', + var LIBVERSION = '2.0.0-rc.2', EMPTY = '', UNKNOWN = '?', FUNC_TYPE = 'function', @@ -42,6 +42,7 @@ WEARABLE = 'wearable', XR = 'xr', EMBEDDED = 'embedded', + INAPP = 'inapp', USER_AGENT = 'user-agent', UA_MAX_LENGTH = 500, BRANDS = 'brands', @@ -322,17 +323,19 @@ // Mixed /\bb[ai]*d(?:uhd|[ub]*[aekoprswx]{5,6})[\/ ]?([\w\.]+)/i // Baidu ], [VERSION, [NAME, 'Baidu']], [ + /\b(?:mxbrowser|mxios|myie2)\/?([-\w\.]*)\b/i // Maxthon + ], [VERSION, [NAME, 'Maxthon']], [ /(kindle)\/([\w\.]+)/i, // Kindle /(lunascape|maxthon|netfront|jasmine|blazer|sleipnir)[\/ ]?([\w\.]*)/i, // Lunascape/Maxthon/Netfront/Jasmine/Blazer/Sleipnir // Trident based - /(avant|iemobile|slim)\s?(?:browser)?[\/ ]?([\w\.]*)/i, // Avant/IEMobile/SlimBrowser + /(avant|iemobile|slim(?:browser|boat|jet))[\/ ]?([\d\.]*)/i, // Avant/IEMobile/SlimBrowser/SlimBoat/Slimjet /(?: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|qupzilla|falkon|rekonq|puffin|brave|whale(?!.+naver)|qqbrowserlite|duckduckgo|klar|helio)\/([-\w\.]+)/i, - // Rekonq/Puffin/Brave/Whale/QQBrowserLite/QQ//Vivaldi/DuckDuckGo/Klar/Helio - /(heytap|ovi)browser\/([\d\.]+)/i, // HeyTap/Ovi + // Blink/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|qupzilla|falkon|rekonq|puffin|brave|whale(?!.+naver)|qqbrowserlite|duckduckgo|klar|helio|(?=comodo_)?dragon)\/([-\w\.]+)/i, + // Rekonq/Puffin/Brave/Whale/QQBrowserLite/QQ//Vivaldi/DuckDuckGo/Klar/Helio/Dragon + /(heytap|ovi|115)browser\/([\d\.]+)/i, // HeyTap/Ovi/115 /(weibo)__([\d\.]+)/i // Weibo ], [NAME, VERSION], [ /quark(?:pc)?\/([-\w\.]+)/i // Quark @@ -369,31 +372,31 @@ ], [VERSION, [NAME, 'MIUI' + SUFFIX_BROWSER]], [ /fxios\/([\w\.-]+)/i // Firefox for iOS ], [VERSION, [NAME, PREFIX_MOBILE + FIREFOX]], [ - /\bqihu|(qi?ho?o?|360)browser/i // 360 - ], [[NAME, '360' + SUFFIX_BROWSER]], [ + /\bqihoobrowser\/?([\w\.]*)/i // 360 + ], [VERSION, [NAME, '360']], [ /\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|2345Explorer)[\/ ]?([\w\.]+)/i // QQBrowser/2345 Browser + /m?(qqbrowser|2345(?=browser|chrome|explorer))\w*[\/ ]?v?([\w\.]+)/i // QQ/2345 ], [NAME, VERSION], [ - /(lbbrowser|rekonq)/i, // LieBao Browser/Rekonq - /\[(linkedin)app\]/i // LinkedIn App for iOS & Android + /(lbbrowser|rekonq)/i // LieBao Browser/Rekonq ], [NAME], [ + /ome\/([\w\.]+) \w* ?(iron) saf/i, // Iron + /ome\/([\w\.]+).+qihu (360)[es]e/i // 360 + ], [VERSION, NAME], [ // WebView /((?:fban\/fbios|fb_iab\/fb4a)(?!.+fbav)|;fbav\/([\w\.]+);)/i // Facebook App for iOS & Android - ], [[NAME, FACEBOOK], VERSION], [ + ], [[NAME, FACEBOOK], VERSION, [TYPE, INAPP]], [ /(Klarna)\/([\w\.]+)/i, // Klarna Shopping Browser for iOS & Android /(kakao(?:talk|story))[\/ ]([\w\.]+)/i, // Kakao App /(naver)\(.*?(\d+\.[\w\.]+).*\)/i, // Naver InApp @@ -401,12 +404,17 @@ /\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], [ + /(instagram|snapchat)[\/ ]([-\w\.]+)/i // Instagram/Snapchat + ], [NAME, VERSION, [TYPE, INAPP]], [ /\bgsa\/([\w\.]+) .*safari\//i // Google Search Appliance on iOS - ], [VERSION, [NAME, 'GSA']], [ + ], [VERSION, [NAME, 'GSA'], [TYPE, INAPP]], [ /musical_ly(?:.+app_?version\/|_)([\w\.]+)/i // TikTok - ], [VERSION, [NAME, 'TikTok']], [ + ], [VERSION, [NAME, 'TikTok'], [TYPE, INAPP]], [ + /\[(linkedin)app\]/i // LinkedIn App for iOS & Android + ], [NAME, [TYPE, INAPP]], [ + + /(chromium)[\/ ]([-\w\.]+)/i // Chromium + ], [NAME, VERSION], [ /headlesschrome(?:\/([\w\.]+)| )/i // Chrome Headless ], [VERSION, [NAME, CHROME+' Headless']], [ @@ -440,7 +448,7 @@ ], [[NAME, PREFIX_MOBILE + FIREFOX], VERSION], [ /(navigator|netscape\d?)\/([-\w\.]+)/i // Netscape ], [[NAME, 'Netscape'], VERSION], [ - /(wolvic)\/([\w\.]+)/i // Wolvic + /(wolvic|librewolf)\/([\w\.]+)/i // Wolvic/LibreWolf ], [NAME, VERSION], [ /mobile vr; rv:([\w\.]+)\).+firefox/i // Firefox Reality ], [VERSION, [NAME, FIREFOX+' Reality']], [ From be2f167f9074ea633d7df34cb952721ee68e0e63 Mon Sep 17 00:00:00 2001 From: Aiyush Date: Sat, 9 Nov 2024 08:50:45 +0530 Subject: [PATCH 54/64] Added support for honor separated from Huawei (#749) * Added support for honor separated from Huawei * Revert "Added support for honor separated from Huawei" This reverts commit 28bde1c0b4da2aa14082a8d036914761e00ca750. * Added changes wrt comments * Added another change --- src/enums/ua-parser-enums.js | 1 + src/main/ua-parser.js | 7 ++++++- test/specs/device-all.json | 6 +++--- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/enums/ua-parser-enums.js b/src/enums/ua-parser-enums.js index 6d88e813f..85820f901 100644 --- a/src/enums/ua-parser-enums.js +++ b/src/enums/ua-parser-enums.js @@ -52,6 +52,7 @@ const DeviceVendor = Object.freeze({ APPLE : 'Apple', SAMSUNG : 'Samsung', HUAWEI : 'Huawei', + HONOR : 'Honor', XIAOMI : 'Xiaomi', OPPO : 'OPPO', VIVO : 'Vivo', diff --git a/src/main/ua-parser.js b/src/main/ua-parser.js index c2b736d4a..5d4f80da2 100755 --- a/src/main/ua-parser.js +++ b/src/main/ua-parser.js @@ -68,6 +68,7 @@ BLACKBERRY = 'BlackBerry', GOOGLE = 'Google', HUAWEI = 'Huawei', + HONOR = 'Honor', LG = 'LG', MICROSOFT = 'Microsoft', MOTOROLA = 'Motorola', @@ -467,10 +468,14 @@ /\b(sh-?[altvz]?\d\d[a-ekm]?)/i ], [MODEL, [VENDOR, SHARP], [TYPE, MOBILE]], [ + // Honor + /(?:honor)([-\w ]+)[;\)]/i + ], [MODEL, [VENDOR, HONOR], [TYPE, MOBILE]], [ + // Huawei /\b((?:ag[rs][23]?|bah2?|sht?|btv)-a?[lw]\d{2})\b(?!.+d\/s)/i ], [MODEL, [VENDOR, HUAWEI], [TYPE, TABLET]], [ - /(?:huawei|honor)([-\w ]+)[;\)]/i, + /(?:huawei)([-\w ]+)[;\)]/i, /\b(nexus 6p|\w{2,4}e?-[atu]?[ln][\dx][012359c][adn]?)\b(?!.+d\/s)/i ], [MODEL, [VENDOR, HUAWEI], [TYPE, MOBILE]], [ diff --git a/test/specs/device-all.json b/test/specs/device-all.json index b43969c41..6f2dc51ce 100644 --- a/test/specs/device-all.json +++ b/test/specs/device-all.json @@ -632,7 +632,7 @@ "desc": "Huawei Honor 6A", "ua": "Mozilla/5.0 (Linux; Android 7.0; DLI-L22 Build/HONORDLI-L22; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/79.0.3945.116 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/252.0.0.22.355;]", "expect": { - "vendor": "Huawei", + "vendor": "Honor", "model": "DLI-L22", "type": "mobile" } @@ -641,7 +641,7 @@ "desc": "Huawei Honor 7", "ua": "Mozilla/5.0 (Linux; Android 6.0; PLK-L01 Build/HONORPLK-L01; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/79.0.3945.116 Mobile Safari/537.36", "expect": { - "vendor": "Huawei", + "vendor": "Honor", "model": "PLK-L01", "type": "mobile" } @@ -650,7 +650,7 @@ "desc": "Huawei 10 Lite", "ua": "Mozilla/5.0 (Linux; Android 9; HRY-LX1 Build/HONORHRY-LX1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.91 Mobile Safari/537.36", "expect": { - "vendor": "Huawei", + "vendor": "Honor", "model": "HRY-LX1", "type": "mobile" } From d5edcbae12ffe7025199d8839e2fb5c78cdb9e38 Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Sat, 9 Nov 2024 10:21:36 +0700 Subject: [PATCH 55/64] Fix #763 - Add support for Headers object --- src/main/ua-parser.js | 9 ++++++++- test/playwright-test-main.spec.mjs | 19 ++++++++++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/main/ua-parser.js b/src/main/ua-parser.js index 797890213..8730b6397 100755 --- a/src/main/ua-parser.js +++ b/src/main/ua-parser.js @@ -1236,14 +1236,21 @@ headers = extensions; // case UAParser(ua, headers) extensions = undefined; } + + // Convert Headers object into a plain object + if (headers && typeof headers.append === FUNC_TYPE) { + var kv = {}; + headers.forEach(function (v, k) { kv[k] = v; }); + headers = kv; + } if (!(this instanceof UAParser)) { return new UAParser(ua, extensions, headers).getResult(); } var userAgent = typeof ua === STR_TYPE ? ua : // Passed user-agent string - ((NAVIGATOR && NAVIGATOR.userAgent) ? NAVIGATOR.userAgent : // navigator.userAgent (headers && headers[USER_AGENT] ? headers[USER_AGENT] : // User-Agent from passed headers + ((NAVIGATOR && NAVIGATOR.userAgent) ? NAVIGATOR.userAgent : // navigator.userAgent EMPTY)), // empty string httpUACH = new UACHData(headers, true), diff --git a/test/playwright-test-main.spec.mjs b/test/playwright-test-main.spec.mjs index fe4ac7cbd..db6e149f1 100644 --- a/test/playwright-test-main.spec.mjs +++ b/test/playwright-test-main.spec.mjs @@ -123,4 +123,21 @@ test.describe('withFeatureCheck() tests', () => { expect(uap).toHaveProperty('device.model', 'iPad'); expect(uap).toHaveProperty('device.type', 'tablet'); }); -}); \ No newline at end of file +}); + +test.describe('request.headers can be passed in form of a Headers object', () => { + + test('Headers automatically converted into a plain key-value object', async ({ page }) => { + await page.addInitScript(() => { + Object.defineProperty(window, 'req', { + value : { + headers: new Headers([["User-Agent", "myBrowser/1.0"]]) + } + }); + }); + await page.goto(localHtml); + // @ts-ignore + const uap = await page.evaluate(() => UAParser(req.headers)); + expect(uap.ua).toBe('myBrowser/1.0'); + }); +}); From 19e5d322e27ced7e95abfa988218a0c28ef995b1 Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Sat, 9 Nov 2024 20:04:29 +0700 Subject: [PATCH 56/64] [submodule:helpers] Add an optional parameter in `isAppleSilicon()` that flags the use of feature detection --- src/helpers/ua-parser-helpers.d.ts | 2 +- src/helpers/ua-parser-helpers.js | 22 ++++++++++++---------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/helpers/ua-parser-helpers.d.ts b/src/helpers/ua-parser-helpers.d.ts index a1e3f20c5..0f46125a4 100644 --- a/src/helpers/ua-parser-helpers.d.ts +++ b/src/helpers/ua-parser-helpers.d.ts @@ -5,7 +5,7 @@ import { IResult } from "../main/ua-parser"; declare function getDeviceVendor(model: string): string | undefined; -declare function isAppleSilicon(res: IResult): boolean; +declare function isAppleSilicon(res: IResult, useFeatureDetection?: boolean): boolean; declare function isBot(res: IResult): boolean; declare function isChromeFamily(res: IResult): boolean; declare function isElectron(): boolean; diff --git a/src/helpers/ua-parser-helpers.js b/src/helpers/ua-parser-helpers.js index 7234e63d2..ce2db0c8e 100644 --- a/src/helpers/ua-parser-helpers.js +++ b/src/helpers/ua-parser-helpers.js @@ -15,21 +15,23 @@ const { isStandalonePWA } = require('is-standalone-pwa'); const getDeviceVendor = (model) => UAParser(`Mozilla/5.0 (Linux; Android 10; ${model}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.0.0 Safari/537.36`).device.vendor; -const isAppleSilicon = (res) => { +const isAppleSilicon = (res, useFeatureDetection) => { if (res.os.is(OS.MACOS)) { if (res.cpu.is(CPU.ARM)) { return true; } - try { - const canvas = document.createElement('canvas'); - const webgl = canvas.getContext('webgl2') || canvas.getContext('webgl') || canvas.getContext('experimental-webgl'); - const debug = webgl.getExtension('WEBGL_debug_renderer_info'); - const renderer = webgl.getParameter(debug.UNMASKED_RENDERER_WEBGL); - if (renderer.match(/apple m\d/i)) { - return true; + if (useFeatureDetection) { + try { + const canvas = document.createElement('canvas'); + const webgl = canvas.getContext('webgl2') || canvas.getContext('webgl') || canvas.getContext('experimental-webgl'); + const debug = webgl.getExtension('WEBGL_debug_renderer_info'); + const renderer = webgl.getParameter(debug.UNMASKED_RENDERER_WEBGL); + if (renderer.match(/apple m\d/i)) { + return true; + } + } catch { + return false; } - } catch { - return false; } } return false; From 3b3361fe53bd74b4b3a58d5908cc7348742b3439 Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Sun, 10 Nov 2024 08:15:39 +0700 Subject: [PATCH 57/64] [submodule:extensions] Breaking change: rename `module` to `library` --- src/enums/ua-parser-enums.js | 2 +- src/extensions/ua-parser-extensions.d.ts | 4 ++-- src/extensions/ua-parser-extensions.js | 18 +++++++++--------- src/helpers/ua-parser-helpers.js | 2 +- src/main/ua-parser.d.ts | 2 +- test/dts-test.ts | 2 +- test/mocha-test-extension.js | 14 +++++++------- ...ser-modules.json => browser-libraries.json} | 2 +- 8 files changed, 23 insertions(+), 23 deletions(-) rename test/specs/{browser-modules.json => browser-libraries.json} (86%) diff --git a/src/enums/ua-parser-enums.js b/src/enums/ua-parser-enums.js index 1c15464d1..903aa057c 100644 --- a/src/enums/ua-parser-enums.js +++ b/src/enums/ua-parser-enums.js @@ -159,7 +159,7 @@ const BrowserType = Object.freeze({ FETCHER: 'fetcher', INAPP: 'inapp', MEDIAPLAYER: 'mediaplayer', - MODULE: 'module' + LIBRARY: 'library' }); const CPU = Object.freeze({ diff --git a/src/extensions/ua-parser-extensions.d.ts b/src/extensions/ua-parser-extensions.d.ts index 89f5bd3a5..013a3d75b 100644 --- a/src/extensions/ua-parser-extensions.d.ts +++ b/src/extensions/ua-parser-extensions.d.ts @@ -11,5 +11,5 @@ export const ExtraDevices: UAParserExt; export const Emails: UAParserExt; export const Fetchers: UAParserExt; export const InApps: UAParserExt; -export const MediaPlayers: UAParserExt; -export const Modules: UAParserExt; \ No newline at end of file +export const Libraries: UAParserExt; +export const MediaPlayers: UAParserExt; \ No newline at end of file diff --git a/src/extensions/ua-parser-extensions.js b/src/extensions/ua-parser-extensions.js index 182bd872d..1ba574fad 100644 --- a/src/extensions/ua-parser-extensions.js +++ b/src/extensions/ua-parser-extensions.js @@ -20,7 +20,7 @@ const EMAIL = 'email'; const FETCHER = 'fetcher'; const INAPP = 'inapp'; const MEDIAPLAYER = 'mediaplayer'; -const MODULE = 'module'; +const LIBRARY = 'library'; ////////////////////// // COMMAND LINE APPS @@ -332,14 +332,14 @@ const MediaPlayers = Object.freeze({ ] }); -//////////////////////// -// MODULES / LIBRARIES -/////////////////////// +///////////// +// LIBRARIES +////////////// -const Modules = Object.freeze({ +const Libraries = Object.freeze({ browser : [ // Axios/jsdom/Scrapy - [/\b(axios|jsdom|scrapy)\/([\w\.]+)/i], [NAME, VERSION, [TYPE, MODULE]] + [/\b(axios|jsdom|scrapy)\/([\w\.]+)/i], [NAME, VERSION, [TYPE, LIBRARY]] ] }); @@ -352,7 +352,7 @@ const Bots = Object.freeze({ ...CLIs.browser, ...Crawlers.browser, ...Fetchers.browser, - ...Modules.browser + ...Libraries.browser ] }); @@ -364,6 +364,6 @@ module.exports = { Emails, Fetchers, InApps, - MediaPlayers, - Modules + Libraries, + MediaPlayers }; \ No newline at end of file diff --git a/src/helpers/ua-parser-helpers.js b/src/helpers/ua-parser-helpers.js index ce2db0c8e..cd63a79ff 100644 --- a/src/helpers/ua-parser-helpers.js +++ b/src/helpers/ua-parser-helpers.js @@ -37,7 +37,7 @@ const isAppleSilicon = (res, useFeatureDetection) => { return false; } -const isBot = (res) => ['cli', 'crawler', 'fetcher', 'module'].includes(res.browser.type); +const isBot = (res) => ['cli', 'crawler', 'fetcher', 'library'].includes(res.browser.type); const isChromeFamily = (res) => res.engine.is(Engine.BLINK); diff --git a/src/main/ua-parser.d.ts b/src/main/ua-parser.d.ts index b54f4cdb5..cbf583717 100644 --- a/src/main/ua-parser.d.ts +++ b/src/main/ua-parser.d.ts @@ -15,7 +15,7 @@ declare namespace UAParser { name?: string; version?: string; major?: string; - type?: 'crawler' | 'cli' | 'email' | 'fetcher' | 'inapp' | 'mediaplayer' | 'module'; + type?: 'crawler' | 'cli' | 'email' | 'fetcher' | 'inapp' | 'mediaplayer' | 'library'; } interface ICPU extends IData { diff --git a/test/dts-test.ts b/test/dts-test.ts index 0f05a8aa2..39bb4a30f 100644 --- a/test/dts-test.ts +++ b/test/dts-test.ts @@ -28,7 +28,7 @@ expectType(browser); expectType(browser.name); expectType(browser.version); expectType(browser.major); -expectType<'crawler' | 'cli' | 'email' | 'fetcher' | 'inapp' | 'mediaplayer' | 'module' | undefined>(browser.type); +expectType<'crawler' | 'cli' | 'email' | 'fetcher' | 'inapp' | 'mediaplayer' | 'library' | undefined>(browser.type); expectType(browser.is('')); expectType(browser.toString()); expectType>(browser.withClientHints()); diff --git a/test/mocha-test-extension.js b/test/mocha-test-extension.js index 2f81a5c2f..246bf35aa 100644 --- a/test/mocha-test-extension.js +++ b/test/mocha-test-extension.js @@ -8,8 +8,8 @@ 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 { Bots, CLIs, Crawlers, Emails, Fetchers, Modules } = require('../src/extensions/ua-parser-extensions'); +const libraries = require('./specs/browser-libraries.json'); +const { Bots, CLIs, Crawlers, Emails, Fetchers, Libraries } = require('../src/extensions/ua-parser-extensions'); describe('Extensions', () => { [ @@ -17,7 +17,7 @@ describe('Extensions', () => { ['Crawlers', crawlers, Crawlers], ['Emails', emails, Emails], ['Fetchers', fetchers, Fetchers], - ['Modules', modules, Modules] + ['Libraries', libraries, Libraries] ] .forEach((list) => { describe(list[0], () => { @@ -44,10 +44,10 @@ describe('Extensions', () => { 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"}); + const libraryParser = new UAParser(Libraries); + assert.deepEqual(libraryParser.setUA(axios).getBrowser(), {name: "axios", version: "1.3.5", major: "1", type: "library"}); + assert.deepEqual(libraryParser.setUA(jsdom).getBrowser(), {name: "jsdom", version: "20.0.3", major: "20", type: "library"}); + assert.deepEqual(libraryParser.setUA(scrapy).getBrowser(), {name: "Scrapy", version: "1.5.0", major: "1", type: "library"}); }); describe('Merge', () => { diff --git a/test/specs/browser-modules.json b/test/specs/browser-libraries.json similarity index 86% rename from test/specs/browser-modules.json rename to test/specs/browser-libraries.json index 1639a1973..8e0eb56fb 100644 --- a/test/specs/browser-modules.json +++ b/test/specs/browser-libraries.json @@ -6,7 +6,7 @@ { "name" : "Scrapy", "version" : "1.5.0", - "type" : "module" + "type" : "library" } } ] From a0e11b701e6c7b25230115a6de9e7d69dd3bfeee Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Sun, 10 Nov 2024 13:01:46 +0700 Subject: [PATCH 58/64] [submodule:extensions] Add some new bots: `360Spider`, `Archive.org Bots`, `CCBot`, `DataForSeoBot`, `DuckAssistBot`, `Exabot`, `Google Bots`, `Meta Bots`, `MojeekBot`, `PerplexityBot`, `PetalBot`, `TurnitinBot`, `Yeti`, `YisouSpider` --- src/extensions/ua-parser-extensions.js | 56 ++++- test/specs/browser-crawlers.json | 301 +++++++++++++++++++++++++ test/specs/browser-fetchers.json | 70 ++++++ 3 files changed, 415 insertions(+), 12 deletions(-) diff --git a/src/extensions/ua-parser-extensions.js b/src/extensions/ua-parser-extensions.js index 1ba574fad..d80e48c43 100644 --- a/src/extensions/ua-parser-extensions.js +++ b/src/extensions/ua-parser-extensions.js @@ -44,26 +44,36 @@ const Crawlers = Object.freeze({ // Amazonbot - https://developer.amazon.com/amazonbot // Applebot - http://apple.com/go/applebot // Bingbot - http://www.bing.com/bingbot.htm + // CCBot - https://commoncrawl.org/faq // Dotbot - https://moz.com/help/moz-procedures/crawlers/dotbot // DuckDuckBot - http://duckduckgo.com/duckduckbot.html // FacebookBot - https://developers.facebook.com/docs/sharing/bot/ // GPTBot - https://platform.openai.com/docs/gptbot // MJ12bot - https://mj12bot.com/ - // OpenAI Search - https://platform.openai.com/docs/bots + // MojeekBot - https://www.mojeek.com/bot.html + // OpenAI's SearchGPT - https://platform.openai.com/docs/bots + // PerplexityBot - https://perplexity.ai/perplexitybot // SemrushBot - http://www.semrush.com/bot.html - /((?:ahrefs|amazon|apple|bing|dot|duckduck|facebook|gpt|mj12|oai-search|semrush)bot)\/([\w\.]+)/i, + /((?:ahrefs|amazon|apple|bing|cc|dot|duckduck|exa|facebook|gpt|mj12|mojeek|oai-search|perplexity|semrush)bot)\/([\w\.]+)/i, // Baiduspider https://help.baidu.com/question?prod_id=99&class=0&id=3001 /(baiduspider)[-imagevdonsfcpr]{0,6}\/([\w\.]+)/i, - // ClaudeBot + // ClaudeBot (Anthropic) /(claude(?:bot|-web))\/([\w\.]+)/i, // Coc Coc Bot - https://help.coccoc.com/en/search-engine /(coccocbot-(?:image|web))\/([\w\.]+)/i, + // Facebook / Meta + // https://developers.facebook.com/docs/sharing/webmasters/web-crawlers + /(facebook(?:externalhit|catalog)|meta-externalagent)\/([\w\.]+)/i, + // Googlebot - http://www.google.com/bot.html - /(google(?:bot|other)(?:-image|-video|-news|-extended)?|(?:storebot-)?google(?:-inspectiontool)?)\/?([\w\.]*)/i, + /(google(?:bot|other|-inspectiontool)(?:-image|-video|-news)?|storebot-google)\/?([\w\.]*)/i, + + // Internet Archive (archive.org) + /(ia_archiver|archive\.org_bot)\/?([\w\.]*)/i, // Sogou Spider /(sogou (?:pic|head|web|orion|news) spider)\/([\w\.]+)/i, @@ -72,14 +82,29 @@ const Crawlers = Object.freeze({ /(y!?j-(?:asr|br[uw]|dscv|mmp|vsidx|wsc))\/([\w\.]+)/i, // 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 + /(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, + + // Yeti (Naver) + /(yeti)\/([\w\.]+)/i, + + // YisouSpider + /(yisouspider)\/?([\w\.]*)/i ], [NAME, VERSION, [TYPE, CRAWLER]], - // Bytespider - // Yahoo! Slurp - http://help.yahoo.com/help/us/ysearch/slurp - [/((?:bytespider|(?=yahoo! )slurp))/i], + [ + // Google Bots + /((?:adsbot|apis|mediapartners)-google(?:-mobile)?|google-?(?:other|cloudvertexbot|extended|safety))/i, + + // Bytespider + // DataForSeoBot - https://dataforseo.com/dataforseo-bot + // Huawei AspiegelBot / PetalBot https://aspiegel.com/petalbot + // Qihoo 360Spider + // TurnitinBot - https://www.turnitin.com/robot/crawlerinfo.html + // Yahoo! Slurp - http://help.yahoo.com/help/us/ysearch/slurp + /(360spider-?(?:image|video)?|bytespider|(?:aspiegel|dataforseo|petal|turnitin)bot|(?=yahoo! )slurp)/i + ], [NAME, [TYPE, CRAWLER]] ] }); @@ -184,8 +209,15 @@ const Fetchers = Object.freeze({ [ // AhrefsSiteAudit - https://ahrefs.com/robot/site-audit // ChatGPT-User - https://platform.openai.com/docs/plugins/bot + // DuckAssistBot - https://duckduckgo.com/duckassistbot/ // BingPreview / Mastodon / Pinterestbot / Redditbot / Rogerbot / Telegrambot / Twitterbot / UptimeRobot - /(ahrefssiteaudit|bingpreview|chatgpt-user|mastodon|(?:discord|linkedin|pinterest|reddit|roger|telegram|twitter|uptimero)bot)\/([\w\.]+)/i, + /(ahrefssiteaudit|bingpreview|chatgpt-user|mastodon|(?:discord|duckassist|linkedin|pinterest|reddit|roger|telegram|twitter|uptimero)bot)\/([\w\.]+)/i, + + // Google Site Verifier + /(google-site-verification)\/([\w\.]+)/i, + + // Meta + /(meta-externalfetcher)\/([\w\.]+)/i, // Slackbot - https://api.slack.com/robots /(slack(?:bot)?(?:-imgproxy|-linkexpanding)?) ([\w\.]+)/i, @@ -203,7 +235,7 @@ const Fetchers = Object.freeze({ [NAME, VERSION, [TYPE, FETCHER]], // Google Bots / Snapchat - [/(feedfetcher-google|google-read-aloud|(?=bot; )snapchat)/i], + [/(feedfetcher-google|google(?:-read-aloud|producer)|(?=bot; )snapchat)/i], [NAME, [TYPE, FETCHER]], ] }); @@ -252,8 +284,8 @@ const MediaPlayers = Object.freeze({ /(flrp)\/([\w\.-]+)/i // Flip Player ], [[NAME, 'Flip Player'], VERSION, [TYPE, MEDIAPLAYER]], [ - /(fstream|nativehost|queryseekspider|ia-archiver|facebookexternalhit)/i - // FStream/NativeHost/QuerySeekSpider/IA Archiver/facebookexternalhit + /(fstream|nativehost|queryseekspider)/i + // FStream/NativeHost/QuerySeekSpider ], [NAME, [TYPE, MEDIAPLAYER]], [ /(gstreamer) souphttpsrc.+libsoup\/([\w\.-]+)/i diff --git a/test/specs/browser-crawlers.json b/test/specs/browser-crawlers.json index 45e25ad18..e527740e3 100644 --- a/test/specs/browser-crawlers.json +++ b/test/specs/browser-crawlers.json @@ -1,4 +1,44 @@ [ + { + "desc" : "360Spider", + "ua" : "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0); 360Spider", + "expect" : + { + "name" : "360Spider", + "version" : "undefined", + "type" : "crawler" + } + }, + { + "desc" : "AdsBot Mobile Web", + "ua" : "AdsBot-Google (+http://www.google.com/adsbot.html)", + "expect" : + { + "name" : "AdsBot-Google", + "version" : "undefined", + "type" : "crawler" + } + }, + { + "desc" : "AdsBot Mobile Web", + "ua" : "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.96 Mobile Safari/537.36 (compatible; AdsBot-Google-Mobile; +http://www.google.com/mobile/adsbot.html)", + "expect" : + { + "name" : "AdsBot-Google-Mobile", + "version" : "undefined", + "type" : "crawler" + } + }, + { + "desc" : "AdSense", + "ua" : "Mediapartners-Google", + "expect" : + { + "name" : "Mediapartners-Google", + "version" : "undefined", + "type" : "crawler" + } + }, { "desc" : "AhrefsBot", "ua" : "Mozilla/5.0 (compatible; AhrefsBot/7.0; +http://ahrefs.com/robot/)", @@ -49,6 +89,16 @@ "type" : "crawler" } }, + { + "desc" : "CCBot", + "ua" : "CCBot/1.0 (+https://commoncrawl.org/bot.html)", + "expect" : + { + "name" : "CCBot", + "version" : "1.0", + "type" : "crawler" + } + }, { "desc" : "Coc Coc Bot (web)", "ua" : "Mozilla/5.0 (compatible; coccocbot-web/1.0; +http://help.coccoc.com/searchengine)", @@ -79,6 +129,16 @@ "type" : "crawler" } }, + { + "desc" : "DataForSEO", + "ua" : "Mozilla/5.0 (compatible; DataForSeoBot; +https://dataforseo.com/dataforseo-bot) ", + "expect" : + { + "name" : "DataForSeoBot", + "version" : "undefined", + "type" : "crawler" + } + }, { "desc" : "Dotbot", "ua" : "Mozilla/5.0 (compatible; DotBot/1.2; +https://opensiteexplorer.org/dotbot; help@moz.com)", @@ -89,6 +149,16 @@ "type" : "crawler" } }, + { + "desc" : "Exabot", + "ua" : "Mozilla/5.0 (compatible; Exabot/3.0; +http://www.exabot.com/go/robot)", + "expect" : + { + "name" : "Exabot", + "version" : "3.0", + "type" : "crawler" + } + }, { "desc" : "FacebookBot", "ua" : "Mozilla/5.0 (compatible; FacebookBot/1.0; +https://developers.facebook.com/docs/sharing/webmasters/facebookbot/", @@ -99,6 +169,26 @@ "type" : "crawler" } }, + { + "desc" : "FacebookExternalHit", + "ua" : "facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)", + "expect" : + { + "name" : "facebookexternalhit", + "version" : "1.1", + "type" : "crawler" + } + }, + { + "desc" : "FacebookExternalHit", + "ua" : "facebookcatalog/1.0", + "expect" : + { + "name" : "facebookcatalog", + "version" : "1.0", + "type" : "crawler" + } + }, { "desc" : "Googlebot-Video", "ua" : "Googlebot-Video/1.0", @@ -109,6 +199,106 @@ "type" : "crawler" } }, + { + "desc" : "Googlebot", + "ua" : "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)", + "expect" : + { + "name" : "Googlebot", + "version" : "2.1", + "type" : "crawler" + } + }, + { + "desc" : "Googlebot Image", + "ua" : "Googlebot-Image/1.0", + "expect" : + { + "name" : "Googlebot-Image", + "version" : "1.0", + "type" : "crawler" + } + }, + { + "desc" : "Googlebot Video", + "ua" : "Googlebot-Video/1.0", + "expect" : + { + "name" : "Googlebot-Video", + "version" : "1.0", + "type" : "crawler" + } + }, + { + "desc" : "Googlebot News", + "ua" : "Googlebot-News/1.0", + "expect" : + { + "name" : "Googlebot-News", + "version" : "1.0", + "type" : "crawler" + } + }, + { + "desc" : "Google Storebot", + "ua" : "Storebot-Google/1.0", + "expect" : + { + "name" : "Storebot-Google", + "version" : "1.0", + "type" : "crawler" + } + }, + { + "desc" : "Google InspectionTool", + "ua" : "Mozilla/5.0 (compatible; Google-InspectionTool/1.0;)", + "expect" : + { + "name" : "Google-InspectionTool", + "version" : "1.0", + "type" : "crawler" + } + }, + { + "desc" : "GoogleOther", + "ua" : "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; GoogleOther) Chrome/41.0.2272.96 Safari/537.36", + "expect" : + { + "name" : "GoogleOther", + "version" : "undefined", + "type" : "crawler" + } + }, + { + "desc" : "GoogleOther-Image", + "ua" : "GoogleOther-Image/1.0", + "expect" : + { + "name" : "GoogleOther-Image", + "version" : "1.0", + "type" : "crawler" + } + }, + { + "desc" : "GoogleOther-Video", + "ua" : "GoogleOther-Video/1.0", + "expect" : + { + "name" : "GoogleOther-Video", + "version" : "1.0", + "type" : "crawler" + } + }, + { + "desc" : "Google-Safety", + "ua" : "Google-Safety", + "expect" : + { + "name" : "Google-Safety", + "version" : "undefined", + "type" : "crawler" + } + }, { "desc" : "GPTBot", "ua" : "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; GPTBot/1.0; +https://openai.com/gptbot)", @@ -119,6 +309,36 @@ "type" : "crawler" } }, + { + "desc" : "Archive.org Bot", + "ua" : "ia_archiver/8.1 (Windows 2000 1.9; en-US;)", + "expect" : + { + "name" : "ia_archiver", + "version" : "8.1", + "type" : "crawler" + } + }, + { + "desc" : "Archive.org Bot", + "ua" : "Mozilla/5.0 (compatible; archive.org_bot/3.3.0 +https://archive.org/details/archive.org_bot)", + "expect" : + { + "name" : "archive.org_bot", + "version" : "3.3.0", + "type" : "crawler" + } + }, + { + "desc" : "Meta-ExternalAgent", + "ua" : "meta-externalagent/1.1 (+https://developers.facebook.com/docs/sharing/webmasters/crawler)", + "expect" : + { + "name" : "meta-externalagent", + "version" : "1.1", + "type" : "crawler" + } + }, { "desc" : "MJ12bot", "ua" : "Mozilla/5.0 (compatible; MJ12bot/v1.4.8; http://mj12bot.com/)", @@ -126,6 +346,17 @@ { "name" : "MJ12bot", "version" : "v1.4.8", + "major" : "1", + "type" : "crawler" + } + }, + { + "desc" : "MojeekBot", + "ua" : "Mozilla/5.0 (compatible; MojeekBot/0.11; +https://www.mojeek.com/bot.html)", + "expect" : + { + "name" : "MojeekBot", + "version" : "0.11", "type" : "crawler" } }, @@ -139,6 +370,36 @@ "type" : "crawler" } }, + { + "desc" : "PerplexityBot", + "ua" : "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; PerplexityBot/1.0; +https://perplexity.ai/perplexitybot)", + "expect" : + { + "name" : "PerplexityBot", + "version" : "1.0", + "type" : "crawler" + } + }, + { + "desc" : "PetalBot", + "ua" : "Mozilla/5.0 (compatible;PetalBot; +https://webmaster.petalsearch.com/site/petalbot) ", + "expect" : + { + "name" : "PetalBot", + "version" : "undefined", + "type" : "crawler" + } + }, + { + "desc" : "PetalBot", + "ua" : "Mozilla/5.0 (Linux; Android 7.0;) AppleWebKit/537.36 (KHTML, like Gecko) Mobile Safari/537.36 (compatible; PetalBot;+https://webmaster.petalsearch.com/site/petalbot) ", + "expect" : + { + "name" : "PetalBot", + "version" : "undefined", + "type" : "crawler" + } + }, { "desc" : "SemrushBot", "ua" : "Mozilla/5.0 (compatible; SemrushBot/7~bl; +http://www.semrush.com/bot.html)", @@ -149,6 +410,16 @@ "type" : "crawler" } }, + { + "desc" : "TurnitinBot", + "ua" : "TurnitinBot (https://turnitin.com/robot/crawlerinfo.html)", + "expect" : + { + "name" : "TurnitinBot", + "version" : "undefined", + "type" : "crawler" + } + }, { "desc" : "Yahoo! Japan", "ua" : "Y!J-BRW/1.0 (https://www.yahoo-help.jp/app/answers/detail/p/595/a_id/42716)", @@ -168,5 +439,35 @@ "version" : "3.0", "type" : "crawler" } + }, + { + "desc" : "Yeti", + "ua" : "Mozilla/5.0 (compatible; Yeti/1.1; +http://naver.me/spd)", + "expect" : + { + "name" : "Yeti", + "version" : "1.1", + "type" : "crawler" + } + }, + { + "desc" : "YisouSpider", + "ua" : "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.81 YisouSpider/5.0 Safari/537.36", + "expect" : + { + "name" : "YisouSpider", + "version" : "5.0", + "type" : "crawler" + } + }, + { + "desc" : "YisouSpider", + "ua" : "YisouSpider", + "expect" : + { + "name" : "YisouSpider", + "version" : "undefined", + "type" : "crawler" + } } ] diff --git a/test/specs/browser-fetchers.json b/test/specs/browser-fetchers.json index c508bd22f..94bada00e 100644 --- a/test/specs/browser-fetchers.json +++ b/test/specs/browser-fetchers.json @@ -29,6 +29,76 @@ "type" : "fetcher" } }, + { + "desc" : "DuckAssistBot", + "ua" : "DuckAssistBot/1.2; (+http://duckduckgo.com/duckassistbot.html)", + "expect" : + { + "name" : "DuckAssistBot", + "version" : "1.2", + "type" : "fetcher" + } + }, + { + "desc" : "Google FeedFetcher", + "ua" : "FeedFetcher-Google; (+http://www.google.com/feedfetcher.html)", + "expect" : + { + "name" : "FeedFetcher-Google", + "version" : "undefined", + "type" : "fetcher" + } + }, + { + "desc" : "Google Read Aloud - Mobile agent", + "ua" : "Mozilla/5.0 (Linux; Android 7.0; SM-G930V Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.125 Mobile Safari/537.36 (compatible; Google-Read-Aloud; +https://support.google.com/webmasters/answer/1061943)", + "expect" : + { + "name" : "Google-Read-Aloud", + "version" : "undefined", + "type" : "fetcher" + } + }, + { + "desc" : "Google Read Aloud - Desktop agent", + "ua" : "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36 (compatible; Google-Read-Aloud; +https://support.google.com/webmasters/answer/1061943)", + "expect" : + { + "name" : "Google-Read-Aloud", + "version" : "undefined", + "type" : "fetcher" + } + }, + { + "desc" : "Google Publisher Center", + "ua" : "GoogleProducer; (+https://developers.google.com/search/docs/crawling-indexing/google-producer)", + "expect" : + { + "name" : "GoogleProducer", + "version" : "undefined", + "type" : "fetcher" + } + }, + { + "desc" : "Google Site Verifier", + "ua" : "Mozilla/5.0 (compatible; Google-Site-Verification/1.0)", + "expect" : + { + "name" : "Google-Site-Verification", + "version" : "1.0", + "type" : "fetcher" + } + }, + { + "desc" : "Meta-ExternalFetcher", + "ua" : "meta-externalfetcher/1.1 (+https://developers.facebook.com/docs/sharing/webmasters/crawler)", + "expect" : + { + "name" : "meta-externalfetcher", + "version" : "1.1", + "type" : "fetcher" + } + }, { "desc" : "Rogerbot", "ua" : "Mozilla/5.0 (compatible; rogerBot/1.0; UrlCrawler; http://www.seomoz.org/dp/rogerbot)", From cbe06acaf2834d897c2d3243ad86a81bd2abaa4f Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Sun, 10 Nov 2024 19:32:37 +0700 Subject: [PATCH 59/64] [submodule:extensions] Add email clients: `Evolution`, `KMail`, `Kontact` --- src/extensions/ua-parser-extensions.js | 4 +- test/specs/browser-emails.json | 60 ++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/src/extensions/ua-parser-extensions.js b/src/extensions/ua-parser-extensions.js index d80e48c43..936c90bd2 100644 --- a/src/extensions/ua-parser-extensions.js +++ b/src/extensions/ua-parser-extensions.js @@ -195,8 +195,8 @@ const ExtraDevices = Object.freeze({ const Emails = Object.freeze({ browser : [ - // Microsoft Outlook / Thunderbird - [/(microsoft outlook|thunderbird)[\s\/]([\w\.]+)/i], [NAME, VERSION, [TYPE, EMAIL]] + // Evolution / Kontact/KMail / [Microsoft/Mac] Outlook / Thunderbird + [/(evolution|kmail2?|kontact|(?:microsoft |mac)outlook|thunderbird)[\s\/]([\w\.]+)/i], [NAME, VERSION, [TYPE, EMAIL]] ] }); diff --git a/test/specs/browser-emails.json b/test/specs/browser-emails.json index 1ce6b3029..883f32be6 100644 --- a/test/specs/browser-emails.json +++ b/test/specs/browser-emails.json @@ -1,4 +1,64 @@ [ + { + "desc" : "Evolution", + "ua" : "Evolution/3.52.3", + "expect" : + { + "name" : "Evolution", + "version" : "3.52.3", + "type" : "email" + } + }, + { + "desc" : "KMail", + "ua" : "KMail/4.14.10 (FreeBSD/12.0-CURRENT; KDE/4.14.10; amd64; ; )", + "expect" : + { + "name" : "KMail", + "version" : "4.14.10", + "type" : "email" + } + }, + { + "desc" : "KMail2", + "ua" : "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.34 (KHTML, like Gecko) kmail2/5.7.3 Safari/534.34", + "expect" : + { + "name" : "kmail2", + "version" : "5.7.3", + "type" : "email" + } + }, + { + "desc" : "Kontact", + "ua" : "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.34 (KHTML, like Gecko) kontact/4.13.3 Safari/534.34", + "expect" : + { + "name" : "kontact", + "version" : "4.13.3", + "type" : "email" + } + }, + { + "desc" : "Microsoft Outlook", + "ua" : "Microsoft Office/16.0 (Windows NT 10.0; Microsoft Outlook 16.0.5431; Pro)", + "expect" : + { + "name" : "Microsoft Outlook", + "version" : "16.0.5431", + "type" : "email" + } + }, + { + "desc" : "Microsoft Outlook for Mac", + "ua" : "MacOutlook/14.7.1.161129 (Intel Mac OS X 10.9.6)", + "expect" : + { + "name" : "MacOutlook", + "version" : "14.7.1.161129", + "type" : "email" + } + }, { "desc" : "Thunderbird", "ua" : "Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.13.0", From 49151e478c4af104d7226463c5c4d3ff641fdbea Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Mon, 11 Nov 2024 19:55:40 +0700 Subject: [PATCH 60/64] Add new browser engine: `Servo` --- src/enums/ua-parser-enums.js | 1 + src/main/ua-parser.js | 2 +- test/specs/engine-all.json | 9 +++++++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/enums/ua-parser-enums.js b/src/enums/ua-parser-enums.js index 903aa057c..c81194f90 100644 --- a/src/enums/ua-parser-enums.js +++ b/src/enums/ua-parser-enums.js @@ -274,6 +274,7 @@ const Engine = Object.freeze({ NETFRONT: 'NetFront', NETSURF: 'NetSurf', PRESTO: 'Presto', + SERVO: 'Servo', TASMAN: 'Tasman', TRIDENT: 'Trident', W3M: 'w3m', diff --git a/src/main/ua-parser.js b/src/main/ua-parser.js index 7d5173540..0f046afaf 100755 --- a/src/main/ua-parser.js +++ b/src/main/ua-parser.js @@ -814,7 +814,7 @@ ], [VERSION, [NAME, 'Blink']], [ /(presto)\/([\w\.]+)/i, // Presto - /(webkit|trident|netfront|netsurf|amaya|lynx|w3m|goanna)\/([\w\.]+)/i, // WebKit/Trident/NetFront/NetSurf/Amaya/Lynx/w3m/Goanna + /(webkit|trident|netfront|netsurf|amaya|lynx|w3m|goanna|servo)\/([\w\.]+)/i, // WebKit/Trident/NetFront/NetSurf/Amaya/Lynx/w3m/Goanna/Servo /ekioh(flow)\/([\w\.]+)/i, // Flow /(khtml|tasman|links)[\/ ]\(?([\w\.]+)/i, // KHTML/Tasman/Links /(icab)[\/ ]([23]\.[\d\.]+)/i, // iCab diff --git a/test/specs/engine-all.json b/test/specs/engine-all.json index 67fdd3381..7523fc36e 100644 --- a/test/specs/engine-all.json +++ b/test/specs/engine-all.json @@ -89,6 +89,15 @@ "version" : "2.8.149" } }, + { + "desc" : "Servo", + "ua" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Servo/1.0 Firefox/111.0", + "expect" : + { + "name" : "Servo", + "version" : "1.0" + } + }, { "desc" : "Tasman", "ua" : "Mozilla/4.0 (compatible; MSIE 6.0; PPC Mac OS X 10.4.7; Tasman 1.0)", From 6b8920c7007d92ade3d7468062c274b81f00cbb0 Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Mon, 11 Nov 2024 21:41:07 +0700 Subject: [PATCH 61/64] Add new device vendors: `Cat`, `Energizer`, `Micromax` - https://www.catphones.com - https://www.energizeyourdevice.com - https://micromaxinfo.com/ --- src/enums/ua-parser-enums.js | 3 ++ src/main/ua-parser.js | 16 +++++-- test/specs/device-all.json | 90 ++++++++++++++++++++++++++++++++++++ 3 files changed, 106 insertions(+), 3 deletions(-) diff --git a/src/enums/ua-parser-enums.js b/src/enums/ua-parser-enums.js index c81194f90..67d0155a2 100644 --- a/src/enums/ua-parser-enums.js +++ b/src/enums/ua-parser-enums.js @@ -203,7 +203,9 @@ const Vendor = Object.freeze({ ATT: 'AT&T', BENQ: 'BenQ', BLACKBERRY: 'BlackBerry', + CAT: 'Cat', DELL: 'Dell', + ENERGIZER: 'Energizer', ESSENTIAL: 'Essential', FACEBOOK: 'Facebook', FAIRPHONE: 'Fairphone', @@ -220,6 +222,7 @@ const Vendor = Object.freeze({ LENOVO: 'Lenovo', LG: 'LG', MEIZU: 'Meizu', + MICROMAX: 'Micromax', MICROSOFT: 'Microsoft', MOTOROLA: 'Motorola', NEXIAN: 'Nexian', diff --git a/src/main/ua-parser.js b/src/main/ua-parser.js index 0f046afaf..6c7a86ea5 100755 --- a/src/main/ua-parser.js +++ b/src/main/ua-parser.js @@ -600,7 +600,7 @@ ], [MODEL, [VENDOR, GOOGLE], [TYPE, MOBILE]], [ // Sony - /droid.+ (a?\d[0-2]{2}so|[c-g]\d{4}|so[-gl]\w+|xq-a\w[4-7][12])(?= bui|\).+chrome\/(?![1-6]{0,1}\d\.))/i + /droid.+; (a?\d[0-2]{2}so|[c-g]\d{4}|so[-gl]\w+|xq-a\w[4-7][12])(?= bui|\).+chrome\/(?![1-6]{0,1}\d\.))/i ], [MODEL, [VENDOR, SONY], [TYPE, MOBILE]], [ /sony tablet [ps]/i, /\b(?:sony)?sgp\w+(?: bui|\))/i @@ -666,13 +666,23 @@ /; ((?:power )?armor(?:[\w ]{0,8}))(?: bui|\))/i ], [MODEL, [VENDOR, 'Ulefone'], [TYPE, MOBILE]], [ + // Energizer + /; (energy ?\w+)(?: bui|\))/i, + /; energizer ([\w ]+?)(?: bui|\))/i + ], [MODEL, [VENDOR, 'Energizer'], [TYPE, MOBILE]], [ + + // Cat + /; cat (b35);/i, + /; (b15q?|s22 flip|s48c|s62 pro)(?: bui|\))/i + ], [MODEL, [VENDOR, 'Cat'], [TYPE, MOBILE]], [ + // Nothing /droid.+; (a(?:015|06[35]|142p?))/i ], [MODEL, [VENDOR, 'Nothing'], [TYPE, MOBILE]], [ // MIXED - /(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus|dell|meizu|motorola|polytron|infinix|tecno)[-_ ]?([-\w]*)/i, - // BlackBerry/BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron + /(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus|dell|meizu|motorola|polytron|infinix|tecno|micromax)[-_ ]?([-\w]*)/i, + // BlackBerry/BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron/Infinix/Tecno/Micromax /(hp) ([\w ]+\w)/i, // HP iPAQ /(asus)-?(\w+)/i, // Asus /(microsoft); (lumia[\w ]+)/i, // Microsoft Lumia diff --git a/test/specs/device-all.json b/test/specs/device-all.json index e7003247c..810a15374 100644 --- a/test/specs/device-all.json +++ b/test/specs/device-all.json @@ -215,6 +215,42 @@ "type": "mobile" } }, + { + "desc": "Cat B15Q", + "ua": "Mozilla/5.0 (Linux; Android 4.4.2; B15Q) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.80 Mobile Safari/537.36", + "expect": { + "vendor": "Cat", + "model": "B15Q", + "type": "mobile" + } + }, + { + "desc": "Cat B35", + "ua": "Mozilla/5.0 (Mobile; CAT B35; rv:48.0) Gecko/48.0 Firefox/48.0 KAIOS/2.5.1", + "expect": { + "vendor": "Cat", + "model": "B35", + "type": "mobile" + } + }, + { + "desc": "Cat S22 Flip", + "ua": "Mozilla/5.0 (Linux; Android 11; S22 FLIP Build/RKQ1.210416.002) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.165 Mobile Safari/537.36", + "expect": { + "vendor": "Cat", + "model": "S22 FLIP", + "type": "mobile" + } + }, + { + "desc": "Cat S62 Pro", + "ua": "Mozilla/5.0 (Linux; Android 11; S62 Pro Build/RKQ1.210406.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/94.0.4606.85 Mobile Safari/537.36 GSA/12.34.17.23.arm64", + "expect": { + "vendor": "Cat", + "model": "S62 Pro", + "type": "mobile" + } + }, { "desc": "Desktop (IE11 with Tablet string)", "ua": "Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; .NET4.0E; .NET4.0C; .NET CLR 3.5.30729; .NET CLR 2.0.50727; .NET CLR 3.0.30729; Tablet PC 2.0; GWX:MANAGED; rv:11.0) like Gecko", @@ -233,6 +269,33 @@ "type": "mobile" } }, + { + "desc": "Energizer Energy 400", + "ua": "Mozilla/5.0 (Linux; Android 6.0; Energy400 Build/MRA58K test-keys; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.158 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/172.0.0.66.93;]", + "expect": { + "vendor": "Energizer", + "model": "Energy400", + "type": "mobile" + } + }, + { + "desc": "Energizer Energy 400S", + "ua": "Mozilla/5.0 (Linux; Android 6.0; Energy 400S Build/MRA58K; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/68.0.3440.85 Mobile Safari/537.36", + "expect": { + "vendor": "Energizer", + "model": "Energy 400S", + "type": "mobile" + } + }, + { + "desc": "Energizer Ultimate 65G", + "ua": "Mozilla/5.0 (Linux; Android 14; Energizer Ultimate 65G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Mobile Safari/537.36", + "expect": { + "vendor": "Energizer", + "model": "Ultimate 65G", + "type": "mobile" + } + }, { "desc": "Fairphone 1U", "ua": "Mozilla/5.0 (Linux; U; Android 4.2.2; FP1U Build/JDQ39) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30", @@ -1151,6 +1214,33 @@ "type": "mobile" } }, + { + "desc": "Micromax Bharat 2 Plus", + "ua": "Mozilla/5.0 (Linux; U; Android 7.0; en-US; Micromax Q402Plus Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.108 UCBrowser/12.12.9.1226 Mobile Safari/537.36", + "expect": { + "vendor": "Micromax", + "model": "Q402Plus", + "type": "mobile" + } + }, + { + "desc": "Micromax Canvas Infinity", + "ua": "Mozilla/5.0 (Linux; U; Android 7.1.2; en-US; Micromax HS2 Build/N2G47H) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 UCBrowser/13.2.0.1296 (SpeedMode) U4/1.0 UCWEB/2.0 Mobile Safari/534.30", + "expect": { + "vendor": "Micromax", + "model": "HS2", + "type": "mobile" + } + }, + { + "desc": "Micromax In 1b", + "ua": "Mozilla/5.0 (Linux; U; Android 10; Micromax E7533 Build/QP1A.190711.020; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/87.0.4280.101 Mobile Safari/537.36 OPR/54.0.2254.56148", + "expect": { + "vendor": "Micromax", + "model": "E7533", + "type": "mobile" + } + }, { "desc": "Microsoft Lumia 950", "ua": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Mobile Safari/537.36 Edge/13.10586", From 84c46131454954c5b767cb8b8259645b5b3e39af Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Tue, 12 Nov 2024 16:07:06 +0700 Subject: [PATCH 62/64] Add new device vendors: `Advan`, `IMO`, `Smartfren` --- src/enums/ua-parser-enums.js | 3 + src/main/ua-parser.js | 12 +++- test/specs/device-all.json | 126 +++++++++++++++++++++++++++++++++++ 3 files changed, 138 insertions(+), 3 deletions(-) diff --git a/src/enums/ua-parser-enums.js b/src/enums/ua-parser-enums.js index 67d0155a2..74218fc14 100644 --- a/src/enums/ua-parser-enums.js +++ b/src/enums/ua-parser-enums.js @@ -195,6 +195,7 @@ const Device = Object.freeze({ const Vendor = Object.freeze({ ACER: 'Acer', + ADVAN: 'Advan', ALCATEL: 'Alcatel', APPLE: 'Apple', AMAZON: 'Amazon', @@ -215,6 +216,7 @@ const Vendor = Object.freeze({ HP: 'HP', HTC: 'HTC', HUAWEI: 'Huawei', + IMO: 'IMO', INFINIX: 'Infinix', ITEL: 'itel', JOLLA: 'Jolla', @@ -244,6 +246,7 @@ const Vendor = Object.freeze({ SAMSUNG: 'Samsung', SHARP: 'Sharp', SIEMENS: 'Siemens', + SMARTFREN: 'Smartfren', SONY: 'Sony', SPRINT: 'Sprint', TCL: 'TCL', diff --git a/src/main/ua-parser.js b/src/main/ua-parser.js index 6c7a86ea5..3615efd46 100755 --- a/src/main/ua-parser.js +++ b/src/main/ua-parser.js @@ -668,7 +668,7 @@ // Energizer /; (energy ?\w+)(?: bui|\))/i, - /; energizer ([\w ]+?)(?: bui|\))/i + /; energizer ([\w ]+)(?: bui|\))/i ], [MODEL, [VENDOR, 'Energizer'], [TYPE, MOBILE]], [ // Cat @@ -676,13 +676,18 @@ /; (b15q?|s22 flip|s48c|s62 pro)(?: bui|\))/i ], [MODEL, [VENDOR, 'Cat'], [TYPE, MOBILE]], [ + // Smartfren + /((?:new )?andromax[\w- ]+)(?: bui|\))/i + ], [MODEL, [VENDOR, 'Smartfren'], [TYPE, MOBILE]], [ + // Nothing /droid.+; (a(?:015|06[35]|142p?))/i ], [MODEL, [VENDOR, 'Nothing'], [TYPE, MOBILE]], [ // MIXED - /(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus|dell|meizu|motorola|polytron|infinix|tecno|micromax)[-_ ]?([-\w]*)/i, - // BlackBerry/BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron/Infinix/Tecno/Micromax + /(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus|dell|meizu|motorola|polytron|infinix|tecno|micromax|advan)[-_ ]?([-\w]*)/i, + // BlackBerry/BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron/Infinix/Tecno/Micromax/Advan + /; (imo) ((?!tab)[\w ]+?)(?: bui|\))/i, // IMO /(hp) ([\w ]+\w)/i, // HP iPAQ /(asus)-?(\w+)/i, // Asus /(microsoft); (lumia[\w ]+)/i, // Microsoft Lumia @@ -691,6 +696,7 @@ /(oppo) ?([\w ]+) bui/i // OPPO ], [VENDOR, MODEL, [TYPE, MOBILE]], [ + /(imo) (tab \w+)/i, // IMO /(kobo)\s(ereader|touch)/i, // Kobo /(archos) (gamepad2?)/i, // Archos /(hp).+(touchpad(?!.+tablet)|tablet)/i, // HP TouchPad diff --git a/test/specs/device-all.json b/test/specs/device-all.json index 810a15374..f0898b9f1 100644 --- a/test/specs/device-all.json +++ b/test/specs/device-all.json @@ -8,6 +8,33 @@ "type": "mobile" } }, + { + "desc": "Advan M4", + "ua": "Mozilla/5.0 (Linux; U; Android 6.0; ADVAN M4 Build/MRA58K; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/44.0.2403.119 Mobile Safari/537.36 OPR/28.0.2254.119214", + "expect": { + "vendor": "ADVAN", + "model": "M4", + "type": "mobile" + } + }, + { + "desc": "Advan S40", + "ua": "Mozilla/5.0 (Linux; Android 7.0; ADVAN S40 Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Mobile Safari/537.36 EdgA/79.0.309.58", + "expect": { + "vendor": "ADVAN", + "model": "S40", + "type": "mobile" + } + }, + { + "desc": "Advan Sketsa 2", + "ua": "Mozilla/5.0 (Linux; Android 11; ADVAN 1011) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.101 Safari/537.36", + "expect": { + "vendor": "ADVAN", + "model": "1011", + "type": "mobile" + } + }, { "desc": "ASUS Nexus 7", "ua": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 7 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.99 Safari/537.36", @@ -845,6 +872,42 @@ "type": "mobile" } }, + { + "desc": "IMO FEEL A2", + "ua": "Mozilla/5.0 (Linux; Android 5.1; IMO FEEL A2 Build/LMY47I; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/49.0.2623.105 Mobile Safari/537.36", + "expect": { + "vendor": "IMO", + "model": "FEEL A2", + "type": "mobile" + } + }, + { + "desc": "IMO Q2", + "ua": "Mozilla/5.0 (Linux; Android 5.1; IMO Q2 Build/LMY47D; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/65.0.3325.109 Mobile Safari/537.36 GSA/7.22.24.21.arm", + "expect": { + "vendor": "IMO", + "model": "Q2", + "type": "mobile" + } + }, + { + "desc": "IMO S2", + "ua": "Mozilla/5.0 (Linux; Android 8.1.0; IMO S2 Build/O11019; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/80.0.3987.162 Mobile Safari/537.36", + "expect": { + "vendor": "IMO", + "model": "S2", + "type": "mobile" + } + }, + { + "desc": "IMO Tab X9", + "ua": "Mozilla/5.0 (Linux; U; Android 4.0.3; id-id; IMO TAB X9 Build/IML74K) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30", + "expect": { + "vendor": "IMO", + "model": "TAB X9", + "type": "tablet" + } + }, { "desc": "Infinix Hot 7 Pro", "ua": "Mozilla/5.0 (Linux; Android 9; Infinix X625C) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Mobile Safari/537.36", @@ -1997,6 +2060,42 @@ "type": "xr" } }, + { + "desc": "Polytron Prime 7 Pro", + "ua": "Mozilla/5.0 (Linux; U; Android 7.0; POLYTRON_P552 Build/NRD90M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/64.0.3282.137 Mobile Safari/537.36 OPR/50.0.2254.149182", + "expect": { + "vendor": "POLYTRON", + "model": "P552", + "type": "mobile" + } + }, + { + "desc": "Polytron Rocket T1", + "ua": "Mozilla/5.0 (Linux; U; Android 5.0; en-US; POLYTRON R2501 Build/LRX21M) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.108 UCBrowser/13.1.2.1293 Mobile Safari/537.36", + "expect": { + "vendor": "POLYTRON", + "model": "R2501", + "type": "mobile" + } + }, + { + "desc": "Polytron Rocket T6", + "ua": "Mozilla/5.0 (Linux; Android 7.0; POLYTRON R2509) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.92 Mobile Safari/537.36", + "expect": { + "vendor": "POLYTRON", + "model": "R2509", + "type": "mobile" + } + }, + { + "desc": "Polytron Zap 6 Posh", + "ua": "Mozilla/5.0 (Linux; U; Android 5.1; in-ID; POLYTRON_4G501 Build/LMY47D) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.108 UCBrowser/12.10.0.1163 UCTurbo/1.9.9.900 Mobile Safari/537.36", + "expect": { + "vendor": "POLYTRON", + "model": "4G501", + "type": "mobile" + } + }, { "desc": "Roku", "ua": "Mozilla/5.0 (Roku) AppleWebKit/537.36 (KHTML, like Gecko) Web/1.1 Safari/537.36", @@ -2447,6 +2546,33 @@ "type": "mobile" } }, + { + "desc": "Smartfren Andromax L", + "ua": "Mozilla/5.0 (Linux; Android 6.0.1; Andromax B26D2H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.127 Mobile Safari/537.36", + "expect": { + "vendor": "Smartfren", + "model": "Andromax B26D2H", + "type": "mobile" + } + }, + { + "desc": "Smartfren Andromax G2", + "ua": "Mozilla/5.0 (Linux; Android 4.4.2; Smartfren Andromax AD9A1H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.83 Mobile Safari/537.36", + "expect": { + "vendor": "Smartfren", + "model": "Andromax AD9A1H", + "type": "mobile" + } + }, + { + "desc": "Smartfren New Andromax I", + "ua": "Mozilla/5.0 (Linux; U; Android 4.1.2; id-id; New Andromax-i Build/JZO54K) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30", + "expect": { + "vendor": "Smartfren", + "model": "New Andromax-i", + "type": "mobile" + } + }, { "desc": "SONY Xperia 1 III", "ua": "Mozilla/5.0 (Linux; Android 11; A101SO) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Mobile Safari/537.36", From ee51caf422b157bb93e88cc091c4aa403df437f2 Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Wed, 13 Nov 2024 10:44:38 +0700 Subject: [PATCH 63/64] Update version to `2.0.0-rc.3` --- CHANGELOG.md | 39 +++++++----- README.md | 62 ++++++++++-------- dist/ua-parser.min.js | 4 +- dist/ua-parser.pack.js | 4 +- package-lock.json | 28 ++++----- package.json | 8 +-- src/enums/ua-parser-enums.js | 2 +- src/enums/ua-parser-enums.mjs | 12 +++- src/extensions/ua-parser-extensions.d.ts | 2 +- src/extensions/ua-parser-extensions.js | 2 +- src/extensions/ua-parser-extensions.mjs | 80 +++++++++++++++++------- src/helpers/ua-parser-helpers.d.ts | 2 +- src/helpers/ua-parser-helpers.js | 2 +- src/helpers/ua-parser-helpers.mjs | 26 ++++---- src/main/ua-parser.d.ts | 6 +- src/main/ua-parser.js | 4 +- src/main/ua-parser.mjs | 44 ++++++++++--- 17 files changed, 208 insertions(+), 119 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 52575f009..3a16881fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # UAParser.js Changelog +# Version 2.0 ## Migrating from v1 to v2 - What's breaking: @@ -8,28 +9,38 @@ - OS detection: `"Mac OS" => "macOS"`, `"Chromium OS" => "Chrome OS"` - What's new: - New device type: `xr`, to identify AR/VR devices - - New browser property: `browser.type`, to identify the type of the browser: `crawler`, `cli`, `email`, `fetcher`, `inapp`, `mediaplayer`, `module` + - New browser property: `browser.type`, to identify the type of the browser: `crawler`, `cli`, `email`, `fetcher`, `inapp`, `library`, `mediaplayer` - New methods in result object (all of `get*()` return value): - - Support for client hints: `withClientHints()` - - Support for feature detection: `withFeatureCheck()` + - Enhance detection using client hints: `withClientHints()` + - Enhance detection using feature check: `withFeatureCheck()` - Utility for easy comparison: `is()` - Utility to print full-name: `toString()` - - Parse directly from command line using `npx ua-parser-js` + - Parse user-agent directly from command line using `npx ua-parser-js "[User-Agent]"` - Extensions can be passed as a list to `UAParser()` - Support for ES module & TypeScript `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'`: - - `getDeviceVendor()` to guess for a device vendor based on its model name - - `isAppleSilicon()` to check if the device has Apple Silicon Mac device properties - - `isBot()` to check if the browser is identified as a bot - - `isChromeFamily()` to check if the browser is Chrome-based / has Blink engine (i.e: New Opera, New Edge, Vivaldi, Brave, Arc, etc.) - - `isElectron()` to check if current window is running inside Electron - - `isFromEU()` to check if current window is from an EU (European Union) country - - `isFrozenUA()` to check if a user-agent string match with the reduced/frozen user-agent pattern - - `isStandalonePWA()` to check if current window is a standalone PWA + - `getDeviceVendor()`: guess for a device vendor based on its model name + - `isAppleSilicon()`: check if the device has Apple Silicon Mac device properties + - `isBot()`: check if the browser is identified as a bot + - `isChromeFamily()`: check if the browser is Chrome-based (has Blink engine, i.e: New Opera, New Edge, Vivaldi, Brave, Arc, etc.) + - `isElectron()`: check if current window is running inside Electron + - `isFromEU()`: check if current window is from an EU (European Union) country + - `isFrozenUA()`: check if a user-agent string match with the reduced/frozen user-agent pattern + - `isStandalonePWA()`: check if current window is a standalone PWA + +--- --- +## Version 2.0.0-rc.3 + +- Add support for Headers object +- Add new device: Advan, Cat, Energizer, Honor, IMO, Micromax, Smartfren +- Add new engine: Servo +- `ua-parser-js/extensions` submodule: + - Breaking change: rename `module` to `library` + - Add new email clients: Evolution, KMail, Kontact + - Add new bots: 360Spider, Archive.org Bots, CCBot, DataForSeoBot, DuckAssistBot, Exabot, Google Bots, Meta Bots, MojeekBot, PerplexityBot, PetalBot, TurnitinBot, Yeti, YisouSpider ## Version 2.0.0-rc.2 @@ -59,7 +70,7 @@ - Rename `isChromiumBased()` to `isChromeFamily()` - Update `isAppleSilicon()` to also checks for WebGL renderer info - `ua-parser-js/extensions` submodule: - - Restore `bots` as a compilation of all these browser types: `clis`, `crawlers`, `fetchers`, and `modules` + - Restore `Bots` as a compilation of all these browser types: `cli`, `crawler`, `fetcher`, and `library` ## Version 2.0.0-beta.3 diff --git a/README.md b/README.md index 701add0cd..7b0aa5fa8 100644 --- a/README.md +++ b/README.md @@ -44,15 +44,15 @@ see what's new & breaking. License options - MIT (v1.x) - AGPL (v2.x) + MIT (v0.7~v1.0) + AGPL (>=v2.0) PRO Personal PRO Business PRO Enterprise Browser detection - ⚠️ + ⚠️ ✅ ✅ ✅ @@ -60,7 +60,7 @@ see what's new & breaking. CPU detection - ⚠️ + ⚠️ ✅ ✅ ✅ @@ -68,7 +68,7 @@ see what's new & breaking. Device detection - ⚠️ + ⚠️ ✅ ✅ ✅ @@ -76,7 +76,7 @@ see what's new & breaking. Engine detection - ⚠️ + ⚠️ ✅ ✅ ✅ @@ -84,31 +84,39 @@ see what's new & breaking. OS detection - ⚠️ + ⚠️ ✅ ✅ ✅ ✅ - Enhanced detection - ⛔️ + Bot detection + ❌ ✅ ✅ ✅ ✅ - Client Hints support - ⛔️ + Extras (Apps, Libs, Emails, Media Players, etc) + ❌ + ✅ + ✅ + ✅ + ✅ + + + Enhanced detection result + ❌ ✅ ✅ ✅ ✅ - Extras (Apps, Bots, Libs, Emails, Media Players, etc) - ⛔️ + Client Hints support + ❌ ✅ ✅ ✅ @@ -124,14 +132,14 @@ see what's new & breaking. ES modules support - ⛔️ + ❌ ✅ ✅ ✅ ✅ - npm module available + npm module ✅ ✅ ✅ @@ -139,25 +147,25 @@ see what's new & breaking. ✅ - TypeScript declarations available - ⚠️ + TypeScript declarations + ⚠️ ✅ ✅ ✅ ✅ - Allowed for commercial use + Allows commercial use ✅ ✅ - ⛔️ + ❌ ✅ ✅ Permissive (non-copyleft) license ✅ - ⛔️ + ✅ ✅ ✅ @@ -167,13 +175,13 @@ see what's new & breaking. ✅ ✅ ✅ - ⛔️ + ✅ - 1-year support - ⛔️ - ⛔️ + 1-year product support + ❌ + ❌ ✅ ✅ ✅ @@ -192,13 +200,13 @@ see what's new & breaking. FREE (License) $14 (License) $29 (License) - $588 (License) + $599 (License) - GET THE PRO PACKAGES 📥 +

GET THE PRO PACKAGES 📥

@@ -221,4 +229,4 @@ Made with [contributors-img](https://contrib.rocks). -Support the open-source versions of UAParser.js on [OpenCollective](https://opencollective.com/ua-parser-js) or [GitHub Sponsors](https://github.com/sponsors/faisalman). +Support the open-source editions of UAParser.js on [OpenCollective](https://opencollective.com/ua-parser-js) or [GitHub Sponsors](https://github.com/sponsors/faisalman). diff --git a/dist/ua-parser.min.js b/dist/ua-parser.min.js index 18512030c..bfc76aa6f 100644 --- a/dist/ua-parser.min.js +++ b/dist/ua-parser.min.js @@ -1,4 +1,4 @@ -/* UAParser.js v2.0.0-rc.2 +/* UAParser.js v2.0.0-rc.3 Copyright © 2012-2024 Faisal Salman AGPLv3 License */ -(function(window,undefined){"use strict";var LIBVERSION="2.0.0-rc.2",EMPTY="",UNKNOWN="?",FUNC_TYPE="function",UNDEF_TYPE="undefined",OBJ_TYPE="object",STR_TYPE="string",MAJOR="major",MODEL="model",NAME="name",TYPE="type",VENDOR="vendor",VERSION="version",ARCHITECTURE="architecture",CONSOLE="console",MOBILE="mobile",TABLET="tablet",SMARTTV="smarttv",WEARABLE="wearable",XR="xr",EMBEDDED="embedded",INAPP="inapp",USER_AGENT="user-agent",UA_MAX_LENGTH=500,BRANDS="brands",FORMFACTORS="formFactors",FULLVERLIST="fullVersionList",PLATFORM="platform",PLATFORMVER="platformVersion",BITNESS="bitness",CH_HEADER="sec-ch-ua",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,FORMFACTORS,BITNESS],UA_BROWSER="browser",UA_CPU="cpu",UA_DEVICE="device",UA_ENGINE="engine",UA_OS="os",UA_RESULT="result",AMAZON="Amazon",APPLE="Apple",ASUS="ASUS",BLACKBERRY="BlackBerry",GOOGLE="Google",HUAWEI="Huawei",LENOVO="Lenovo",LG="LG",MICROSOFT="Microsoft",MOTOROLA="Motorola",SAMSUNG="Samsung",SHARP="Sharp",SONY="Sony",XIAOMI="Xiaomi",ZEBRA="Zebra",PREFIX_MOBILE="Mobile ",SUFFIX_BROWSER=" Browser",CHROME="Chrome",CHROMECAST="Chromecast",EDGE="Edge",FIREFOX="Firefox",OPERA="Opera",FACEBOOK="Facebook",SOGOU="Sogou",WINDOWS="Windows";var isWindow=typeof window!==UNDEF_TYPE,NAVIGATOR=isWindow&&window.navigator?window.navigator:undefined,NAVIGATOR_UADATA=NAVIGATOR&&NAVIGATOR.userAgentData?NAVIGATOR.userAgentData:undefined;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]:[])}}}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={};for(var i=0;i0){for(var i in str1){if(lowerize(str1[i])==lowerize(str2))return true}return false}return isString(str1)?lowerize(str2).indexOf(lowerize(str1))!==-1:false},isExtensions=function(obj,deep){for(var prop in obj){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(",");for(var i=0;i-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 isString(str)?str.toLowerCase():str},majorize=function(version){return isString(version)?strip(/[^\d\.]/g,version).split(".")[0]:undefined},setProps=function(arr){for(var i in arr){var propName=arr[i];if(typeof propName==OBJ_TYPE&&propName.length==2){this[propName[0]]=propName[1]}else{this[propName]=undefined}}return this},strip=function(pattern,str){return isString(str)?str.replace(pattern,EMPTY):str},stripQuotes=function(str){return strip(/\\?\"/g,str)},trim=function(str,len){if(isString(str)){str=strip(/^\s\s*/,str);return typeof len===UNDEF_TYPE?str:str.substring(0,UA_MAX_LENGTH)}};var rgxMapper=function(ua,arrays){if(!ua||!arrays)return;var i=0,j,k,p,q,matches,match;while(i0){if(q.length===2){if(typeof q[1]==FUNC_TYPE){this[q[0]]=q[1].call(this,match)}else{this[q[0]]=q[1]}}else if(q.length===3){if(typeof q[1]===FUNC_TYPE&&!(q[1].exec&&q[1].test)){this[q[0]]=match?q[1].call(this,match,q[2]):undefined}else{this[q[0]]=match?match.replace(q[1],q[2]):undefined}}else if(q.length===4){this[q[0]]=match?q[3].call(this,match.replace(q[1],q[2])):undefined}}else{this[q]=match?match:undefined}}}}i+=2}},strMapper=function(str,map){for(var i in map){if(typeof map[i]===OBJ_TYPE&&map[i].length>0){for(var j=0;j2){this.set(MODEL,"iPad").set(TYPE,TABLET)}break;case UA_OS:if(!this.get(NAME)&&NAVIGATOR_UADATA&&NAVIGATOR_UADATA[PLATFORM]){this.set(NAME,NAVIGATOR_UADATA[PLATFORM])}break;case UA_RESULT:var data=this.data;var detect=function(itemType){return data[itemType].getItem().detectFeature().get()};this.set(UA_BROWSER,detect(UA_BROWSER)).set(UA_CPU,detect(UA_CPU)).set(UA_DEVICE,detect(UA_DEVICE)).set(UA_ENGINE,detect(UA_ENGINE)).set(UA_OS,detect(UA_OS))}}return this};this.parseUA=function(){if(this.itemType!=UA_RESULT){rgxMapper.call(this.data,this.ua,this.rgxMap)}if(this.itemType==UA_BROWSER){this.set(MAJOR,majorize(this.get(VERSION)))}return this};this.parseCH=function(){var uaCH=this.uaCH,rgxMap=this.rgxMap;switch(this.itemType){case UA_BROWSER:var brands=uaCH[FULLVERLIST]||uaCH[BRANDS],prevName;if(brands){for(var i in brands){var brandName=strip(/(Google|Microsoft) /,brands[i].brand||brands[i]),brandVersion=brands[i].version;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}}}break;case UA_CPU:var archName=uaCH[ARCHITECTURE];if(archName){if(archName&&uaCH[BITNESS]=="64")archName+="64";rgxMapper.call(this.data,archName+";",rgxMap)}break;case UA_DEVICE:if(uaCH[MOBILE]){this.set(TYPE,MOBILE)}if(uaCH[MODEL]){this.set(MODEL,uaCH[MODEL])}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=13?"11":"10";this.set(NAME,osName).set(VERSION,osVersion)}if(this.get(NAME)==WINDOWS&&uaCH[MODEL]=="Xbox"){this.set(NAME,"Xbox").set(VERSION,undefined)}break;case UA_RESULT:var data=this.data;var parse=function(itemType){return data[itemType].getItem().setCH(uaCH).parseCH().get()};this.set(UA_BROWSER,parse(UA_BROWSER)).set(UA_CPU,parse(UA_CPU)).set(UA_DEVICE,parse(UA_DEVICE)).set(UA_ENGINE,parse(UA_ENGINE)).set(UA_OS,parse(UA_OS))}return this};setProps.call(this,[["itemType",itemType],["ua",ua],["uaCH",uaCH],["rgxMap",rgxMap],["data",createIData(this,itemType)]]);return this}function UAParser(ua,extensions,headers){if(typeof ua===OBJ_TYPE){if(isExtensions(ua,true)){if(typeof extensions===OBJ_TYPE){headers=extensions}extensions=ua}else{headers=ua;extensions=undefined}ua=undefined}else if(typeof ua===STR_TYPE&&!isExtensions(extensions,true)){headers=extensions;extensions=undefined}if(!(this instanceof UAParser)){return new UAParser(ua,extensions,headers).getResult()}var userAgent=typeof ua===STR_TYPE?ua:NAVIGATOR&&NAVIGATOR.userAgent?NAVIGATOR.userAgent:headers&&headers[USER_AGENT]?headers[USER_AGENT]:EMPTY,httpUACH=new UACHData(headers,true),regexMap=extensions?extend(defaultRegexes,extensions):defaultRegexes,createItemFunc=function(itemType){if(itemType==UA_RESULT){return function(){return new UAItem(itemType,userAgent,regexMap,httpUACH).set("ua",userAgent).set(UA_BROWSER,this.getBrowser()).set(UA_CPU,this.getCPU()).set(UA_DEVICE,this.getDevice()).set(UA_ENGINE,this.getEngine()).set(UA_OS,this.getOS()).get()}}else{return function(){return new UAItem(itemType,userAgent,regexMap[itemType],httpUACH).parseUA().get()}}};setProps.call(this,[["getBrowser",createItemFunc(UA_BROWSER)],["getCPU",createItemFunc(UA_CPU)],["getDevice",createItemFunc(UA_DEVICE)],["getEngine",createItemFunc(UA_ENGINE)],["getOS",createItemFunc(UA_OS)],["getResult",createItemFunc(UA_RESULT)],["getUA",function(){return userAgent}],["setUA",function(ua){if(isString(ua))userAgent=ua.length>UA_MAX_LENGTH?trim(ua,UA_MAX_LENGTH):ua;return this}]]).setUA(userAgent);return this}UAParser.VERSION=LIBVERSION;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]);if(typeof exports!==UNDEF_TYPE){if(typeof module!==UNDEF_TYPE&&module.exports){exports=module.exports=UAParser}exports.UAParser=UAParser}else{if(typeof define===FUNC_TYPE&&define.amd){define(function(){return UAParser})}else if(isWindow){window.UAParser=UAParser}}var $=isWindow&&(window.jQuery||window.Zepto);if($&&!$.ua){var parser=new UAParser;$.ua=parser.getResult();$.ua.get=function(){return parser.getUA()};$.ua.set=function(ua){parser.setUA(ua);var result=parser.getResult();for(var prop in result){$.ua[prop]=result[prop]}}}})(typeof window==="object"?window:this); \ No newline at end of file +(function(window,undefined){"use strict";var LIBVERSION="2.0.0-rc.3",EMPTY="",UNKNOWN="?",FUNC_TYPE="function",UNDEF_TYPE="undefined",OBJ_TYPE="object",STR_TYPE="string",MAJOR="major",MODEL="model",NAME="name",TYPE="type",VENDOR="vendor",VERSION="version",ARCHITECTURE="architecture",CONSOLE="console",MOBILE="mobile",TABLET="tablet",SMARTTV="smarttv",WEARABLE="wearable",XR="xr",EMBEDDED="embedded",INAPP="inapp",USER_AGENT="user-agent",UA_MAX_LENGTH=500,BRANDS="brands",FORMFACTORS="formFactors",FULLVERLIST="fullVersionList",PLATFORM="platform",PLATFORMVER="platformVersion",BITNESS="bitness",CH_HEADER="sec-ch-ua",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,FORMFACTORS,BITNESS],UA_BROWSER="browser",UA_CPU="cpu",UA_DEVICE="device",UA_ENGINE="engine",UA_OS="os",UA_RESULT="result",AMAZON="Amazon",APPLE="Apple",ASUS="ASUS",BLACKBERRY="BlackBerry",GOOGLE="Google",HUAWEI="Huawei",LENOVO="Lenovo",HONOR="Honor",LG="LG",MICROSOFT="Microsoft",MOTOROLA="Motorola",SAMSUNG="Samsung",SHARP="Sharp",SONY="Sony",XIAOMI="Xiaomi",ZEBRA="Zebra",PREFIX_MOBILE="Mobile ",SUFFIX_BROWSER=" Browser",CHROME="Chrome",CHROMECAST="Chromecast",EDGE="Edge",FIREFOX="Firefox",OPERA="Opera",FACEBOOK="Facebook",SOGOU="Sogou",WINDOWS="Windows";var isWindow=typeof window!==UNDEF_TYPE,NAVIGATOR=isWindow&&window.navigator?window.navigator:undefined,NAVIGATOR_UADATA=NAVIGATOR&&NAVIGATOR.userAgentData?NAVIGATOR.userAgentData:undefined;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]:[])}}}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={};for(var i=0;i0){for(var i in str1){if(lowerize(str1[i])==lowerize(str2))return true}return false}return isString(str1)?lowerize(str2).indexOf(lowerize(str1))!==-1:false},isExtensions=function(obj,deep){for(var prop in obj){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(",");for(var i=0;i-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 isString(str)?str.toLowerCase():str},majorize=function(version){return isString(version)?strip(/[^\d\.]/g,version).split(".")[0]:undefined},setProps=function(arr){for(var i in arr){var propName=arr[i];if(typeof propName==OBJ_TYPE&&propName.length==2){this[propName[0]]=propName[1]}else{this[propName]=undefined}}return this},strip=function(pattern,str){return isString(str)?str.replace(pattern,EMPTY):str},stripQuotes=function(str){return strip(/\\?\"/g,str)},trim=function(str,len){if(isString(str)){str=strip(/^\s\s*/,str);return typeof len===UNDEF_TYPE?str:str.substring(0,UA_MAX_LENGTH)}};var rgxMapper=function(ua,arrays){if(!ua||!arrays)return;var i=0,j,k,p,q,matches,match;while(i0){if(q.length===2){if(typeof q[1]==FUNC_TYPE){this[q[0]]=q[1].call(this,match)}else{this[q[0]]=q[1]}}else if(q.length===3){if(typeof q[1]===FUNC_TYPE&&!(q[1].exec&&q[1].test)){this[q[0]]=match?q[1].call(this,match,q[2]):undefined}else{this[q[0]]=match?match.replace(q[1],q[2]):undefined}}else if(q.length===4){this[q[0]]=match?q[3].call(this,match.replace(q[1],q[2])):undefined}}else{this[q]=match?match:undefined}}}}i+=2}},strMapper=function(str,map){for(var i in map){if(typeof map[i]===OBJ_TYPE&&map[i].length>0){for(var j=0;j2){this.set(MODEL,"iPad").set(TYPE,TABLET)}break;case UA_OS:if(!this.get(NAME)&&NAVIGATOR_UADATA&&NAVIGATOR_UADATA[PLATFORM]){this.set(NAME,NAVIGATOR_UADATA[PLATFORM])}break;case UA_RESULT:var data=this.data;var detect=function(itemType){return data[itemType].getItem().detectFeature().get()};this.set(UA_BROWSER,detect(UA_BROWSER)).set(UA_CPU,detect(UA_CPU)).set(UA_DEVICE,detect(UA_DEVICE)).set(UA_ENGINE,detect(UA_ENGINE)).set(UA_OS,detect(UA_OS))}}return this};this.parseUA=function(){if(this.itemType!=UA_RESULT){rgxMapper.call(this.data,this.ua,this.rgxMap)}if(this.itemType==UA_BROWSER){this.set(MAJOR,majorize(this.get(VERSION)))}return this};this.parseCH=function(){var uaCH=this.uaCH,rgxMap=this.rgxMap;switch(this.itemType){case UA_BROWSER:var brands=uaCH[FULLVERLIST]||uaCH[BRANDS],prevName;if(brands){for(var i in brands){var brandName=strip(/(Google|Microsoft) /,brands[i].brand||brands[i]),brandVersion=brands[i].version;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}}}break;case UA_CPU:var archName=uaCH[ARCHITECTURE];if(archName){if(archName&&uaCH[BITNESS]=="64")archName+="64";rgxMapper.call(this.data,archName+";",rgxMap)}break;case UA_DEVICE:if(uaCH[MOBILE]){this.set(TYPE,MOBILE)}if(uaCH[MODEL]){this.set(MODEL,uaCH[MODEL])}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=13?"11":"10";this.set(NAME,osName).set(VERSION,osVersion)}if(this.get(NAME)==WINDOWS&&uaCH[MODEL]=="Xbox"){this.set(NAME,"Xbox").set(VERSION,undefined)}break;case UA_RESULT:var data=this.data;var parse=function(itemType){return data[itemType].getItem().setCH(uaCH).parseCH().get()};this.set(UA_BROWSER,parse(UA_BROWSER)).set(UA_CPU,parse(UA_CPU)).set(UA_DEVICE,parse(UA_DEVICE)).set(UA_ENGINE,parse(UA_ENGINE)).set(UA_OS,parse(UA_OS))}return this};setProps.call(this,[["itemType",itemType],["ua",ua],["uaCH",uaCH],["rgxMap",rgxMap],["data",createIData(this,itemType)]]);return this}function UAParser(ua,extensions,headers){if(typeof ua===OBJ_TYPE){if(isExtensions(ua,true)){if(typeof extensions===OBJ_TYPE){headers=extensions}extensions=ua}else{headers=ua;extensions=undefined}ua=undefined}else if(typeof ua===STR_TYPE&&!isExtensions(extensions,true)){headers=extensions;extensions=undefined}if(headers&&typeof headers.append===FUNC_TYPE){var kv={};headers.forEach(function(v,k){kv[k]=v});headers=kv}if(!(this instanceof UAParser)){return new UAParser(ua,extensions,headers).getResult()}var userAgent=typeof ua===STR_TYPE?ua:headers&&headers[USER_AGENT]?headers[USER_AGENT]:NAVIGATOR&&NAVIGATOR.userAgent?NAVIGATOR.userAgent:EMPTY,httpUACH=new UACHData(headers,true),regexMap=extensions?extend(defaultRegexes,extensions):defaultRegexes,createItemFunc=function(itemType){if(itemType==UA_RESULT){return function(){return new UAItem(itemType,userAgent,regexMap,httpUACH).set("ua",userAgent).set(UA_BROWSER,this.getBrowser()).set(UA_CPU,this.getCPU()).set(UA_DEVICE,this.getDevice()).set(UA_ENGINE,this.getEngine()).set(UA_OS,this.getOS()).get()}}else{return function(){return new UAItem(itemType,userAgent,regexMap[itemType],httpUACH).parseUA().get()}}};setProps.call(this,[["getBrowser",createItemFunc(UA_BROWSER)],["getCPU",createItemFunc(UA_CPU)],["getDevice",createItemFunc(UA_DEVICE)],["getEngine",createItemFunc(UA_ENGINE)],["getOS",createItemFunc(UA_OS)],["getResult",createItemFunc(UA_RESULT)],["getUA",function(){return userAgent}],["setUA",function(ua){if(isString(ua))userAgent=ua.length>UA_MAX_LENGTH?trim(ua,UA_MAX_LENGTH):ua;return this}]]).setUA(userAgent);return this}UAParser.VERSION=LIBVERSION;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]);if(typeof exports!==UNDEF_TYPE){if(typeof module!==UNDEF_TYPE&&module.exports){exports=module.exports=UAParser}exports.UAParser=UAParser}else{if(typeof define===FUNC_TYPE&&define.amd){define(function(){return UAParser})}else if(isWindow){window.UAParser=UAParser}}var $=isWindow&&(window.jQuery||window.Zepto);if($&&!$.ua){var parser=new UAParser;$.ua=parser.getResult();$.ua.get=function(){return parser.getUA()};$.ua.set=function(ua){parser.setUA(ua);var result=parser.getResult();for(var prop in result){$.ua[prop]=result[prop]}}}})(typeof window==="object"?window:this); \ No newline at end of file diff --git a/dist/ua-parser.pack.js b/dist/ua-parser.pack.js index 0f145e7e3..55b1df175 100644 --- a/dist/ua-parser.pack.js +++ b/dist/ua-parser.pack.js @@ -1,4 +1,4 @@ -/* UAParser.js v2.0.0-rc.2 +/* UAParser.js v2.0.0-rc.3 Copyright © 2012-2024 Faisal Salman AGPLv3 License */ -!function(i,c){"use strict";function e(i){for(var e={},t=0;tT?Ti(i,T):i),this}]]).setUA(o),this}Ui.VERSION="2.0.0-rc.2",Ui.BROWSER=e([m,v,h,f]),Ui.CPU=e([k]),Ui.DEVICE=e([p,g,f,x,y,t,r,o,d]),Ui.ENGINE=Ui.OS=e([m,v]),typeof exports!==b?(typeof module!==b&&module.exports&&(exports=module.exports=Ui),exports.UAParser=Ui):typeof define===l&&define.amd?define(function(){return Ui}):ui&&(i.UAParser=Ui);var ji,Mi=ui&&(i.jQuery||i.Zepto);Mi&&!Mi.ua&&(ji=new Ui,Mi.ua=ji.getResult(),Mi.ua.get=function(){return ji.getUA()},Mi.ua.set=function(i){ji.setUA(i);var e,t=ji.getResult();for(e in t)Mi.ua[e]=t[e]})}("object"==typeof window?window:this); \ No newline at end of file +!function(i,d){"use strict";function e(i){for(var e={},t=0;tC?Ci(i,C):i),this}]]).setUA(r),this}Ui.VERSION="2.0.0-rc.3",Ui.BROWSER=e([m,v,p,f]),Ui.CPU=e([k]),Ui.DEVICE=e([h,g,f,x,y,t,r,o,s]),Ui.ENGINE=Ui.OS=e([m,v]),typeof exports!==b?(typeof module!==b&&module.exports&&(exports=module.exports=Ui),exports.UAParser=Ui):typeof define===u&&define.amd?define(function(){return Ui}):li&&(i.UAParser=Ui);var ji,Ei=li&&(i.jQuery||i.Zepto);Ei&&!Ei.ua&&(ji=new Ui,Ei.ua=ji.getResult(),Ei.ua.get=function(){return ji.getUA()},Ei.ua.set=function(i){ji.setUA(i);var e,t=ji.getResult();for(e in t)Ei.ua[e]=t[e]})}("object"==typeof window?window:this); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 8d8b2bc24..42acf6be8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ua-parser-js", - "version": "2.0.0-rc.2", + "version": "2.0.0-rc.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "ua-parser-js", - "version": "2.0.0-rc.2", + "version": "2.0.0-rc.3", "funding": [ { "type": "opencollective", @@ -23,9 +23,9 @@ ], "license": "AGPL-3.0-or-later", "dependencies": { - "detect-europe-js": "^0.1.1", - "is-standalone-pwa": "^0.1.0", - "ua-is-frozen": "^0.1.1" + "detect-europe-js": "^0.1.2", + "is-standalone-pwa": "^0.1.1", + "ua-is-frozen": "^0.1.2" }, "bin": { "ua-parser-js": "script/cli.js" @@ -1670,9 +1670,9 @@ "dev": true }, "node_modules/detect-europe-js": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/detect-europe-js/-/detect-europe-js-0.1.1.tgz", - "integrity": "sha512-+bUXDf+tI3L4dcEuRdAFa44Amx9aEaJzoZssx7Xis4H1bXWc5fAcOP850BOj0wJPRzOdovOuOVEvrg6T+GflZA==", + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/detect-europe-js/-/detect-europe-js-0.1.2.tgz", + "integrity": "sha512-lgdERlL3u0aUdHocoouzT10d9I89VVhk0qNRmll7mXdGfJT1/wqZ2ZLA4oJAjeACPY5fT1wsbq2AT+GkuInsow==", "funding": [ { "type": "github", @@ -2612,9 +2612,9 @@ } }, "node_modules/is-standalone-pwa": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-standalone-pwa/-/is-standalone-pwa-0.1.0.tgz", - "integrity": "sha512-n5SQqXd0/JEkrKYEB7ZUndwuS7NKskZvk6rZZt6kTE1jiPxtPfPvVhXkfteIKpUfcEP07qsja/Wjz9NDjiZ5gg==", + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-standalone-pwa/-/is-standalone-pwa-0.1.1.tgz", + "integrity": "sha512-9Cbovsa52vNQCjdXOzeQq5CnCbAcRk05aU62K20WO372NrTv0NxibLFCK6lQ4/iZEFdEA3p3t2VNOn8AJ53F5g==", "funding": [ { "type": "github", @@ -4619,9 +4619,9 @@ } }, "node_modules/ua-is-frozen": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ua-is-frozen/-/ua-is-frozen-0.1.1.tgz", - "integrity": "sha512-TxhyfblPzcDJXRXu/j+73OI6s1jG6PUZBF/8hjTHoAsjZYKl9IhZzLQlnZHFLe5U2mvL1lMOOmcy647KpUq25A==", + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ua-is-frozen/-/ua-is-frozen-0.1.2.tgz", + "integrity": "sha512-RwKDW2p3iyWn4UbaxpP2+VxwqXh0jpvdxsYpZ5j/MLLiQOfbsV5shpgQiw93+KMYQPcteeMQ289MaAFzs3G9pw==", "funding": [ { "type": "github", diff --git a/package.json b/package.json index 1beaf501a..73f74c852 100755 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "title": "UAParser.js", "name": "ua-parser-js", - "version": "2.0.0-rc.2", + "version": "2.0.0-rc.3", "author": "Faisal Salman (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": [ @@ -211,9 +211,9 @@ "test:playwright": "playwright test" }, "dependencies": { - "detect-europe-js": "^0.1.1", - "is-standalone-pwa": "^0.1.0", - "ua-is-frozen": "^0.1.1" + "detect-europe-js": "^0.1.2", + "is-standalone-pwa": "^0.1.1", + "ua-is-frozen": "^0.1.2" }, "devDependencies": { "@babel/parser": "7.15.8", diff --git a/src/enums/ua-parser-enums.js b/src/enums/ua-parser-enums.js index 74218fc14..ff0156d90 100644 --- a/src/enums/ua-parser-enums.js +++ b/src/enums/ua-parser-enums.js @@ -1,5 +1,5 @@ /////////////////////////////////////////////// -/* Enums for UAParser.js v2.0.0-rc.2 +/* Enums for UAParser.js v2.0.0-rc.3 https://github.com/faisalman/ua-parser-js Author: Faisal Salman AGPLv3 License */ diff --git a/src/enums/ua-parser-enums.mjs b/src/enums/ua-parser-enums.mjs index 6af7ef755..dff46cb72 100644 --- a/src/enums/ua-parser-enums.mjs +++ b/src/enums/ua-parser-enums.mjs @@ -3,7 +3,7 @@ // Source: /src/enums/ua-parser-enums.js /////////////////////////////////////////////// -/* Enums for UAParser.js v2.0.0-rc.2 +/* Enums for UAParser.js v2.0.0-rc.3 https://github.com/faisalman/ua-parser-js Author: Faisal Salman AGPLv3 License */ @@ -59,6 +59,7 @@ const Browser = Object.freeze({ GOOGLE_SEARCH: 'GSA', HELIO: 'Helio', HEYTAP: 'HeyTap', + HONOR: 'Honor', HUAWEI: 'Huawei Browser', ICAB: 'iCab', ICE: 'ICE Browser', @@ -162,7 +163,7 @@ const BrowserType = Object.freeze({ FETCHER: 'fetcher', INAPP: 'inapp', MEDIAPLAYER: 'mediaplayer', - MODULE: 'module' + LIBRARY: 'library' }); const CPU = Object.freeze({ @@ -198,6 +199,7 @@ const Device = Object.freeze({ const Vendor = Object.freeze({ ACER: 'Acer', + ADVAN: 'Advan', ALCATEL: 'Alcatel', APPLE: 'Apple', AMAZON: 'Amazon', @@ -206,7 +208,9 @@ const Vendor = Object.freeze({ ATT: 'AT&T', BENQ: 'BenQ', BLACKBERRY: 'BlackBerry', + CAT: 'Cat', DELL: 'Dell', + ENERGIZER: 'Energizer', ESSENTIAL: 'Essential', FACEBOOK: 'Facebook', FAIRPHONE: 'Fairphone', @@ -216,6 +220,7 @@ const Vendor = Object.freeze({ HP: 'HP', HTC: 'HTC', HUAWEI: 'Huawei', + IMO: 'IMO', INFINIX: 'Infinix', ITEL: 'itel', JOLLA: 'Jolla', @@ -223,6 +228,7 @@ const Vendor = Object.freeze({ LENOVO: 'Lenovo', LG: 'LG', MEIZU: 'Meizu', + MICROMAX: 'Micromax', MICROSOFT: 'Microsoft', MOTOROLA: 'Motorola', NEXIAN: 'Nexian', @@ -244,6 +250,7 @@ const Vendor = Object.freeze({ SAMSUNG: 'Samsung', SHARP: 'Sharp', SIEMENS: 'Siemens', + SMARTFREN: 'Smartfren', SONY: 'Sony', SPRINT: 'Sprint', TCL: 'TCL', @@ -277,6 +284,7 @@ const Engine = Object.freeze({ NETFRONT: 'NetFront', NETSURF: 'NetSurf', PRESTO: 'Presto', + SERVO: 'Servo', TASMAN: 'Tasman', TRIDENT: 'Trident', W3M: 'w3m', diff --git a/src/extensions/ua-parser-extensions.d.ts b/src/extensions/ua-parser-extensions.d.ts index 013a3d75b..b4da5499b 100644 --- a/src/extensions/ua-parser-extensions.d.ts +++ b/src/extensions/ua-parser-extensions.d.ts @@ -1,4 +1,4 @@ -// Type definitions for Helpers submodule of UAParser.js v2.0.0-rc.2 +// Type definitions for Helpers submodule of UAParser.js v2.0.0-rc.3 // Project: https://github.com/faisalman/ua-parser-js // Definitions by: Faisal Salman diff --git a/src/extensions/ua-parser-extensions.js b/src/extensions/ua-parser-extensions.js index 936c90bd2..a6774ad8b 100644 --- a/src/extensions/ua-parser-extensions.js +++ b/src/extensions/ua-parser-extensions.js @@ -1,5 +1,5 @@ /////////////////////////////////////////////// -/* Extensions for UAParser.js v2.0.0-rc.2 +/* Extensions for UAParser.js v2.0.0-rc.3 https://github.com/faisalman/ua-parser-js Author: Faisal Salman AGPLv3 License */ diff --git a/src/extensions/ua-parser-extensions.mjs b/src/extensions/ua-parser-extensions.mjs index 21c2dcb9a..5fc374d5d 100644 --- a/src/extensions/ua-parser-extensions.mjs +++ b/src/extensions/ua-parser-extensions.mjs @@ -3,7 +3,7 @@ // Source: /src/extensions/ua-parser-extensions.js /////////////////////////////////////////////// -/* Extensions for UAParser.js v2.0.0-rc.2 +/* Extensions for UAParser.js v2.0.0-rc.3 https://github.com/faisalman/ua-parser-js Author: Faisal Salman AGPLv3 License */ @@ -24,7 +24,7 @@ const EMAIL = 'email'; const FETCHER = 'fetcher'; const INAPP = 'inapp'; const MEDIAPLAYER = 'mediaplayer'; -const MODULE = 'module'; +const LIBRARY = 'library'; ////////////////////// // COMMAND LINE APPS @@ -48,26 +48,36 @@ const Crawlers = Object.freeze({ // Amazonbot - https://developer.amazon.com/amazonbot // Applebot - http://apple.com/go/applebot // Bingbot - http://www.bing.com/bingbot.htm + // CCBot - https://commoncrawl.org/faq // Dotbot - https://moz.com/help/moz-procedures/crawlers/dotbot // DuckDuckBot - http://duckduckgo.com/duckduckbot.html // FacebookBot - https://developers.facebook.com/docs/sharing/bot/ // GPTBot - https://platform.openai.com/docs/gptbot // MJ12bot - https://mj12bot.com/ - // OpenAI Search - https://platform.openai.com/docs/bots + // MojeekBot - https://www.mojeek.com/bot.html + // OpenAI's SearchGPT - https://platform.openai.com/docs/bots + // PerplexityBot - https://perplexity.ai/perplexitybot // SemrushBot - http://www.semrush.com/bot.html - /((?:ahrefs|amazon|apple|bing|dot|duckduck|facebook|gpt|mj12|oai-search|semrush)bot)\/([\w\.]+)/i, + /((?:ahrefs|amazon|apple|bing|cc|dot|duckduck|exa|facebook|gpt|mj12|mojeek|oai-search|perplexity|semrush)bot)\/([\w\.]+)/i, // Baiduspider https://help.baidu.com/question?prod_id=99&class=0&id=3001 /(baiduspider)[-imagevdonsfcpr]{0,6}\/([\w\.]+)/i, - // ClaudeBot + // ClaudeBot (Anthropic) /(claude(?:bot|-web))\/([\w\.]+)/i, // Coc Coc Bot - https://help.coccoc.com/en/search-engine /(coccocbot-(?:image|web))\/([\w\.]+)/i, + // Facebook / Meta + // https://developers.facebook.com/docs/sharing/webmasters/web-crawlers + /(facebook(?:externalhit|catalog)|meta-externalagent)\/([\w\.]+)/i, + // Googlebot - http://www.google.com/bot.html - /(google(?:bot|other)(?:-image|-video|-news|-extended)?|(?:storebot-)?google(?:-inspectiontool)?)\/?([\w\.]*)/i, + /(google(?:bot|other|-inspectiontool)(?:-image|-video|-news)?|storebot-google)\/?([\w\.]*)/i, + + // Internet Archive (archive.org) + /(ia_archiver|archive\.org_bot)\/?([\w\.]*)/i, // Sogou Spider /(sogou (?:pic|head|web|orion|news) spider)\/([\w\.]+)/i, @@ -76,14 +86,29 @@ const Crawlers = Object.freeze({ /(y!?j-(?:asr|br[uw]|dscv|mmp|vsidx|wsc))\/([\w\.]+)/i, // 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 + /(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, + + // Yeti (Naver) + /(yeti)\/([\w\.]+)/i, + + // YisouSpider + /(yisouspider)\/?([\w\.]*)/i ], [NAME, VERSION, [TYPE, CRAWLER]], - // Bytespider - // Yahoo! Slurp - http://help.yahoo.com/help/us/ysearch/slurp - [/((?:bytespider|(?=yahoo! )slurp))/i], + [ + // Google Bots + /((?:adsbot|apis|mediapartners)-google(?:-mobile)?|google-?(?:other|cloudvertexbot|extended|safety))/i, + + // Bytespider + // DataForSeoBot - https://dataforseo.com/dataforseo-bot + // Huawei AspiegelBot / PetalBot https://aspiegel.com/petalbot + // Qihoo 360Spider + // TurnitinBot - https://www.turnitin.com/robot/crawlerinfo.html + // Yahoo! Slurp - http://help.yahoo.com/help/us/ysearch/slurp + /(360spider-?(?:image|video)?|bytespider|(?:aspiegel|dataforseo|petal|turnitin)bot|(?=yahoo! )slurp)/i + ], [NAME, [TYPE, CRAWLER]] ] }); @@ -174,8 +199,8 @@ const ExtraDevices = Object.freeze({ const Emails = Object.freeze({ browser : [ - // Microsoft Outlook / Thunderbird - [/(microsoft outlook|thunderbird)[\s\/]([\w\.]+)/i], [NAME, VERSION, [TYPE, EMAIL]] + // Evolution / Kontact/KMail / [Microsoft/Mac] Outlook / Thunderbird + [/(evolution|kmail2?|kontact|(?:microsoft |mac)outlook|thunderbird)[\s\/]([\w\.]+)/i], [NAME, VERSION, [TYPE, EMAIL]] ] }); @@ -188,8 +213,15 @@ const Fetchers = Object.freeze({ [ // AhrefsSiteAudit - https://ahrefs.com/robot/site-audit // ChatGPT-User - https://platform.openai.com/docs/plugins/bot + // DuckAssistBot - https://duckduckgo.com/duckassistbot/ // BingPreview / Mastodon / Pinterestbot / Redditbot / Rogerbot / Telegrambot / Twitterbot / UptimeRobot - /(ahrefssiteaudit|bingpreview|chatgpt-user|mastodon|(?:discord|linkedin|pinterest|reddit|roger|telegram|twitter|uptimero)bot)\/([\w\.]+)/i, + /(ahrefssiteaudit|bingpreview|chatgpt-user|mastodon|(?:discord|duckassist|linkedin|pinterest|reddit|roger|telegram|twitter|uptimero)bot)\/([\w\.]+)/i, + + // Google Site Verifier + /(google-site-verification)\/([\w\.]+)/i, + + // Meta + /(meta-externalfetcher)\/([\w\.]+)/i, // Slackbot - https://api.slack.com/robots /(slack(?:bot)?(?:-imgproxy|-linkexpanding)?) ([\w\.]+)/i, @@ -207,7 +239,7 @@ const Fetchers = Object.freeze({ [NAME, VERSION, [TYPE, FETCHER]], // Google Bots / Snapchat - [/(feedfetcher-google|google-read-aloud|(?=bot; )snapchat)/i], + [/(feedfetcher-google|google(?:-read-aloud|producer)|(?=bot; )snapchat)/i], [NAME, [TYPE, FETCHER]], ] }); @@ -256,8 +288,8 @@ const MediaPlayers = Object.freeze({ /(flrp)\/([\w\.-]+)/i // Flip Player ], [[NAME, 'Flip Player'], VERSION, [TYPE, MEDIAPLAYER]], [ - /(fstream|nativehost|queryseekspider|ia-archiver|facebookexternalhit)/i - // FStream/NativeHost/QuerySeekSpider/IA Archiver/facebookexternalhit + /(fstream|nativehost|queryseekspider)/i + // FStream/NativeHost/QuerySeekSpider ], [NAME, [TYPE, MEDIAPLAYER]], [ /(gstreamer) souphttpsrc.+libsoup\/([\w\.-]+)/i @@ -336,14 +368,14 @@ const MediaPlayers = Object.freeze({ ] }); -//////////////////////// -// MODULES / LIBRARIES -/////////////////////// +///////////// +// LIBRARIES +////////////// -const Modules = Object.freeze({ +const Libraries = Object.freeze({ browser : [ // Axios/jsdom/Scrapy - [/\b(axios|jsdom|scrapy)\/([\w\.]+)/i], [NAME, VERSION, [TYPE, MODULE]] + [/\b(axios|jsdom|scrapy)\/([\w\.]+)/i], [NAME, VERSION, [TYPE, LIBRARY]] ] }); @@ -356,7 +388,7 @@ const Bots = Object.freeze({ ...CLIs.browser, ...Crawlers.browser, ...Fetchers.browser, - ...Modules.browser + ...Libraries.browser ] }); @@ -368,6 +400,6 @@ export { Emails, Fetchers, InApps, - MediaPlayers, - Modules + Libraries, + MediaPlayers }; \ No newline at end of file diff --git a/src/helpers/ua-parser-helpers.d.ts b/src/helpers/ua-parser-helpers.d.ts index 0f46125a4..10398d60d 100644 --- a/src/helpers/ua-parser-helpers.d.ts +++ b/src/helpers/ua-parser-helpers.d.ts @@ -1,4 +1,4 @@ -// Type definitions for Helpers submodule of UAParser.js v2.0.0-rc.2 +// Type definitions for Helpers submodule of UAParser.js v2.0.0-rc.3 // Project: https://github.com/faisalman/ua-parser-js // Definitions by: Faisal Salman diff --git a/src/helpers/ua-parser-helpers.js b/src/helpers/ua-parser-helpers.js index cd63a79ff..abd580379 100644 --- a/src/helpers/ua-parser-helpers.js +++ b/src/helpers/ua-parser-helpers.js @@ -1,5 +1,5 @@ /////////////////////////////////////////////// -/* Helpers for UAParser.js v2.0.0-rc.2 +/* Helpers for UAParser.js v2.0.0-rc.3 https://github.com/faisalman/ua-parser-js Author: Faisal Salman AGPLv3 License */ diff --git a/src/helpers/ua-parser-helpers.mjs b/src/helpers/ua-parser-helpers.mjs index 7c6fd0eff..5e28bf6bb 100644 --- a/src/helpers/ua-parser-helpers.mjs +++ b/src/helpers/ua-parser-helpers.mjs @@ -3,7 +3,7 @@ // Source: /src/helpers/ua-parser-helpers.js /////////////////////////////////////////////// -/* Helpers for UAParser.js v2.0.0-rc.2 +/* Helpers for UAParser.js v2.0.0-rc.3 https://github.com/faisalman/ua-parser-js Author: Faisal Salman AGPLv3 License */ @@ -19,27 +19,29 @@ import { isStandalonePWA } from 'is-standalone-pwa'; const getDeviceVendor = (model) => UAParser(`Mozilla/5.0 (Linux; Android 10; ${model}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.0.0 Safari/537.36`).device.vendor; -const isAppleSilicon = (res) => { +const isAppleSilicon = (res, useFeatureDetection) => { if (res.os.is(OS.MACOS)) { if (res.cpu.is(CPU.ARM)) { return true; } - try { - const canvas = document.createElement('canvas'); - const webgl = canvas.getContext('webgl2') || canvas.getContext('webgl') || canvas.getContext('experimental-webgl'); - const debug = webgl.getExtension('WEBGL_debug_renderer_info'); - const renderer = webgl.getParameter(debug.UNMASKED_RENDERER_WEBGL); - if (renderer.match(/apple m\d/i)) { - return true; + if (useFeatureDetection) { + try { + const canvas = document.createElement('canvas'); + const webgl = canvas.getContext('webgl2') || canvas.getContext('webgl') || canvas.getContext('experimental-webgl'); + const debug = webgl.getExtension('WEBGL_debug_renderer_info'); + const renderer = webgl.getParameter(debug.UNMASKED_RENDERER_WEBGL); + if (renderer.match(/apple m\d/i)) { + return true; + } + } catch { + return false; } - } catch { - return false; } } return false; } -const isBot = (res) => ['cli', 'crawler', 'fetcher', 'module'].includes(res.browser.type); +const isBot = (res) => ['cli', 'crawler', 'fetcher', 'library'].includes(res.browser.type); const isChromeFamily = (res) => res.engine.is(Engine.BLINK); diff --git a/src/main/ua-parser.d.ts b/src/main/ua-parser.d.ts index cbf583717..4e64bf44c 100644 --- a/src/main/ua-parser.d.ts +++ b/src/main/ua-parser.d.ts @@ -1,4 +1,4 @@ -// Type definitions for UAParser.js v2.0.0-rc.2 +// Type definitions for UAParser.js v2.0.0-rc.3 // Project: https://github.com/faisalman/ua-parser-js // Definitions by: Faisal Salman @@ -19,7 +19,7 @@ declare namespace UAParser { } interface ICPU extends IData { - architecture?: 'ia32' | 'ia64' | 'amd64' | 'arm' | 'arm64' | 'armhf' | 'avr' | 'irix' | 'irix64' | 'mips' | 'mips64' | '68k' | 'ppc' | 'sparc' | 'sparc64'; + architecture?: 'ia32' | 'ia64' | 'amd64' | 'arm' | 'arm64' | 'armhf' | 'avr' | 'avr32' | 'irix' | 'irix64' | 'mips' | 'mips64' | '68k' | 'pa-risc' | 'ppc' | 'sparc' | 'sparc64'; } interface IDevice extends IData { @@ -29,7 +29,7 @@ declare namespace UAParser { } interface IEngine extends IData { - name?: 'Amaya' | 'Blink' | 'EdgeHTML' | 'Flow' | 'Gecko' | 'Goanna' | 'iCab' | 'KHTML' | 'LibWeb' | 'Links' | 'Lynx' | 'NetFront' | 'NetSurf' | 'Presto' | 'Tasman' | 'Trident' | 'w3m' | 'WebKit'; + name?: 'Amaya' | 'ArkWeb' | 'Blink' | 'EdgeHTML' | 'Flow' | 'Gecko' | 'Goanna' | 'iCab' | 'KHTML' | 'LibWeb' | 'Links' | 'Lynx' | 'NetFront' | 'NetSurf' | 'Presto' | 'Servo' | 'Tasman' | 'Trident' | 'w3m' | 'WebKit'; version?: string; } diff --git a/src/main/ua-parser.js b/src/main/ua-parser.js index 3615efd46..c1f07cb6c 100755 --- a/src/main/ua-parser.js +++ b/src/main/ua-parser.js @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////////// -/* UAParser.js v2.0.0-rc.2 +/* UAParser.js v2.0.0-rc.3 Copyright © 2012-2024 Faisal Salman AGPLv3 License *//* Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data. @@ -19,7 +19,7 @@ // Constants ///////////// - var LIBVERSION = '2.0.0-rc.2', + var LIBVERSION = '2.0.0-rc.3', EMPTY = '', UNKNOWN = '?', FUNC_TYPE = 'function', diff --git a/src/main/ua-parser.mjs b/src/main/ua-parser.mjs index 130f21649..80e1770ce 100644 --- a/src/main/ua-parser.mjs +++ b/src/main/ua-parser.mjs @@ -3,7 +3,7 @@ // Source: /src/main/ua-parser.js ///////////////////////////////////////////////////////////////////////////////// -/* UAParser.js v2.0.0-rc.2 +/* UAParser.js v2.0.0-rc.3 Copyright © 2012-2024 Faisal Salman AGPLv3 License *//* Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data. @@ -21,7 +21,7 @@ // Constants ///////////// - var LIBVERSION = '2.0.0-rc.2', + var LIBVERSION = '2.0.0-rc.3', EMPTY = '', UNKNOWN = '?', FUNC_TYPE = 'function', @@ -74,6 +74,7 @@ GOOGLE = 'Google', HUAWEI = 'Huawei', LENOVO = 'Lenovo', + HONOR = 'Honor', LG = 'LG', MICROSOFT = 'Microsoft', MOTOROLA = 'Motorola', @@ -529,10 +530,14 @@ /\b(sh-?[altvz]?\d\d[a-ekm]?)/i ], [MODEL, [VENDOR, SHARP], [TYPE, MOBILE]], [ + // Honor + /(?:honor)([-\w ]+)[;\)]/i + ], [MODEL, [VENDOR, HONOR], [TYPE, MOBILE]], [ + // Huawei /\b((?:ag[rs][23]?|bah2?|sht?|btv)-a?[lw]\d{2})\b(?!.+d\/s)/i ], [MODEL, [VENDOR, HUAWEI], [TYPE, TABLET]], [ - /(?:huawei|honor)([-\w ]+)[;\)]/i, + /(?:huawei)([-\w ]+)[;\)]/i, /\b(nexus 6p|\w{2,4}e?-[atu]?[ln][\dx][012359c][adn]?)\b(?!.+d\/s)/i ], [MODEL, [VENDOR, HUAWEI], [TYPE, MOBILE]], [ @@ -597,7 +602,7 @@ ], [MODEL, [VENDOR, GOOGLE], [TYPE, MOBILE]], [ // Sony - /droid.+ (a?\d[0-2]{2}so|[c-g]\d{4}|so[-gl]\w+|xq-a\w[4-7][12])(?= bui|\).+chrome\/(?![1-6]{0,1}\d\.))/i + /droid.+; (a?\d[0-2]{2}so|[c-g]\d{4}|so[-gl]\w+|xq-a\w[4-7][12])(?= bui|\).+chrome\/(?![1-6]{0,1}\d\.))/i ], [MODEL, [VENDOR, SONY], [TYPE, MOBILE]], [ /sony tablet [ps]/i, /\b(?:sony)?sgp\w+(?: bui|\))/i @@ -663,13 +668,28 @@ /; ((?:power )?armor(?:[\w ]{0,8}))(?: bui|\))/i ], [MODEL, [VENDOR, 'Ulefone'], [TYPE, MOBILE]], [ + // Energizer + /; (energy ?\w+)(?: bui|\))/i, + /; energizer ([\w ]+)(?: bui|\))/i + ], [MODEL, [VENDOR, 'Energizer'], [TYPE, MOBILE]], [ + + // Cat + /; cat (b35);/i, + /; (b15q?|s22 flip|s48c|s62 pro)(?: bui|\))/i + ], [MODEL, [VENDOR, 'Cat'], [TYPE, MOBILE]], [ + + // Smartfren + /((?:new )?andromax[\w- ]+)(?: bui|\))/i + ], [MODEL, [VENDOR, 'Smartfren'], [TYPE, MOBILE]], [ + // Nothing /droid.+; (a(?:015|06[35]|142p?))/i ], [MODEL, [VENDOR, 'Nothing'], [TYPE, MOBILE]], [ // MIXED - /(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus|dell|meizu|motorola|polytron|infinix|tecno)[-_ ]?([-\w]*)/i, - // BlackBerry/BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron + /(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus|dell|meizu|motorola|polytron|infinix|tecno|micromax|advan)[-_ ]?([-\w]*)/i, + // BlackBerry/BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron/Infinix/Tecno/Micromax/Advan + /; (imo) ((?!tab)[\w ]+?)(?: bui|\))/i, // IMO /(hp) ([\w ]+\w)/i, // HP iPAQ /(asus)-?(\w+)/i, // Asus /(microsoft); (lumia[\w ]+)/i, // Microsoft Lumia @@ -678,6 +698,7 @@ /(oppo) ?([\w ]+) bui/i // OPPO ], [VENDOR, MODEL, [TYPE, MOBILE]], [ + /(imo) (tab \w+)/i, // IMO /(kobo)\s(ereader|touch)/i, // Kobo /(archos) (gamepad2?)/i, // Archos /(hp).+(touchpad(?!.+tablet)|tablet)/i, // HP TouchPad @@ -811,7 +832,7 @@ ], [VERSION, [NAME, 'Blink']], [ /(presto)\/([\w\.]+)/i, // Presto - /(webkit|trident|netfront|netsurf|amaya|lynx|w3m|goanna)\/([\w\.]+)/i, // WebKit/Trident/NetFront/NetSurf/Amaya/Lynx/w3m/Goanna + /(webkit|trident|netfront|netsurf|amaya|lynx|w3m|goanna|servo)\/([\w\.]+)/i, // WebKit/Trident/NetFront/NetSurf/Amaya/Lynx/w3m/Goanna/Servo /ekioh(flow)\/([\w\.]+)/i, // Flow /(khtml|tasman|links)[\/ ]\(?([\w\.]+)/i, // KHTML/Tasman/Links /(icab)[\/ ]([23]\.[\d\.]+)/i, // iCab @@ -1238,14 +1259,21 @@ headers = extensions; // case UAParser(ua, headers) extensions = undefined; } + + // Convert Headers object into a plain object + if (headers && typeof headers.append === FUNC_TYPE) { + var kv = {}; + headers.forEach(function (v, k) { kv[k] = v; }); + headers = kv; + } if (!(this instanceof UAParser)) { return new UAParser(ua, extensions, headers).getResult(); } var userAgent = typeof ua === STR_TYPE ? ua : // Passed user-agent string - ((NAVIGATOR && NAVIGATOR.userAgent) ? NAVIGATOR.userAgent : // navigator.userAgent (headers && headers[USER_AGENT] ? headers[USER_AGENT] : // User-Agent from passed headers + ((NAVIGATOR && NAVIGATOR.userAgent) ? NAVIGATOR.userAgent : // navigator.userAgent EMPTY)), // empty string httpUACH = new UACHData(headers, true), From ba980c8250cdccb57b1181086e6b7a2300fe247d Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Thu, 14 Nov 2024 11:54:11 +0700 Subject: [PATCH 64/64] Refine changelog details regarding v1 to v2 migration --- CHANGELOG.md | 88 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 60 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a16881fe..0e1966dcf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,36 +1,68 @@ # UAParser.js Changelog -# Version 2.0 ## Migrating from v1 to v2 -- What's breaking: - - Licensed under AGPLv3 (open-source) or PRO License (commercial) - - Browser detection on mobile device: `"Chrome" => "Mobile Chrome"`, `"Firefox" => "Mobile Firefox"` - - OS detection: `"Mac OS" => "macOS"`, `"Chromium OS" => "Chrome OS"` -- What's new: - - New device type: `xr`, to identify AR/VR devices - - New browser property: `browser.type`, to identify the type of the browser: `crawler`, `cli`, `email`, `fetcher`, `inapp`, `library`, `mediaplayer` - - New methods in result object (all of `get*()` return value): - - Enhance detection using client hints: `withClientHints()` - - Enhance detection using feature check: `withFeatureCheck()` - - Utility for easy comparison: `is()` - - Utility to print full-name: `toString()` - - Parse user-agent directly from command line using `npx ua-parser-js "[User-Agent]"` - - Extensions can be passed as a list to `UAParser()` - - Support for ES module & TypeScript `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'`: - - `getDeviceVendor()`: guess for a device vendor based on its model name - - `isAppleSilicon()`: check if the device has Apple Silicon Mac device properties - - `isBot()`: check if the browser is identified as a bot - - `isChromeFamily()`: check if the browser is Chrome-based (has Blink engine, i.e: New Opera, New Edge, Vivaldi, Brave, Arc, etc.) - - `isElectron()`: check if current window is running inside Electron - - `isFromEU()`: check if current window is from an EU (European Union) country - - `isFrozenUA()`: check if a user-agent string match with the reduced/frozen user-agent pattern - - `isStandalonePWA()`: check if current window is a standalone PWA +### What's Breaking: ---- +- **Licensing Changes:** + - UAParser.js is now licensed under AGPLv3 for open-source use, with PRO Licenses available for commercial/proprietary use + +- **Browser Detection on Mobile Devices:** + - `"Chrome"` => `"Mobile Chrome"` + - `"Firefox"` => `"Mobile Firefox"` + +- **OS Detection:** + - `"Mac OS"` => `"macOS"` + - `"Chromium OS"` => `"Chrome OS"` + +### What's New: + +- **Support for ES Modules & TypeScript:** + - Import directly as an ES module with TypeScript support: `import { UAParser } from 'ua-parser-js'` + +- **Support for Custom/Predefined Extensions:** + - Pass custom regexes or predefined extensions as a list to `UAParser()` + +- **Support for CLI Parsing:** + - Parse a user-agent directly from the command line using `npx ua-parser-js "[User-Agent]"` + +- **Enhanced Detection with Client Hints:** + - `withClientHints()`: Improves detection accuracy by leveraging client hints + +- **Enhanced Detection with Feature Detection:** + - `withFeatureCheck()`: Refines detection results using feature detection + +- **Simple Comparison for Detection Results:** + - `is()`: Enables easy comparison checks against the detection result + +- **Detailed Result Output:** + - `toString()`: Returns the detection result in form of a full-name string + +- **New Device Type:** + - Added `xr` to identify AR/VR devices + +- **New Browser Property:** + - Added `browser.type` to identify additional browser types: + - `crawler`, `cli`, `email`, `fetcher`, `inapp`, `library`, `mediaplayer` + +- **New Submodules:** + - **`'ua-parser-js/enums'`**: Provides constants for these specific properties: + - `browser.name`, `browser.type`, `cpu.architecture`, `device.type`, `device.vendor`, `engine.name`, `os.name` + + - **`'ua-parser-js/extensions'`**: Predefined extensions for various use cases: + - `Bots`, `Crawlers`, `CLIs`, `Emails`, `ExtraDevices`, `Fetchers`, `InApps`, `Libraries`, `Mediaplayers` + + - **`'ua-parser-js/helpers'`**: Provides utility methods to extend detection functionality: + - `getDeviceVendor()`: Guesses the device vendor based on its model name + - `isAppleSilicon()`: Detects Apple Silicon device properties + - `isBot()`: Checks if the browser is a bot + - `isChromeFamily()`: Checks if the browser is Chrome-based (uses Blink engine) — e.g., New Opera, New Edge, Vivaldi, Brave, Arc, etc. + - `isElectron()`: Detects if current window is running within Electron + - `isFromEU()`: Detects if current browser's timezone is from an EU country + - `isFrozenUA()`: Checks if the user-agent matches a frozen/reduced user-agent pattern + - `isStandalonePWA()`: Detects if current window is a standalone PWA + +--- ## Version 2.0.0-rc.3