ua-parser-js 2.0.6 → 2.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/ua-parser.min.js +3 -3
- package/dist/ua-parser.min.mjs +3 -3
- package/dist/ua-parser.pack.js +3 -3
- package/dist/ua-parser.pack.mjs +3 -3
- package/package.json +23 -5
- package/script/cli.js +1 -1
- package/src/bot-detection/bot-detection.d.ts +7 -0
- package/src/bot-detection/bot-detection.js +196 -0
- package/src/bot-detection/bot-detection.mjs +200 -0
- package/src/browser-detection/browser-detection.d.ts +10 -0
- package/src/browser-detection/browser-detection.js +30 -0
- package/src/browser-detection/browser-detection.mjs +34 -0
- package/src/device-detection/device-detection.d.ts +8 -0
- package/src/device-detection/device-detection.js +43 -0
- package/src/device-detection/device-detection.mjs +47 -0
- package/src/enums/ua-parser-enums.d.ts +80 -7
- package/src/enums/ua-parser-enums.js +80 -7
- package/src/enums/ua-parser-enums.mjs +80 -7
- package/src/extensions/ua-parser-extensions.d.ts +1 -1
- package/src/extensions/ua-parser-extensions.js +76 -30
- package/src/extensions/ua-parser-extensions.mjs +76 -30
- package/src/helpers/ua-parser-helpers.d.ts +29 -3
- package/src/helpers/ua-parser-helpers.js +85 -159
- package/src/helpers/ua-parser-helpers.mjs +85 -159
- package/src/main/ua-parser.d.ts +1 -1
- package/src/main/ua-parser.js +223 -215
- package/src/main/ua-parser.mjs +223 -215
- package/dist/ua-parser.html +0 -1
package/src/main/ua-parser.mjs
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
// Source: /src/main/ua-parser.js
|
|
4
4
|
|
|
5
5
|
/////////////////////////////////////////////////////////////////////////////////
|
|
6
|
-
/* UAParser.js v2.0.
|
|
7
|
-
Copyright © 2012-
|
|
6
|
+
/* UAParser.js v2.0.9
|
|
7
|
+
Copyright © 2012-2026 Faisal Salman <f@faisalman.com>
|
|
8
8
|
AGPLv3 License *//*
|
|
9
9
|
Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data.
|
|
10
10
|
Supports browser & node.js environment.
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
// Constants
|
|
22
22
|
/////////////
|
|
23
23
|
|
|
24
|
-
var LIBVERSION = '2.0.
|
|
24
|
+
var LIBVERSION = '2.0.9',
|
|
25
25
|
UA_MAX_LENGTH = 500,
|
|
26
26
|
USER_AGENT = 'user-agent',
|
|
27
27
|
EMPTY = '',
|
|
@@ -59,6 +59,7 @@
|
|
|
59
59
|
EMBEDDED = 'embedded',
|
|
60
60
|
|
|
61
61
|
// browser types
|
|
62
|
+
FETCHER = 'fetcher',
|
|
62
63
|
INAPP = 'inapp',
|
|
63
64
|
|
|
64
65
|
// client hints
|
|
@@ -377,10 +378,11 @@
|
|
|
377
378
|
/(avant|iemobile|slim(?:browser|boat|jet))[\/ ]?([\d\.]*)/i, // Avant/IEMobile/SlimBrowser/SlimBoat/Slimjet
|
|
378
379
|
/(?:ms|\()(ie) ([\w\.]+)/i, // Internet Explorer
|
|
379
380
|
|
|
380
|
-
// Blink/Webkit/KHTML based // Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS/Bowser/QupZilla/Falkon/LG Browser/Otter/qutebrowser/Dooble/Palemoon
|
|
381
|
-
/(flock|rockmelt|midori|epiphany|silk|skyfire|
|
|
382
|
-
// Rekonq/Puffin/
|
|
383
|
-
/(
|
|
381
|
+
// Blink/Webkit/KHTML based // Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS/Bowser/QupZilla/Falkon/LG Browser/Otter/qutebrowser/Dooble/Palemoon/HiBrowser
|
|
382
|
+
/(atlas|flock|rockmelt|midori|epiphany|silk|skyfire|bolt|iron|vivaldi|iridium|phantomjs|bowser|qupzilla|falkon|rekonq|puffin|whale(?!.+naver)|qqbrowserlite|duckduckgo|klar|helio|(?=comodo_)?dragon|otter|dooble|(?:hi|lg |ovi|qute)browser|palemoon)\/v?([-\w\.]+)/i,
|
|
383
|
+
// Atlas/Rekonq/Puffin/Whale/QQBrowserLite/QQ//Vivaldi/DuckDuckGo/Klar/Helio/Dragon
|
|
384
|
+
/(brave)(?: chrome)?\/([\d\.]+)/i, // Brave
|
|
385
|
+
/(aloha|heytap|ovi|115|surf|qwant)browser\/([\d\.]+)/i, // Aloha/HeyTap/Ovi/115/Surf
|
|
384
386
|
/(qwant)(?:ios|mobile)\/([\d\.]+)/i, // Qwant
|
|
385
387
|
/(ecosia|weibo)(?:__| \w+@)([\d\.]+)/i // Ecosia/Weibo
|
|
386
388
|
], [NAME, VERSION], [
|
|
@@ -402,11 +404,15 @@
|
|
|
402
404
|
], [VERSION, [NAME, 'Yandex']], [
|
|
403
405
|
/slbrowser\/([\w\.]+)/i // Smart Lenovo Browser
|
|
404
406
|
], [VERSION, [NAME, 'Smart ' + LENOVO + SUFFIX_BROWSER]], [
|
|
405
|
-
/(
|
|
407
|
+
/(av(?:ast|g|ira))\/([\w\.]+)/i // Avast/AVG/Avira Secure Browser
|
|
406
408
|
], [[NAME, /(.+)/, '$1 Secure' + SUFFIX_BROWSER], VERSION], [
|
|
409
|
+
/norton\/([\w\.]+)/i // Norton Private Browser
|
|
410
|
+
], [VERSION, [NAME, 'Norton Private' + SUFFIX_BROWSER]], [
|
|
407
411
|
/\bfocus\/([\w\.]+)/i // Firefox Focus
|
|
408
412
|
], [VERSION, [NAME, FIREFOX+' Focus']], [
|
|
409
|
-
|
|
413
|
+
/ mms\/([\w\.]+)$/i // Opera Neon
|
|
414
|
+
], [VERSION, [NAME, OPERA+' Neon']], [
|
|
415
|
+
/ opt\/([\w\.]+)$/i // Opera Touch
|
|
410
416
|
], [VERSION, [NAME, OPERA+' Touch']], [
|
|
411
417
|
/coc_coc\w+\/([\w\.]+)/i // Coc Coc Browser
|
|
412
418
|
], [VERSION, [NAME, 'Coc Coc']], [
|
|
@@ -434,10 +440,9 @@
|
|
|
434
440
|
/(tesla)(?: qtcarbrowser|\/(20\d\d\.[-\w\.]+))/i, // Tesla
|
|
435
441
|
/m?(qqbrowser|2345(?=browser|chrome|explorer))\w*[\/ ]?v?([\w\.]+)/i // QQ/2345
|
|
436
442
|
], [NAME, VERSION], [
|
|
437
|
-
/(lbbrowser|rekonq)/i
|
|
443
|
+
/(lbbrowser|luakit|rekonq|steam(?= (clie|tenf|gameo)))/i // LieBao Browser/Luakit/Rekonq/Steam
|
|
438
444
|
], [NAME], [
|
|
439
|
-
/ome\/([\w\.]+)
|
|
440
|
-
/ome\/([\w\.]+).+qihu (360)[es]e/i // 360
|
|
445
|
+
/ome\/([\w\.]+).+(iron(?= saf)|360(?=[es]e$))/i // Iron / 360
|
|
441
446
|
], [VERSION, NAME], [
|
|
442
447
|
|
|
443
448
|
// WebView
|
|
@@ -455,7 +460,7 @@
|
|
|
455
460
|
], [NAME, VERSION, [TYPE, INAPP]], [
|
|
456
461
|
/\bgsa\/([\w\.]+) .*safari\//i // Google Search Appliance on iOS
|
|
457
462
|
], [VERSION, [NAME, 'GSA'], [TYPE, INAPP]], [
|
|
458
|
-
/musical_ly(?:.+app_?version\/|_)([\w\.]+)/i
|
|
463
|
+
/(?:musical_ly|trill)(?:.+app_?version\/|_)([\w\.]+)/i // TikTok
|
|
459
464
|
], [VERSION, [NAME, 'TikTok'], [TYPE, INAPP]], [
|
|
460
465
|
/\[(linkedin)app\]/i // LinkedIn App for iOS & Android
|
|
461
466
|
], [NAME, [TYPE, INAPP]], [
|
|
@@ -465,6 +470,9 @@
|
|
|
465
470
|
/(chromium)[\/ ]([-\w\.]+)/i // Chromium
|
|
466
471
|
], [NAME, VERSION], [
|
|
467
472
|
|
|
473
|
+
/ome-(lighthouse)$/i // Chrome Lighthouse
|
|
474
|
+
], [NAME, [TYPE, FETCHER]], [
|
|
475
|
+
|
|
468
476
|
/headlesschrome(?:\/([\w\.]+)| )/i // Chrome Headless
|
|
469
477
|
], [VERSION, [NAME, CHROME+' Headless']], [
|
|
470
478
|
|
|
@@ -600,17 +608,17 @@
|
|
|
600
608
|
/\b(?:xiao)?((?:red)?mi[-_ ]?pad[\w- ]*)(?: bui|\))/i // Mi Pad tablets
|
|
601
609
|
],[[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, TABLET]], [
|
|
602
610
|
|
|
603
|
-
/\b(poco[\w ]+|m2\d{3}j\d\d[a-z]{2})(?: bui|\))/i, // Xiaomi POCO
|
|
604
611
|
/\b; (\w+) build\/hm\1/i, // Xiaomi Hongmi 'numeric' models
|
|
605
612
|
/\b(hm[-_ ]?note?[_ ]?(?:\d\w)?) bui/i, // Xiaomi Hongmi
|
|
606
|
-
|
|
607
|
-
/oid[^\)]+; (m?[12][
|
|
608
|
-
|
|
613
|
+
// Xiaomi Redmi / POCO / Black Shark / Qin
|
|
614
|
+
/oid[^\)]+; (redmi[\-_ ]?(?:note|k)?[\w_ ]+|m?[12]\d[01]\d\w{3,6}|poco[\w ]+|(shark )?\w{3}-[ah]0|qin ?[1-3](s\+|ultra| pro)?)( bui|; wv|\))/i,
|
|
615
|
+
// Xiaomi Mi
|
|
616
|
+
/\b(mi[-_ ]?(?:a\d|one|one[_ ]plus|note|max|cc)?[_ ]?(?:\d{0,2}\w?)[_ ]?(?:plus|se|lite|pro)?( 5g|lte)?)(?: bui|\))/i,
|
|
609
617
|
/ ([\w ]+) miui\/v?\d/i
|
|
610
618
|
], [[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, MOBILE]], [
|
|
611
619
|
|
|
612
620
|
// OnePlus
|
|
613
|
-
/droid.+; (cph2[3-6]\d[13579]|((gm|hd)19|(ac|be|in|kb)20|(d[en]|eb|le|mt)21|ne22)[0-2]\d|p[g-
|
|
621
|
+
/droid.+; (cph2[3-6]\d[13579]|((gm|hd)19|(ac|be|in|kb)20|(d[en]|eb|le|mt)21|ne22)[0-2]\d|p[g-l]\w[1m]10)\b/i,
|
|
614
622
|
/(?:one)?(?:plus)? (a\d0\d\d)(?: b|\))/i
|
|
615
623
|
], [MODEL, [VENDOR, ONEPLUS], [TYPE, MOBILE]], [
|
|
616
624
|
|
|
@@ -650,7 +658,7 @@
|
|
|
650
658
|
], [MODEL, [VENDOR, MOTOROLA], [TYPE, TABLET]], [
|
|
651
659
|
|
|
652
660
|
// LG
|
|
653
|
-
|
|
661
|
+
/\b(?:lg)?([vl]k\-?\d{3}) bui| 3\.[-\w; ]{10}lg?-([06cv9]{3,4})/i
|
|
654
662
|
], [MODEL, [VENDOR, LG], [TYPE, TABLET]], [
|
|
655
663
|
/(lm(?:-?f100[nv]?|-[\w\.]+)(?= bui|\))|nexus [45])/i,
|
|
656
664
|
/\blg[-e;\/ ]+(?!.*(?:browser|netcast|android tv|watch|webos))(\w+)/i,
|
|
@@ -854,10 +862,10 @@
|
|
|
854
862
|
], [MODEL, [VENDOR, MICROSOFT], [TYPE, CONSOLE]], [
|
|
855
863
|
/(ouya)/i, // Ouya
|
|
856
864
|
/(nintendo) (\w+)/i, // Nintendo
|
|
857
|
-
/(retroid) (pocket ([^\)]+))/i
|
|
858
|
-
|
|
859
|
-
/droid.+; (shield)( bui|\))/i
|
|
860
|
-
], [
|
|
865
|
+
/(retroid) (pocket ([^\)]+))/i, // Retroid Pocket
|
|
866
|
+
/(valve).+(steam deck)/i,
|
|
867
|
+
/droid.+; ((shield|rgcube|gr0006))( bui|\))/i // Nvidia Portable/Anbernic/Logitech
|
|
868
|
+
], [[VENDOR, strMapper, { 'Nvidia': 'Shield', 'Anbernic': 'RGCUBE', 'Logitech': 'GR0006' }], MODEL, [TYPE, CONSOLE]], [
|
|
861
869
|
|
|
862
870
|
///////////////////
|
|
863
871
|
// WEARABLES
|
|
@@ -866,7 +874,7 @@
|
|
|
866
874
|
/\b(sm-[lr]\d\d[0156][fnuw]?s?|gear live)\b/i // Samsung Galaxy Watch
|
|
867
875
|
], [MODEL, [VENDOR, SAMSUNG], [TYPE, WEARABLE]], [
|
|
868
876
|
/((pebble))app/i, // Pebble
|
|
869
|
-
/(asus|google|lg|oppo) ((pixel |zen)?watch[\w ]*)( bui|\))/i
|
|
877
|
+
/(asus|google|lg|oppo|xiaomi) ((pixel |zen)?watch[\w ]*)( bui|\))/i // Asus ZenWatch / LG Watch / Pixel Watch / Xiaomi Watch
|
|
870
878
|
], [VENDOR, MODEL, [TYPE, WEARABLE]], [
|
|
871
879
|
/(ow(?:19|20)?we?[1-3]{1,3})/i // Oppo Watch
|
|
872
880
|
], [MODEL, [VENDOR, OPPO], [TYPE, WEARABLE]], [
|
|
@@ -941,7 +949,7 @@
|
|
|
941
949
|
/(presto)\/([\w\.]+)/i, // Presto
|
|
942
950
|
/(webkit|trident|netfront|netsurf|amaya|lynx|w3m|goanna|servo)\/([\w\.]+)/i, // WebKit/Trident/NetFront/NetSurf/Amaya/Lynx/w3m/Goanna/Servo
|
|
943
951
|
/ekioh(flow)\/([\w\.]+)/i, // Flow
|
|
944
|
-
/(khtml|tasman|links)[\/ ]\(?([\w\.]+)/i,
|
|
952
|
+
/(khtml|tasman|links|dillo)[\/ ]\(?([\w\.]+)/i, // KHTML/Tasman/Links/Dillo
|
|
945
953
|
/(icab)[\/ ]([23]\.[\d\.]+)/i, // iCab
|
|
946
954
|
|
|
947
955
|
/\b(libweb)/i // LibWeb
|
|
@@ -970,7 +978,8 @@
|
|
|
970
978
|
|
|
971
979
|
// iOS/macOS
|
|
972
980
|
/[adehimnop]{4,7}\b(?:.*os ([\w]+) like mac|; opera)/i, // iOS
|
|
973
|
-
/(?:ios;fbsv|ios(?=.+ip(?:ad|hone))|ip(?:ad|hone)(?: |.+i(?:pad)?)os)[\/ ]([\w\.]+)/i,
|
|
981
|
+
/(?:ios;fbsv|ios(?=.+ip(?:ad|hone)|.+apple ?tv)|ip(?:ad|hone)(?: |.+i(?:pad)?)os|apple ?tv.+ios)[\/ ]([\w\.]+)/i,
|
|
982
|
+
/\btvos ?([\w\.]+)/i,
|
|
974
983
|
/cfnetwork\/.+darwin/i
|
|
975
984
|
], [[VERSION, /_/g, '.'], [NAME, 'iOS']], [
|
|
976
985
|
/(mac os x) ?([\w\. ]*)/i,
|
|
@@ -1002,7 +1011,7 @@
|
|
|
1002
1011
|
], [VERSION, [NAME, BLACKBERRY]], [
|
|
1003
1012
|
/(?:symbian ?os|symbos|s60(?=;)|series ?60)[-\/ ]?([\w\.]*)/i // Symbian
|
|
1004
1013
|
], [VERSION, [NAME, 'Symbian']], [
|
|
1005
|
-
/mozilla\/[\d\.]+ \((?:mobile
|
|
1014
|
+
/mozilla\/[\d\.]+ \((?:mobile[;\w ]*|tablet|tv|[^\)]*(?:viera|lg(?:l25|-d300)|alcatel ?o.+|y300-f1)); rv:([\w\.]+)\).+gecko\//i // Firefox OS
|
|
1006
1015
|
], [VERSION, [NAME, FIREFOX+' OS']], [
|
|
1007
1016
|
/\b(?:hp)?wos(?:browser)?\/([\w\.]+)/i, // WebOS
|
|
1008
1017
|
/webos(?:[ \/]?|\.tv-20(?=2[2-9]))(\d[\d\.]*)/i
|
|
@@ -1010,15 +1019,16 @@
|
|
|
1010
1019
|
/web0s;.+?(?:chr[o0]me|safari)\/(\d+)/i
|
|
1011
1020
|
// https://webostv.developer.lge.com/develop/specifications/web-api-and-web-engine
|
|
1012
1021
|
], [[VERSION, strMapper, {'25':'120','24':'108','23':'94','22':'87','6':'79','5':'68','4':'53','3':'38','2':'538','1':'537','*':'TV'}], [NAME, 'webOS']], [
|
|
1013
|
-
/watch(?: ?os[,\/]|\d,\d\/)([\d\.]+)/i // watchOS
|
|
1022
|
+
/watch(?: ?os[,\/ ]|\d,\d\/)([\d\.]+)/i // watchOS
|
|
1014
1023
|
], [VERSION, [NAME, 'watchOS']], [
|
|
1015
1024
|
|
|
1016
1025
|
// Google ChromeOS
|
|
1017
|
-
/
|
|
1018
|
-
], [[NAME,
|
|
1026
|
+
/cros [\w]+(?:\)| ([\w\.]+)\b)/i // Chromium OS
|
|
1027
|
+
], [VERSION, [NAME, 'Chrome OS']],[
|
|
1019
1028
|
|
|
1020
1029
|
// Smart TVs
|
|
1021
|
-
/
|
|
1030
|
+
/kepler ([\w\.]+); (aft|aeo)/i // Vega OS
|
|
1031
|
+
], [VERSION, [NAME, 'Vega OS']],[
|
|
1022
1032
|
/(netrange)mmh/i, // Netrange
|
|
1023
1033
|
/(nettv)\/(\d+\.[\w\.]+)/i, // NetTV
|
|
1024
1034
|
|
|
@@ -1144,25 +1154,25 @@
|
|
|
1144
1154
|
};
|
|
1145
1155
|
}
|
|
1146
1156
|
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
var
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
this[prop] = that[prop];
|
|
1154
|
-
}
|
|
1157
|
+
IData.prototype.then = function (cb) {
|
|
1158
|
+
var that = this;
|
|
1159
|
+
var IDataResolve = function () {
|
|
1160
|
+
for (var prop in that) {
|
|
1161
|
+
if (that.hasOwnProperty(prop)) {
|
|
1162
|
+
this[prop] = that[prop];
|
|
1155
1163
|
}
|
|
1156
|
-
}
|
|
1157
|
-
IDataResolve.prototype = {
|
|
1158
|
-
is : IData.prototype.is,
|
|
1159
|
-
toString : IData.prototype.toString
|
|
1160
|
-
};
|
|
1161
|
-
var resolveData = new IDataResolve();
|
|
1162
|
-
cb(resolveData);
|
|
1163
|
-
return resolveData;
|
|
1164
|
+
}
|
|
1164
1165
|
};
|
|
1165
|
-
|
|
1166
|
+
IDataResolve.prototype = {
|
|
1167
|
+
is : IData.prototype.is,
|
|
1168
|
+
toString : IData.prototype.toString,
|
|
1169
|
+
withClientHints : IData.prototype.withClientHints,
|
|
1170
|
+
withFeatureCheck : IData.prototype.withFeatureCheck
|
|
1171
|
+
};
|
|
1172
|
+
var resolveData = new IDataResolve();
|
|
1173
|
+
cb(resolveData);
|
|
1174
|
+
return resolveData;
|
|
1175
|
+
};
|
|
1166
1176
|
|
|
1167
1177
|
return new IData();
|
|
1168
1178
|
};
|
|
@@ -1194,199 +1204,197 @@
|
|
|
1194
1204
|
}
|
|
1195
1205
|
|
|
1196
1206
|
function UAItem (itemType, ua, rgxMap, uaCH) {
|
|
1207
|
+
setProps.call(this, [
|
|
1208
|
+
['itemType', itemType],
|
|
1209
|
+
['ua', ua],
|
|
1210
|
+
['uaCH', uaCH],
|
|
1211
|
+
['rgxMap', rgxMap],
|
|
1212
|
+
['data', createIData(this, itemType)]
|
|
1213
|
+
]);
|
|
1214
|
+
return this;
|
|
1215
|
+
}
|
|
1197
1216
|
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
this.set = function (prop, val) {
|
|
1204
|
-
this.data[prop] = val;
|
|
1205
|
-
return this;
|
|
1206
|
-
};
|
|
1217
|
+
UAItem.prototype.get = function (prop) {
|
|
1218
|
+
if (!prop) return this.data;
|
|
1219
|
+
return this.data.hasOwnProperty(prop) ? this.data[prop] : undefined;
|
|
1220
|
+
};
|
|
1207
1221
|
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1222
|
+
UAItem.prototype.set = function (prop, val) {
|
|
1223
|
+
this.data[prop] = val;
|
|
1224
|
+
return this;
|
|
1225
|
+
};
|
|
1212
1226
|
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
// Brave-specific detection
|
|
1218
|
-
if (NAVIGATOR.brave && typeof NAVIGATOR.brave.isBrave == TYPEOF.FUNCTION) {
|
|
1219
|
-
this.set(NAME, 'Brave');
|
|
1220
|
-
}
|
|
1221
|
-
break;
|
|
1222
|
-
case DEVICE:
|
|
1223
|
-
// Chrome-specific detection: check for 'mobile' value of navigator.userAgentData
|
|
1224
|
-
if (!this.get(TYPE) && NAVIGATOR_UADATA && NAVIGATOR_UADATA[MOBILE]) {
|
|
1225
|
-
this.set(TYPE, MOBILE);
|
|
1226
|
-
}
|
|
1227
|
-
// iPadOS-specific detection: identified as Mac, but has some iOS-only properties
|
|
1228
|
-
if (this.get(MODEL) == 'Macintosh' && NAVIGATOR && typeof NAVIGATOR.standalone !== TYPEOF.UNDEFINED && NAVIGATOR.maxTouchPoints && NAVIGATOR.maxTouchPoints > 2) {
|
|
1229
|
-
this.set(MODEL, 'iPad')
|
|
1230
|
-
.set(TYPE, TABLET);
|
|
1231
|
-
}
|
|
1232
|
-
break;
|
|
1233
|
-
case OS:
|
|
1234
|
-
// Chrome-specific detection: check for 'platform' value of navigator.userAgentData
|
|
1235
|
-
if (!this.get(NAME) && NAVIGATOR_UADATA && NAVIGATOR_UADATA[PLATFORM]) {
|
|
1236
|
-
this.set(NAME, NAVIGATOR_UADATA[PLATFORM]);
|
|
1237
|
-
}
|
|
1238
|
-
break;
|
|
1239
|
-
case RESULT:
|
|
1240
|
-
var data = this.data;
|
|
1241
|
-
var detect = function (itemType) {
|
|
1242
|
-
return data[itemType]
|
|
1243
|
-
.getItem()
|
|
1244
|
-
.detectFeature()
|
|
1245
|
-
.get();
|
|
1246
|
-
};
|
|
1247
|
-
this.set(BROWSER, detect(BROWSER))
|
|
1248
|
-
.set(CPU, detect(CPU))
|
|
1249
|
-
.set(DEVICE, detect(DEVICE))
|
|
1250
|
-
.set(ENGINE, detect(ENGINE))
|
|
1251
|
-
.set(OS, detect(OS));
|
|
1252
|
-
}
|
|
1253
|
-
}
|
|
1254
|
-
return this;
|
|
1255
|
-
};
|
|
1227
|
+
UAItem.prototype.setCH = function (ch) {
|
|
1228
|
+
this.uaCH = ch;
|
|
1229
|
+
return this;
|
|
1230
|
+
};
|
|
1256
1231
|
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
rgxMapper.call(this.data, this.ua, this.rgxMap);
|
|
1260
|
-
}
|
|
1232
|
+
UAItem.prototype.detectFeature = function () {
|
|
1233
|
+
if (NAVIGATOR && NAVIGATOR.userAgent == this.ua) {
|
|
1261
1234
|
switch (this.itemType) {
|
|
1262
1235
|
case BROWSER:
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
if (this.get(NAME) == 'iOS' && this.get(VERSION) == '18.6') {
|
|
1267
|
-
// Based on the assumption that iOS version is tightly coupled with Safari version
|
|
1268
|
-
var realVersion = /\) Version\/([\d\.]+)/.exec(this.ua); // Get Safari version
|
|
1269
|
-
if (realVersion && parseInt(realVersion[1].substring(0,2), 10) >= 26) {
|
|
1270
|
-
this.set(VERSION, realVersion[1]); // Set as iOS version
|
|
1271
|
-
}
|
|
1272
|
-
}
|
|
1273
|
-
break;
|
|
1274
|
-
}
|
|
1275
|
-
return this;
|
|
1276
|
-
};
|
|
1277
|
-
|
|
1278
|
-
this.parseCH = function () {
|
|
1279
|
-
var uaCH = this.uaCH,
|
|
1280
|
-
rgxMap = this.rgxMap;
|
|
1281
|
-
|
|
1282
|
-
switch (this.itemType) {
|
|
1283
|
-
case BROWSER:
|
|
1284
|
-
case ENGINE:
|
|
1285
|
-
var brands = uaCH[FULLVERLIST] || uaCH[BRANDS], prevName;
|
|
1286
|
-
if (brands) {
|
|
1287
|
-
for (var i=0; i<brands.length; i++) {
|
|
1288
|
-
var brandName = brands[i].brand || brands[i],
|
|
1289
|
-
brandVersion = brands[i].version;
|
|
1290
|
-
if (this.itemType == BROWSER &&
|
|
1291
|
-
!/not.a.brand/i.test(brandName) &&
|
|
1292
|
-
(!prevName ||
|
|
1293
|
-
(/Chrom/.test(prevName) && brandName != CHROMIUM) ||
|
|
1294
|
-
(prevName == EDGE && /WebView2/.test(brandName))
|
|
1295
|
-
)) {
|
|
1296
|
-
brandName = strMapper(brandName, browserHintsMap);
|
|
1297
|
-
prevName = this.get(NAME);
|
|
1298
|
-
if (!(prevName && !/Chrom/.test(prevName) && /Chrom/.test(brandName))) {
|
|
1299
|
-
this.set(NAME, brandName)
|
|
1300
|
-
.set(VERSION, brandVersion)
|
|
1301
|
-
.set(MAJOR, majorize(brandVersion));
|
|
1302
|
-
}
|
|
1303
|
-
prevName = brandName;
|
|
1304
|
-
}
|
|
1305
|
-
if (this.itemType == ENGINE && brandName == CHROMIUM) {
|
|
1306
|
-
this.set(VERSION, brandVersion);
|
|
1307
|
-
}
|
|
1308
|
-
}
|
|
1309
|
-
}
|
|
1310
|
-
break;
|
|
1311
|
-
case CPU:
|
|
1312
|
-
var archName = uaCH[ARCHITECTURE];
|
|
1313
|
-
if (archName) {
|
|
1314
|
-
if (archName && uaCH[BITNESS] == '64') archName += '64';
|
|
1315
|
-
rgxMapper.call(this.data, archName + ';', rgxMap);
|
|
1236
|
+
// Brave-specific detection
|
|
1237
|
+
if (NAVIGATOR.brave && typeof NAVIGATOR.brave.isBrave == TYPEOF.FUNCTION) {
|
|
1238
|
+
this.set(NAME, 'Brave');
|
|
1316
1239
|
}
|
|
1317
1240
|
break;
|
|
1318
1241
|
case DEVICE:
|
|
1319
|
-
|
|
1242
|
+
// Chrome-specific detection: check for 'mobile' value of navigator.userAgentData
|
|
1243
|
+
if (!this.get(TYPE) && NAVIGATOR_UADATA && NAVIGATOR_UADATA[MOBILE]) {
|
|
1320
1244
|
this.set(TYPE, MOBILE);
|
|
1321
1245
|
}
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
rgxMapper.call(reParse, 'droid 9; ' + uaCH[MODEL] + ')', rgxMap);
|
|
1327
|
-
if (!this.get(TYPE) && !!reParse.type) {
|
|
1328
|
-
this.set(TYPE, reParse.type);
|
|
1329
|
-
}
|
|
1330
|
-
if (!this.get(VENDOR) && !!reParse.vendor) {
|
|
1331
|
-
this.set(VENDOR, reParse.vendor);
|
|
1332
|
-
}
|
|
1333
|
-
}
|
|
1334
|
-
}
|
|
1335
|
-
if (uaCH[FORMFACTORS]) {
|
|
1336
|
-
var ff;
|
|
1337
|
-
if (typeof uaCH[FORMFACTORS] !== 'string') {
|
|
1338
|
-
var idx = 0;
|
|
1339
|
-
while (!ff && idx < uaCH[FORMFACTORS].length) {
|
|
1340
|
-
ff = strMapper(uaCH[FORMFACTORS][idx++], formFactorsMap);
|
|
1341
|
-
}
|
|
1342
|
-
} else {
|
|
1343
|
-
ff = strMapper(uaCH[FORMFACTORS], formFactorsMap);
|
|
1344
|
-
}
|
|
1345
|
-
this.set(TYPE, ff);
|
|
1246
|
+
// iPadOS-specific detection: identified as Mac, but has some iOS-only properties
|
|
1247
|
+
if (this.get(MODEL) == 'Macintosh' && NAVIGATOR && typeof NAVIGATOR.standalone !== TYPEOF.UNDEFINED && NAVIGATOR.maxTouchPoints && NAVIGATOR.maxTouchPoints > 2) {
|
|
1248
|
+
this.set(MODEL, 'iPad')
|
|
1249
|
+
.set(TYPE, TABLET);
|
|
1346
1250
|
}
|
|
1347
1251
|
break;
|
|
1348
1252
|
case OS:
|
|
1349
|
-
|
|
1350
|
-
if(
|
|
1351
|
-
|
|
1352
|
-
if (osName == WINDOWS) osVersion = (parseInt(majorize(osVersion), 10) >= 13 ? '11' : '10');
|
|
1353
|
-
this.set(NAME, osName)
|
|
1354
|
-
.set(VERSION, osVersion);
|
|
1253
|
+
// Chrome-specific detection: check for 'platform' value of navigator.userAgentData
|
|
1254
|
+
if (!this.get(NAME) && NAVIGATOR_UADATA && NAVIGATOR_UADATA[PLATFORM]) {
|
|
1255
|
+
this.set(NAME, NAVIGATOR_UADATA[PLATFORM]);
|
|
1355
1256
|
}
|
|
1356
|
-
// Xbox-Specific Detection
|
|
1357
|
-
if (this.get(NAME) == WINDOWS && uaCH[MODEL] == 'Xbox') {
|
|
1358
|
-
this.set(NAME, 'Xbox')
|
|
1359
|
-
.set(VERSION, undefined);
|
|
1360
|
-
}
|
|
1361
1257
|
break;
|
|
1362
1258
|
case RESULT:
|
|
1363
1259
|
var data = this.data;
|
|
1364
|
-
var
|
|
1260
|
+
var detect = function (itemType) {
|
|
1365
1261
|
return data[itemType]
|
|
1366
1262
|
.getItem()
|
|
1367
|
-
.
|
|
1368
|
-
.parseCH()
|
|
1263
|
+
.detectFeature()
|
|
1369
1264
|
.get();
|
|
1370
1265
|
};
|
|
1371
|
-
this.set(BROWSER,
|
|
1372
|
-
.set(CPU,
|
|
1373
|
-
.set(DEVICE,
|
|
1374
|
-
.set(ENGINE,
|
|
1375
|
-
.set(OS,
|
|
1266
|
+
this.set(BROWSER, detect(BROWSER))
|
|
1267
|
+
.set(CPU, detect(CPU))
|
|
1268
|
+
.set(DEVICE, detect(DEVICE))
|
|
1269
|
+
.set(ENGINE, detect(ENGINE))
|
|
1270
|
+
.set(OS, detect(OS));
|
|
1376
1271
|
}
|
|
1377
|
-
|
|
1378
|
-
|
|
1272
|
+
}
|
|
1273
|
+
return this;
|
|
1274
|
+
};
|
|
1379
1275
|
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1276
|
+
UAItem.prototype.parseUA = function () {
|
|
1277
|
+
if (this.itemType != RESULT) {
|
|
1278
|
+
rgxMapper.call(this.data, this.ua, this.rgxMap);
|
|
1279
|
+
}
|
|
1280
|
+
switch (this.itemType) {
|
|
1281
|
+
case BROWSER:
|
|
1282
|
+
this.set(MAJOR, majorize(this.get(VERSION)));
|
|
1283
|
+
break;
|
|
1284
|
+
case OS:
|
|
1285
|
+
if (this.get(NAME) == 'iOS' && this.get(VERSION) == '18.6') {
|
|
1286
|
+
// Based on the assumption that iOS version is tightly coupled with Safari version
|
|
1287
|
+
var realVersion = /\) Version\/([\d\.]+)/.exec(this.ua); // Get Safari version
|
|
1288
|
+
if (realVersion && parseInt(realVersion[1].substring(0,2), 10) >= 26) {
|
|
1289
|
+
this.set(VERSION, realVersion[1]); // Set as iOS version
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
break;
|
|
1293
|
+
}
|
|
1294
|
+
return this;
|
|
1295
|
+
};
|
|
1387
1296
|
|
|
1297
|
+
UAItem.prototype.parseCH = function () {
|
|
1298
|
+
var uaCH = this.uaCH,
|
|
1299
|
+
rgxMap = this.rgxMap;
|
|
1300
|
+
|
|
1301
|
+
switch (this.itemType) {
|
|
1302
|
+
case BROWSER:
|
|
1303
|
+
case ENGINE:
|
|
1304
|
+
var brands = uaCH[FULLVERLIST] || uaCH[BRANDS], prevName;
|
|
1305
|
+
if (brands) {
|
|
1306
|
+
for (var i=0; i<brands.length; i++) {
|
|
1307
|
+
var brandName = brands[i].brand || brands[i],
|
|
1308
|
+
brandVersion = brands[i].version;
|
|
1309
|
+
if (this.itemType == BROWSER &&
|
|
1310
|
+
!/not.a.brand/i.test(brandName) &&
|
|
1311
|
+
(!prevName ||
|
|
1312
|
+
(/Chrom/.test(prevName) && brandName != CHROMIUM) ||
|
|
1313
|
+
(prevName == EDGE && /WebView2/.test(brandName))
|
|
1314
|
+
)) {
|
|
1315
|
+
brandName = strMapper(brandName, browserHintsMap);
|
|
1316
|
+
prevName = this.get(NAME);
|
|
1317
|
+
if (!(prevName && !/Chrom/.test(prevName) && /Chrom/.test(brandName))) {
|
|
1318
|
+
this.set(NAME, brandName)
|
|
1319
|
+
.set(VERSION, brandVersion)
|
|
1320
|
+
.set(MAJOR, majorize(brandVersion));
|
|
1321
|
+
}
|
|
1322
|
+
prevName = brandName;
|
|
1323
|
+
}
|
|
1324
|
+
if (this.itemType == ENGINE && brandName == CHROMIUM) {
|
|
1325
|
+
this.set(VERSION, brandVersion);
|
|
1326
|
+
}
|
|
1327
|
+
}
|
|
1328
|
+
}
|
|
1329
|
+
break;
|
|
1330
|
+
case CPU:
|
|
1331
|
+
var archName = uaCH[ARCHITECTURE];
|
|
1332
|
+
if (archName) {
|
|
1333
|
+
if (archName && uaCH[BITNESS] == '64') archName += '64';
|
|
1334
|
+
rgxMapper.call(this.data, archName + ';', rgxMap);
|
|
1335
|
+
}
|
|
1336
|
+
break;
|
|
1337
|
+
case DEVICE:
|
|
1338
|
+
if (uaCH[MOBILE]) {
|
|
1339
|
+
this.set(TYPE, MOBILE);
|
|
1340
|
+
}
|
|
1341
|
+
if (uaCH[MODEL]) {
|
|
1342
|
+
this.set(MODEL, uaCH[MODEL]);
|
|
1343
|
+
if (!this.get(TYPE) || !this.get(VENDOR)) {
|
|
1344
|
+
var reParse = {};
|
|
1345
|
+
rgxMapper.call(reParse, 'droid 9; ' + uaCH[MODEL] + ')', rgxMap);
|
|
1346
|
+
if (!this.get(TYPE) && !!reParse.type) {
|
|
1347
|
+
this.set(TYPE, reParse.type);
|
|
1348
|
+
}
|
|
1349
|
+
if (!this.get(VENDOR) && !!reParse.vendor) {
|
|
1350
|
+
this.set(VENDOR, reParse.vendor);
|
|
1351
|
+
}
|
|
1352
|
+
}
|
|
1353
|
+
}
|
|
1354
|
+
if (uaCH[FORMFACTORS]) {
|
|
1355
|
+
var ff;
|
|
1356
|
+
if (typeof uaCH[FORMFACTORS] !== 'string') {
|
|
1357
|
+
var idx = 0;
|
|
1358
|
+
while (!ff && idx < uaCH[FORMFACTORS].length) {
|
|
1359
|
+
ff = strMapper(uaCH[FORMFACTORS][idx++], formFactorsMap);
|
|
1360
|
+
}
|
|
1361
|
+
} else {
|
|
1362
|
+
ff = strMapper(uaCH[FORMFACTORS], formFactorsMap);
|
|
1363
|
+
}
|
|
1364
|
+
this.set(TYPE, ff);
|
|
1365
|
+
}
|
|
1366
|
+
break;
|
|
1367
|
+
case OS:
|
|
1368
|
+
var osName = uaCH[PLATFORM];
|
|
1369
|
+
if(osName) {
|
|
1370
|
+
var osVersion = uaCH[PLATFORMVER];
|
|
1371
|
+
if (osName == WINDOWS) osVersion = (parseInt(majorize(osVersion), 10) >= 13 ? '11' : '10');
|
|
1372
|
+
this.set(NAME, osName)
|
|
1373
|
+
.set(VERSION, osVersion);
|
|
1374
|
+
}
|
|
1375
|
+
// Xbox-Specific Detection
|
|
1376
|
+
if (this.get(NAME) == WINDOWS && uaCH[MODEL] == 'Xbox') {
|
|
1377
|
+
this.set(NAME, 'Xbox')
|
|
1378
|
+
.set(VERSION, undefined);
|
|
1379
|
+
}
|
|
1380
|
+
break;
|
|
1381
|
+
case RESULT:
|
|
1382
|
+
var data = this.data;
|
|
1383
|
+
var parse = function (itemType) {
|
|
1384
|
+
return data[itemType]
|
|
1385
|
+
.getItem()
|
|
1386
|
+
.setCH(uaCH)
|
|
1387
|
+
.parseCH()
|
|
1388
|
+
.get();
|
|
1389
|
+
};
|
|
1390
|
+
this.set(BROWSER, parse(BROWSER))
|
|
1391
|
+
.set(CPU, parse(CPU))
|
|
1392
|
+
.set(DEVICE, parse(DEVICE))
|
|
1393
|
+
.set(ENGINE, parse(ENGINE))
|
|
1394
|
+
.set(OS, parse(OS));
|
|
1395
|
+
}
|
|
1388
1396
|
return this;
|
|
1389
|
-
}
|
|
1397
|
+
};
|
|
1390
1398
|
|
|
1391
1399
|
function UAParser (ua, extensions, headers) {
|
|
1392
1400
|
|
package/dist/ua-parser.html
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<script src="./ua-parser.min.js"></script>
|