ua-parser-js 2.0.3 → 2.0.6
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 +62 -33
- package/dist/ua-parser.min.js +2 -2
- package/dist/ua-parser.min.mjs +2 -2
- package/dist/ua-parser.pack.js +2 -2
- package/dist/ua-parser.pack.mjs +2 -2
- package/package.json +7 -9
- package/script/cli.js +92 -2
- package/src/enums/ua-parser-enums.d.ts +734 -364
- package/src/enums/ua-parser-enums.js +371 -16
- package/src/enums/ua-parser-enums.mjs +371 -16
- package/src/extensions/ua-parser-extensions.d.ts +1 -1
- package/src/extensions/ua-parser-extensions.js +89 -24
- package/src/extensions/ua-parser-extensions.mjs +89 -24
- package/src/helpers/ua-parser-helpers.d.ts +10 -22
- package/src/helpers/ua-parser-helpers.js +88 -43
- package/src/helpers/ua-parser-helpers.mjs +88 -43
- package/src/main/ua-parser.d.ts +7 -8
- package/src/main/ua-parser.js +316 -244
- package/src/main/ua-parser.mjs +313 -241
package/src/main/ua-parser.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/////////////////////////////////////////////////////////////////////////////////
|
|
2
|
-
/* UAParser.js v2.0.
|
|
2
|
+
/* UAParser.js v2.0.6
|
|
3
3
|
Copyright © 2012-2025 Faisal Salman <f@faisalman.com>
|
|
4
4
|
AGPLv3 License *//*
|
|
5
5
|
Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data.
|
|
@@ -19,26 +19,26 @@
|
|
|
19
19
|
// Constants
|
|
20
20
|
/////////////
|
|
21
21
|
|
|
22
|
-
var LIBVERSION = '2.0.
|
|
22
|
+
var LIBVERSION = '2.0.6',
|
|
23
23
|
UA_MAX_LENGTH = 500,
|
|
24
24
|
USER_AGENT = 'user-agent',
|
|
25
25
|
EMPTY = '',
|
|
26
26
|
UNKNOWN = '?',
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
27
|
+
TYPEOF = {
|
|
28
|
+
FUNCTION : 'function',
|
|
29
|
+
OBJECT : 'object',
|
|
30
|
+
STRING : 'string',
|
|
31
|
+
UNDEFINED : 'undefined'
|
|
32
|
+
},
|
|
33
33
|
|
|
34
34
|
// properties
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
35
|
+
BROWSER = 'browser',
|
|
36
|
+
CPU = 'cpu',
|
|
37
|
+
DEVICE = 'device',
|
|
38
|
+
ENGINE = 'engine',
|
|
39
|
+
OS = 'os',
|
|
40
|
+
RESULT = 'result',
|
|
41
|
+
|
|
42
42
|
NAME = 'name',
|
|
43
43
|
TYPE = 'type',
|
|
44
44
|
VENDOR = 'vendor',
|
|
@@ -66,16 +66,16 @@
|
|
|
66
66
|
PLATFORM = 'platform',
|
|
67
67
|
PLATFORMVER = 'platformVersion',
|
|
68
68
|
BITNESS = 'bitness',
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
CH_ALL_VALUES
|
|
69
|
+
CH = 'sec-ch-ua',
|
|
70
|
+
CH_FULL_VER_LIST= CH + '-full-version-list',
|
|
71
|
+
CH_ARCH = CH + '-arch',
|
|
72
|
+
CH_BITNESS = CH + '-' + BITNESS,
|
|
73
|
+
CH_FORM_FACTORS = CH + '-form-factors',
|
|
74
|
+
CH_MOBILE = CH + '-' + MOBILE,
|
|
75
|
+
CH_MODEL = CH + '-' + MODEL,
|
|
76
|
+
CH_PLATFORM = CH + '-' + PLATFORM,
|
|
77
|
+
CH_PLATFORM_VER = CH_PLATFORM + '-version',
|
|
78
|
+
CH_ALL_VALUES = [BRANDS, FULLVERLIST, MOBILE, MODEL, PLATFORM, PLATFORMVER, ARCHITECTURE, FORMFACTORS, BITNESS],
|
|
79
79
|
|
|
80
80
|
// device vendors
|
|
81
81
|
AMAZON = 'Amazon',
|
|
@@ -114,7 +114,7 @@
|
|
|
114
114
|
// os
|
|
115
115
|
WINDOWS = 'Windows';
|
|
116
116
|
|
|
117
|
-
var isWindow = typeof window !==
|
|
117
|
+
var isWindow = typeof window !== TYPEOF.UNDEFINED,
|
|
118
118
|
NAVIGATOR = (isWindow && window.navigator) ?
|
|
119
119
|
window.navigator :
|
|
120
120
|
undefined,
|
|
@@ -150,13 +150,13 @@
|
|
|
150
150
|
return enums;
|
|
151
151
|
},
|
|
152
152
|
has = function (str1, str2) {
|
|
153
|
-
if (typeof str1 ===
|
|
153
|
+
if (typeof str1 === TYPEOF.OBJECT && str1.length > 0) {
|
|
154
154
|
for (var i in str1) {
|
|
155
|
-
if (lowerize(
|
|
155
|
+
if (lowerize(str2) == lowerize(str1[i])) return true;
|
|
156
156
|
}
|
|
157
157
|
return false;
|
|
158
158
|
}
|
|
159
|
-
return isString(str1) ? lowerize(str2)
|
|
159
|
+
return isString(str1) ? lowerize(str2) == lowerize(str1) : false;
|
|
160
160
|
},
|
|
161
161
|
isExtensions = function (obj, deep) {
|
|
162
162
|
for (var prop in obj) {
|
|
@@ -164,7 +164,7 @@
|
|
|
164
164
|
}
|
|
165
165
|
},
|
|
166
166
|
isString = function (val) {
|
|
167
|
-
return typeof val ===
|
|
167
|
+
return typeof val === TYPEOF.STRING;
|
|
168
168
|
},
|
|
169
169
|
itemListToArray = function (header) {
|
|
170
170
|
if (!header) return undefined;
|
|
@@ -188,8 +188,10 @@
|
|
|
188
188
|
},
|
|
189
189
|
setProps = function (arr) {
|
|
190
190
|
for (var i in arr) {
|
|
191
|
+
if (!arr.hasOwnProperty(i)) continue;
|
|
192
|
+
|
|
191
193
|
var propName = arr[i];
|
|
192
|
-
if (typeof propName ==
|
|
194
|
+
if (typeof propName == TYPEOF.OBJECT && propName.length == 2) {
|
|
193
195
|
this[propName[0]] = propName[1];
|
|
194
196
|
} else {
|
|
195
197
|
this[propName] = undefined;
|
|
@@ -204,10 +206,8 @@
|
|
|
204
206
|
return strip(/\\?\"/g, str);
|
|
205
207
|
},
|
|
206
208
|
trim = function (str, len) {
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
return typeof len === UNDEF_TYPE ? str : str.substring(0, UA_MAX_LENGTH);
|
|
210
|
-
}
|
|
209
|
+
str = strip(/^\s\s*/, String(str));
|
|
210
|
+
return typeof len === TYPEOF.UNDEFINED ? str : str.substring(0, len);
|
|
211
211
|
};
|
|
212
212
|
|
|
213
213
|
///////////////
|
|
@@ -238,26 +238,34 @@
|
|
|
238
238
|
match = matches[++k];
|
|
239
239
|
q = props[p];
|
|
240
240
|
// check if given property is actually array
|
|
241
|
-
if (typeof q ===
|
|
241
|
+
if (typeof q === TYPEOF.OBJECT && q.length > 0) {
|
|
242
242
|
if (q.length === 2) {
|
|
243
|
-
if (typeof q[1] ==
|
|
243
|
+
if (typeof q[1] == TYPEOF.FUNCTION) {
|
|
244
244
|
// assign modified match
|
|
245
245
|
this[q[0]] = q[1].call(this, match);
|
|
246
246
|
} else {
|
|
247
247
|
// assign given value, ignore regex match
|
|
248
248
|
this[q[0]] = q[1];
|
|
249
249
|
}
|
|
250
|
-
} else if (q.length
|
|
251
|
-
//
|
|
252
|
-
if (typeof q[1] ===
|
|
253
|
-
|
|
254
|
-
|
|
250
|
+
} else if (q.length >= 3) {
|
|
251
|
+
// Check whether q[1] FUNCTION or REGEX
|
|
252
|
+
if (typeof q[1] === TYPEOF.FUNCTION && !(q[1].exec && q[1].test)) {
|
|
253
|
+
if (q.length > 3) {
|
|
254
|
+
this[q[0]] = match ? q[1].apply(this, q.slice(2)) : undefined;
|
|
255
|
+
} else {
|
|
256
|
+
// call function (usually string mapper)
|
|
257
|
+
this[q[0]] = match ? q[1].call(this, match, q[2]) : undefined;
|
|
258
|
+
}
|
|
255
259
|
} else {
|
|
256
|
-
|
|
257
|
-
|
|
260
|
+
if (q.length == 3) {
|
|
261
|
+
// sanitize match using given regex
|
|
262
|
+
this[q[0]] = match ? match.replace(q[1], q[2]) : undefined;
|
|
263
|
+
} else if (q.length == 4) {
|
|
264
|
+
this[q[0]] = match ? q[3].call(this, match.replace(q[1], q[2])) : undefined;
|
|
265
|
+
} else if (q.length > 4) {
|
|
266
|
+
this[q[0]] = match ? q[3].apply(this, [match.replace(q[1], q[2])].concat(q.slice(4))) : undefined;
|
|
267
|
+
}
|
|
258
268
|
}
|
|
259
|
-
} else if (q.length === 4) {
|
|
260
|
-
this[q[0]] = match ? q[3].call(this, match.replace(q[1], q[2])) : undefined;
|
|
261
269
|
}
|
|
262
270
|
} else {
|
|
263
271
|
this[q] = match ? match : undefined;
|
|
@@ -273,7 +281,7 @@
|
|
|
273
281
|
|
|
274
282
|
for (var i in map) {
|
|
275
283
|
// check if current value is array
|
|
276
|
-
if (typeof map[i] ===
|
|
284
|
+
if (typeof map[i] === TYPEOF.OBJECT && map[i].length > 0) {
|
|
277
285
|
for (var j = 0; j < map[i].length; j++) {
|
|
278
286
|
if (has(map[i][j], str)) {
|
|
279
287
|
return (i === UNKNOWN) ? undefined : i;
|
|
@@ -291,17 +299,17 @@
|
|
|
291
299
|
//////////////
|
|
292
300
|
|
|
293
301
|
var windowsVersionMap = {
|
|
294
|
-
'ME'
|
|
295
|
-
'NT 3.
|
|
296
|
-
'NT 4.0'
|
|
297
|
-
'2000'
|
|
298
|
-
'XP'
|
|
299
|
-
'Vista'
|
|
300
|
-
'7'
|
|
301
|
-
'8'
|
|
302
|
-
'8.1'
|
|
303
|
-
'10'
|
|
304
|
-
'
|
|
302
|
+
'ME' : '4.90',
|
|
303
|
+
'NT 3.51': '3.51',
|
|
304
|
+
'NT 4.0': '4.0',
|
|
305
|
+
'2000' : ['5.0', '5.01'],
|
|
306
|
+
'XP' : ['5.1', '5.2'],
|
|
307
|
+
'Vista' : '6.0',
|
|
308
|
+
'7' : '6.1',
|
|
309
|
+
'8' : '6.2',
|
|
310
|
+
'8.1' : '6.3',
|
|
311
|
+
'10' : ['6.4', '10.0'],
|
|
312
|
+
'NT' : ''
|
|
305
313
|
},
|
|
306
314
|
|
|
307
315
|
formFactorsMap = {
|
|
@@ -313,6 +321,18 @@
|
|
|
313
321
|
'xr' : ['VR', 'XR'],
|
|
314
322
|
'?' : ['Desktop', 'Unknown'],
|
|
315
323
|
'*' : undefined
|
|
324
|
+
},
|
|
325
|
+
|
|
326
|
+
browserHintsMap = {
|
|
327
|
+
'Chrome' : 'Google Chrome',
|
|
328
|
+
'Edge' : 'Microsoft Edge',
|
|
329
|
+
'Edge WebView2' : 'Microsoft Edge WebView2',
|
|
330
|
+
'Chrome WebView': 'Android WebView',
|
|
331
|
+
'Chrome Headless':'HeadlessChrome',
|
|
332
|
+
'Huawei Browser': 'HuaweiBrowser',
|
|
333
|
+
'MIUI Browser' : 'Miui Browser',
|
|
334
|
+
'Opera Mobi' : 'OperaMobile',
|
|
335
|
+
'Yandex' : 'YaBrowser'
|
|
316
336
|
};
|
|
317
337
|
|
|
318
338
|
//////////////
|
|
@@ -326,7 +346,9 @@
|
|
|
326
346
|
// Most common regardless engine
|
|
327
347
|
/\b(?:crmo|crios)\/([\w\.]+)/i // Chrome for Android/iOS
|
|
328
348
|
], [VERSION, [NAME, PREFIX_MOBILE + 'Chrome']], [
|
|
329
|
-
/
|
|
349
|
+
/webview.+edge\/([\w\.]+)/i // Microsoft Edge
|
|
350
|
+
], [VERSION, [NAME, EDGE+' WebView']], [
|
|
351
|
+
/edg(?:e|ios|a)?\/([\w\.]+)/i
|
|
330
352
|
], [VERSION, [NAME, 'Edge']], [
|
|
331
353
|
|
|
332
354
|
// Presto based
|
|
@@ -353,10 +375,11 @@
|
|
|
353
375
|
/(avant|iemobile|slim(?:browser|boat|jet))[\/ ]?([\d\.]*)/i, // Avant/IEMobile/SlimBrowser/SlimBoat/Slimjet
|
|
354
376
|
/(?:ms|\()(ie) ([\w\.]+)/i, // Internet Explorer
|
|
355
377
|
|
|
356
|
-
// Blink/Webkit/KHTML based // Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS/Bowser/QupZilla/Falkon/LG Browser/Otter/qutebrowser/Dooble
|
|
357
|
-
/(flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi|iridium|phantomjs|bowser|qupzilla|falkon|rekonq|puffin|brave|whale(?!.+naver)|qqbrowserlite|duckduckgo|klar|helio|(?=comodo_)?dragon|otter|dooble|(?:lg |qute)browser)\/([-\w\.]+)/i,
|
|
378
|
+
// Blink/Webkit/KHTML based // Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS/Bowser/QupZilla/Falkon/LG Browser/Otter/qutebrowser/Dooble/Palemoon
|
|
379
|
+
/(flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi|iridium|phantomjs|bowser|qupzilla|falkon|rekonq|puffin|brave|whale(?!.+naver)|qqbrowserlite|duckduckgo|klar|helio|(?=comodo_)?dragon|otter|dooble|(?:lg |qute)browser|palemoon)\/([-\w\.]+)/i,
|
|
358
380
|
// Rekonq/Puffin/Brave/Whale/QQBrowserLite/QQ//Vivaldi/DuckDuckGo/Klar/Helio/Dragon
|
|
359
|
-
/(heytap|ovi|115|surf)browser\/([\d\.]+)/i,
|
|
381
|
+
/(heytap|ovi|115|surf|qwant)browser\/([\d\.]+)/i, // HeyTap/Ovi/115/Surf
|
|
382
|
+
/(qwant)(?:ios|mobile)\/([\d\.]+)/i, // Qwant
|
|
360
383
|
/(ecosia|weibo)(?:__| \w+@)([\d\.]+)/i // Ecosia/Weibo
|
|
361
384
|
], [NAME, VERSION], [
|
|
362
385
|
/quark(?:pc)?\/([-\w\.]+)/i // Quark
|
|
@@ -418,7 +441,6 @@
|
|
|
418
441
|
// WebView
|
|
419
442
|
/((?:fban\/fbios|fb_iab\/fb4a)(?!.+fbav)|;fbav\/([\w\.]+);)/i // Facebook App for iOS & Android
|
|
420
443
|
], [[NAME, FACEBOOK], VERSION, [TYPE, INAPP]], [
|
|
421
|
-
/(Klarna)\/([\w\.]+)/i, // Klarna Shopping Browser for iOS & Android
|
|
422
444
|
/(kakao(?:talk|story))[\/ ]([\w\.]+)/i, // Kakao App
|
|
423
445
|
/(naver)\(.*?(\d+\.[\w\.]+).*\)/i, // Naver InApp
|
|
424
446
|
/(daum)apps[\/ ]([\w\.]+)/i, // Daum App
|
|
@@ -426,7 +448,8 @@
|
|
|
426
448
|
/\b(line)\/([\w\.]+)\/iab/i, // Line App for Android
|
|
427
449
|
/(alipay)client\/([\w\.]+)/i, // Alipay
|
|
428
450
|
/(twitter)(?:and| f.+e\/([\w\.]+))/i, // Twitter
|
|
429
|
-
/(
|
|
451
|
+
/(bing)(?:web|sapphire)\/([\w\.]+)/i, // Bing
|
|
452
|
+
/(instagram|snapchat|klarna)[\/ ]([-\w\.]+)/i // Instagram/Snapchat/Klarna
|
|
430
453
|
], [NAME, VERSION, [TYPE, INAPP]], [
|
|
431
454
|
/\bgsa\/([\w\.]+) .*safari\//i // Google Search Appliance on iOS
|
|
432
455
|
], [VERSION, [NAME, 'GSA'], [TYPE, INAPP]], [
|
|
@@ -434,6 +457,8 @@
|
|
|
434
457
|
], [VERSION, [NAME, 'TikTok'], [TYPE, INAPP]], [
|
|
435
458
|
/\[(linkedin)app\]/i // LinkedIn App for iOS & Android
|
|
436
459
|
], [NAME, [TYPE, INAPP]], [
|
|
460
|
+
/(zalo(?:app)?)[\/\sa-z]*([\w\.-]+)/i // Zalo
|
|
461
|
+
], [[NAME, /(.+)/, 'Zalo'], VERSION, [TYPE, INAPP]], [
|
|
437
462
|
|
|
438
463
|
/(chromium)[\/ ]([-\w\.]+)/i // Chromium
|
|
439
464
|
], [NAME, VERSION], [
|
|
@@ -441,6 +466,9 @@
|
|
|
441
466
|
/headlesschrome(?:\/([\w\.]+)| )/i // Chrome Headless
|
|
442
467
|
], [VERSION, [NAME, CHROME+' Headless']], [
|
|
443
468
|
|
|
469
|
+
/wv\).+chrome\/([\w\.]+).+edgw\//i // Edge WebView2
|
|
470
|
+
], [VERSION, [NAME, EDGE+' WebView2']], [
|
|
471
|
+
|
|
444
472
|
/ wv\).+(chrome)\/([\w\.]+)/i // Chrome WebView
|
|
445
473
|
], [[NAME, CHROME+' WebView'], VERSION], [
|
|
446
474
|
|
|
@@ -478,10 +506,10 @@
|
|
|
478
506
|
/(swiftfox)/i, // Swiftfox
|
|
479
507
|
/(icedragon|iceweasel|camino|chimera|fennec|maemo browser|minimo|conkeror)[\/ ]?([\w\.\+]+)/i,
|
|
480
508
|
// IceDragon/Iceweasel/Camino/Chimera/Fennec/Maemo/Minimo/Conkeror
|
|
481
|
-
/(seamonkey|k-meleon|icecat|iceape|firebird|phoenix|
|
|
509
|
+
/(seamonkey|k-meleon|icecat|iceape|firebird|phoenix|basilisk|waterfox)\/([-\w\.]+)$/i,
|
|
482
510
|
// Firefox/SeaMonkey/K-Meleon/IceCat/IceApe/Firebird/Phoenix
|
|
483
511
|
/(firefox)\/([\w\.]+)/i, // Other Firefox-based
|
|
484
|
-
/(mozilla)\/([\w\.]+
|
|
512
|
+
/(mozilla)\/([\w\.]+(?= .+rv\:.+gecko\/\d+)|[0-4][\w\.]+(?!.+compatible))/i, // Mozilla
|
|
485
513
|
|
|
486
514
|
// Other
|
|
487
515
|
/(amaya|dillo|doris|icab|ladybird|lynx|mosaic|netsurf|obigo|polaris|w3m|(?:go|ice|up)[\. ]?browser)[-\/ ]?v?([\w\.]+)/i,
|
|
@@ -512,15 +540,17 @@
|
|
|
512
540
|
/( (ce|mobile); ppc;|\/[\w\.]+arm\b)/i
|
|
513
541
|
], [[ARCHITECTURE, 'arm']], [
|
|
514
542
|
|
|
515
|
-
/((ppc|powerpc)(64)?)( mac|;|\))/i // PowerPC
|
|
516
|
-
], [[ARCHITECTURE, /ower/, EMPTY, lowerize]], [
|
|
517
|
-
|
|
518
543
|
/ sun4\w[;\)]/i // SPARC
|
|
519
544
|
], [[ARCHITECTURE, 'sparc']], [
|
|
520
|
-
|
|
521
|
-
/\b(avr32|ia64(?=;)|68k(?=\))|\barm(?=v([1-7]|[5-7]1)l?|;|eabi)|(irix|mips|sparc)(64)?\b|pa-risc)/i
|
|
522
545
|
// IA64, 68K, ARM/64, AVR/32, IRIX/64, MIPS/64, SPARC/64, PA-RISC
|
|
523
|
-
]
|
|
546
|
+
/\b(avr32|ia64(?=;)|68k(?=\))|\barm(?=v([1-7]|[5-7]1)l?|;|eabi)|(irix|mips|sparc)(64)?\b|pa-risc)/i,
|
|
547
|
+
/((ppc|powerpc)(64)?)( mac|;|\))/i, // PowerPC
|
|
548
|
+
/(?:osf1|[freopnt]{3,4}bsd) (alpha)/i // Alpha
|
|
549
|
+
], [[ARCHITECTURE, /ower/, EMPTY, lowerize]], [
|
|
550
|
+
/mc680.0/i
|
|
551
|
+
], [[ARCHITECTURE, '68k']], [
|
|
552
|
+
/winnt.+\[axp/i
|
|
553
|
+
], [[ARCHITECTURE, 'alpha']]
|
|
524
554
|
],
|
|
525
555
|
|
|
526
556
|
device : [[
|
|
@@ -533,16 +563,15 @@
|
|
|
533
563
|
/\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
|
|
534
564
|
], [MODEL, [VENDOR, SAMSUNG], [TYPE, TABLET]], [
|
|
535
565
|
/\b((?:s[cgp]h|gt|sm)-(?![lr])\w+|sc[g-]?[\d]+a?|galaxy nexus)/i,
|
|
536
|
-
/samsung[- ]((?!sm-[lr])[-\w]+)/i,
|
|
566
|
+
/samsung[- ]((?!sm-[lr]|browser)[-\w]+)/i,
|
|
537
567
|
/sec-(sgh\w+)/i
|
|
538
568
|
], [MODEL, [VENDOR, SAMSUNG], [TYPE, MOBILE]], [
|
|
539
569
|
|
|
540
570
|
// Apple
|
|
541
|
-
/(?:\/|\()(ip(?:hone|od)[\w, ]*)
|
|
571
|
+
/(?:\/|\()(ip(?:hone|od)[\w, ]*)[\/\);]/i // iPod/iPhone
|
|
542
572
|
], [MODEL, [VENDOR, APPLE], [TYPE, MOBILE]], [
|
|
543
|
-
/\(
|
|
544
|
-
|
|
545
|
-
/\b(ipad)\d\d?,\d\d?[;\]].+ios/i
|
|
573
|
+
/\b(?:ios|apple\w+)\/.+[\(\/](ipad)/i, // iPad
|
|
574
|
+
/\b(ipad)[\d,]*[;\] ].+(mac |i(pad)?)os/i
|
|
546
575
|
], [MODEL, [VENDOR, APPLE], [TYPE, TABLET]], [
|
|
547
576
|
/(macintosh);/i
|
|
548
577
|
], [MODEL, [VENDOR, APPLE]], [
|
|
@@ -560,13 +589,13 @@
|
|
|
560
589
|
// Huawei
|
|
561
590
|
/\b((?:ag[rs][2356]?k?|bah[234]?|bg[2o]|bt[kv]|cmr|cpn|db[ry]2?|jdn2|got|kob2?k?|mon|pce|scm|sht?|[tw]gr|vrd)-[ad]?[lw][0125][09]b?|605hw|bg2-u03|(?:gem|fdr|m2|ple|t1)-[7a]0[1-4][lu]|t1-a2[13][lw]|mediapad[\w\. ]*(?= bui|\)))\b(?!.+d\/s)/i
|
|
562
591
|
], [MODEL, [VENDOR, HUAWEI], [TYPE, TABLET]], [
|
|
563
|
-
/(?:huawei)([-\w ]+)[;\)]/i,
|
|
564
|
-
/\b(nexus 6p|\w{2,4}e?-[atu]?[ln][\dx][
|
|
592
|
+
/(?:huawei) ?([-\w ]+)[;\)]/i,
|
|
593
|
+
/\b(nexus 6p|\w{2,4}e?-[atu]?[ln][\dx][\dc][adnt]?)\b(?!.+d\/s)/i
|
|
565
594
|
], [MODEL, [VENDOR, HUAWEI], [TYPE, MOBILE]], [
|
|
566
595
|
|
|
567
596
|
// Xiaomi
|
|
568
597
|
/oid[^\)]+; (2[\dbc]{4}(182|283|rp\w{2})[cgl]|m2105k81a?c)(?: bui|\))/i,
|
|
569
|
-
/\b((?:red)?mi[-_ ]?pad[\w- ]*)(?: bui|\))/i
|
|
598
|
+
/\b(?:xiao)?((?:red)?mi[-_ ]?pad[\w- ]*)(?: bui|\))/i // Mi Pad tablets
|
|
570
599
|
],[[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, TABLET]], [
|
|
571
600
|
|
|
572
601
|
/\b(poco[\w ]+|m2\d{3}j\d\d[a-z]{2})(?: bui|\))/i, // Xiaomi POCO
|
|
@@ -574,20 +603,26 @@
|
|
|
574
603
|
/\b(hm[-_ ]?note?[_ ]?(?:\d\w)?) bui/i, // Xiaomi Hongmi
|
|
575
604
|
/\b(redmi[\-_ ]?(?:note|k)?[\w_ ]+)(?: bui|\))/i, // Xiaomi Redmi
|
|
576
605
|
/oid[^\)]+; (m?[12][0-389][01]\w{3,6}[c-y])( bui|; wv|\))/i, // Xiaomi Redmi 'numeric' models
|
|
577
|
-
/\b(mi[-_ ]?(?:a\d|one|one[_ ]plus|note
|
|
606
|
+
/\b(mi[-_ ]?(?:a\d|one|one[_ ]plus|note|max|cc)?[_ ]?(?:\d{0,2}\w?)[_ ]?(?:plus|se|lite|pro)?( 5g|lte)?)(?: bui|\))/i, // Xiaomi Mi
|
|
578
607
|
/ ([\w ]+) miui\/v?\d/i
|
|
579
608
|
], [[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, MOBILE]], [
|
|
580
609
|
|
|
610
|
+
// OnePlus
|
|
611
|
+
/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-k]\w[1m]10)\b/i,
|
|
612
|
+
/(?:one)?(?:plus)? (a\d0\d\d)(?: b|\))/i
|
|
613
|
+
], [MODEL, [VENDOR, ONEPLUS], [TYPE, MOBILE]], [
|
|
614
|
+
|
|
581
615
|
// OPPO
|
|
582
616
|
/; (\w+) bui.+ oppo/i,
|
|
583
617
|
/\b(cph[12]\d{3}|p(?:af|c[al]|d\w|e[ar])[mt]\d0|x9007|a101op)\b/i
|
|
584
618
|
], [MODEL, [VENDOR, OPPO], [TYPE, MOBILE]], [
|
|
585
619
|
/\b(opd2(\d{3}a?))(?: bui|\))/i
|
|
586
|
-
], [MODEL, [VENDOR, strMapper, { 'OnePlus' : ['304', '403', '
|
|
620
|
+
], [MODEL, [VENDOR, strMapper, { 'OnePlus' : ['203', '304', '403', '404', '413', '415'], '*' : OPPO }], [TYPE, TABLET]], [
|
|
621
|
+
|
|
622
|
+
// BLU
|
|
623
|
+
/(vivo (5r?|6|8l?|go|one|s|x[il]?[2-4]?)[\w\+ ]*)(?: bui|\))/i // Vivo series
|
|
624
|
+
], [MODEL, [VENDOR, 'BLU'], [TYPE, MOBILE]], [
|
|
587
625
|
|
|
588
|
-
// BLU Vivo Series
|
|
589
|
-
/(vivo (5r?|6|8l?|go|one|s|x[il]?[2-4]?)[\w\+ ]*)(?: bui|\))/i
|
|
590
|
-
], [MODEL, [VENDOR, 'BLU'], [TYPE, MOBILE]], [
|
|
591
626
|
// Vivo
|
|
592
627
|
/; vivo (\w+)(?: bui|\))/i,
|
|
593
628
|
/\b(v[12]\d{3}\w?[at])(?: bui|;)/i
|
|
@@ -597,10 +632,17 @@
|
|
|
597
632
|
/\b(rmx[1-3]\d{3})(?: bui|;|\))/i
|
|
598
633
|
], [MODEL, [VENDOR, 'Realme'], [TYPE, MOBILE]], [
|
|
599
634
|
|
|
635
|
+
// Lenovo
|
|
636
|
+
/(ideatab[-\w ]+|602lv|d-42a|a101lv|a2109a|a3500-hv|s[56]000|pb-6505[my]|tb-?x?\d{3,4}(?:f[cu]|xu|[av])|yt\d?-[jx]?\d+[lfmx])( bui|;|\)|\/)/i,
|
|
637
|
+
/lenovo ?(b[68]0[08]0-?[hf]?|tab(?:[\w- ]+?)|tb[\w-]{6,7})( bui|;|\)|\/)/i
|
|
638
|
+
], [MODEL, [VENDOR, LENOVO], [TYPE, TABLET]], [
|
|
639
|
+
/lenovo[-_ ]?([-\w ]+?)(?: bui|\)|\/)/i
|
|
640
|
+
], [MODEL, [VENDOR, LENOVO], [TYPE, MOBILE]], [
|
|
641
|
+
|
|
600
642
|
// Motorola
|
|
601
643
|
/\b(milestone|droid(?:[2-4x]| (?:bionic|x2|pro|razr))?:?( 4g)?)\b[\w ]+build\//i,
|
|
602
|
-
/\bmot(?:orola)?[- ](\w
|
|
603
|
-
/((?:moto(?! 360)[
|
|
644
|
+
/\bmot(?:orola)?[- ]([\w\s]+)(\)| bui)/i,
|
|
645
|
+
/((?:moto(?! 360)[-\w\(\) ]+|xt\d{3,4}[cgkosw\+]?[-\d]*|nexus 6)(?= bui|\)))/i
|
|
604
646
|
], [MODEL, [VENDOR, MOTOROLA], [TYPE, MOBILE]], [
|
|
605
647
|
/\b(mz60\d|xoom[2 ]{0,2}) build\//i
|
|
606
648
|
], [MODEL, [VENDOR, MOTOROLA], [TYPE, TABLET]], [
|
|
@@ -609,40 +651,33 @@
|
|
|
609
651
|
/((?=lg)?[vl]k\-?\d{3}) bui| 3\.[-\w; ]{10}lg?-([06cv9]{3,4})/i
|
|
610
652
|
], [MODEL, [VENDOR, LG], [TYPE, TABLET]], [
|
|
611
653
|
/(lm(?:-?f100[nv]?|-[\w\.]+)(?= bui|\))|nexus [45])/i,
|
|
612
|
-
/\blg[-e;\/ ]+(?!.*(?:browser|netcast|android tv|watch))(\w+)/i,
|
|
654
|
+
/\blg[-e;\/ ]+(?!.*(?:browser|netcast|android tv|watch|webos))(\w+)/i,
|
|
613
655
|
/\blg-?([\d\w]+) bui/i
|
|
614
656
|
], [MODEL, [VENDOR, LG], [TYPE, MOBILE]], [
|
|
615
657
|
|
|
616
|
-
// Lenovo
|
|
617
|
-
/(ideatab[-\w ]+|602lv|d-42a|a101lv|a2109a|a3500-hv|s[56]000|pb-6505[my]|tb-?x?\d{3,4}(?:f[cu]|xu|[av])|yt\d?-[jx]?\d+[lfmx])( bui|;|\)|\/)/i,
|
|
618
|
-
/lenovo ?(b[68]0[08]0-?[hf]?|tab(?:[\w- ]+?)|tb[\w-]{6,7})( bui|;|\)|\/)/i
|
|
619
|
-
], [MODEL, [VENDOR, LENOVO], [TYPE, TABLET]], [
|
|
620
|
-
|
|
621
658
|
// Nokia
|
|
622
659
|
/(nokia) (t[12][01])/i
|
|
623
660
|
], [VENDOR, MODEL, [TYPE, TABLET]], [
|
|
624
661
|
/(?:maemo|nokia).*(n900|lumia \d+|rm-\d+)/i,
|
|
625
|
-
/nokia[-_ ]?(([-\w\. ]
|
|
662
|
+
/nokia[-_ ]?(([-\w\. ]*?))( bui|\)|;|\/)/i
|
|
626
663
|
], [[MODEL, /_/g, ' '], [TYPE, MOBILE], [VENDOR, 'Nokia']], [
|
|
627
664
|
|
|
628
665
|
// Google
|
|
629
666
|
/(pixel (c|tablet))\b/i // Google Pixel C/Tablet
|
|
630
667
|
], [MODEL, [VENDOR, GOOGLE], [TYPE, TABLET]], [
|
|
631
|
-
|
|
668
|
+
// Google Pixel
|
|
669
|
+
/droid.+;(?: google)? (g(01[13]a|020[aem]|025[jn]|1b60|1f8f|2ybb|4s1m|576d|5nz6|8hhn|8vou|a02099|c15s|d1yq|e2ae|ec77|gh2x|kv4x|p4bc|pj41|r83y|tt9q|ur25|wvk6)|pixel[\d ]*a?( pro)?( xl)?( fold)?( \(5g\))?)( bui|\))/i
|
|
632
670
|
], [MODEL, [VENDOR, GOOGLE], [TYPE, MOBILE]], [
|
|
671
|
+
/(google) (pixelbook( go)?)/i
|
|
672
|
+
], [VENDOR, MODEL], [
|
|
633
673
|
|
|
634
674
|
// Sony
|
|
635
|
-
/droid.+; (a?\d[0-2]{2}so|[c-g]\d{4}|so[-gl]\w+|xq
|
|
675
|
+
/droid.+; (a?\d[0-2]{2}so|[c-g]\d{4}|so[-gl]\w+|xq-\w\w\d\d)(?= bui|\).+chrome\/(?![1-6]{0,1}\d\.))/i
|
|
636
676
|
], [MODEL, [VENDOR, SONY], [TYPE, MOBILE]], [
|
|
637
677
|
/sony tablet [ps]/i,
|
|
638
678
|
/\b(?:sony)?sgp\w+(?: bui|\))/i
|
|
639
679
|
], [[MODEL, 'Xperia Tablet'], [VENDOR, SONY], [TYPE, TABLET]], [
|
|
640
680
|
|
|
641
|
-
// OnePlus
|
|
642
|
-
/ (kb2005|in20[12]5|be20[12][59])\b/i,
|
|
643
|
-
/(?:one)?(?:plus)? (a\d0\d\d)(?: b|\))/i
|
|
644
|
-
], [MODEL, [VENDOR, ONEPLUS], [TYPE, MOBILE]], [
|
|
645
|
-
|
|
646
681
|
// Amazon
|
|
647
682
|
/(alexa)webm/i,
|
|
648
683
|
/(kf[a-z]{2}wi|aeo(?!bc)\w\w)( bui|\))/i, // Kindle Fire without Silk / Echo Show
|
|
@@ -655,7 +690,7 @@
|
|
|
655
690
|
/(playbook);[-\w\),; ]+(rim)/i // BlackBerry PlayBook
|
|
656
691
|
], [MODEL, VENDOR, [TYPE, TABLET]], [
|
|
657
692
|
/\b((?:bb[a-f]|st[hv])100-\d)/i,
|
|
658
|
-
|
|
693
|
+
/(?:blackberry|\(bb10;) (\w+)/i
|
|
659
694
|
], [MODEL, [VENDOR, BLACKBERRY], [TYPE, MOBILE]], [
|
|
660
695
|
|
|
661
696
|
// Asus
|
|
@@ -713,7 +748,7 @@
|
|
|
713
748
|
], [MODEL, [VENDOR, 'Smartfren'], [TYPE, MOBILE]], [
|
|
714
749
|
|
|
715
750
|
// Nothing
|
|
716
|
-
/droid.+; (a(
|
|
751
|
+
/droid.+; (a(in)?(0(15|59|6[35])|142)p?)/i
|
|
717
752
|
], [MODEL, [VENDOR, 'Nothing'], [TYPE, MOBILE]], [
|
|
718
753
|
|
|
719
754
|
// Archos
|
|
@@ -724,18 +759,24 @@
|
|
|
724
759
|
/; (ac[3-6]\d\w{2,8})( b|\))/i
|
|
725
760
|
], [MODEL, [VENDOR, 'Archos'], [TYPE, MOBILE]], [
|
|
726
761
|
|
|
762
|
+
// HMD
|
|
763
|
+
/; (n159v)/i
|
|
764
|
+
], [MODEL, [VENDOR, 'HMD'], [TYPE, MOBILE]], [
|
|
765
|
+
|
|
727
766
|
// MIXED
|
|
728
767
|
/(imo) (tab \w+)/i, // IMO
|
|
729
|
-
/(infinix) (x1101b
|
|
768
|
+
/(infinix|tecno) (x1101b?|p904|dp(7c|8d|10a)( pro)?|p70[1-3]a?|p904|t1101)/i // Infinix XPad / Tecno
|
|
730
769
|
], [VENDOR, MODEL, [TYPE, TABLET]], [
|
|
731
770
|
|
|
732
|
-
/(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus(?! zenw)|dell|jolla|meizu|motorola|polytron|
|
|
733
|
-
// BlackBerry/BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron/
|
|
734
|
-
|
|
771
|
+
/(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus(?! zenw)|dell|jolla|meizu|motorola|polytron|tecno|micromax|advan)[-_ ]?([-\w]*)/i,
|
|
772
|
+
// BlackBerry/BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron/Tecno/Micromax/Advan
|
|
773
|
+
// BLU/HMD/IMO/Infinix/Lava/OnePlus/TCL/Wiko
|
|
774
|
+
/; (blu|hmd|imo|infinix|lava|oneplus|tcl|wiko)[_ ]([\w\+ ]+?)(?: bui|\)|; r)/i,
|
|
735
775
|
/(hp) ([\w ]+\w)/i, // HP iPAQ
|
|
736
776
|
/(microsoft); (lumia[\w ]+)/i, // Microsoft Lumia
|
|
737
|
-
/(
|
|
738
|
-
/(
|
|
777
|
+
/(oppo) ?([\w ]+) bui/i, // OPPO
|
|
778
|
+
/(hisense) ([ehv][\w ]+)\)/i, // Hisense
|
|
779
|
+
/droid[^;]+; (philips)[_ ]([sv-x][\d]{3,4}[xz]?)/i // Philips
|
|
739
780
|
], [VENDOR, MODEL, [TYPE, MOBILE]], [
|
|
740
781
|
|
|
741
782
|
/(kobo)\s(ereader|touch)/i, // Kobo
|
|
@@ -762,10 +803,12 @@
|
|
|
762
803
|
// SMARTTVS
|
|
763
804
|
///////////////////
|
|
764
805
|
|
|
806
|
+
/(philips)[\w ]+tv/i, // Philips
|
|
765
807
|
/smart-tv.+(samsung)/i // Samsung
|
|
766
808
|
], [VENDOR, [TYPE, SMARTTV]], [
|
|
767
809
|
/hbbtv.+maple;(\d+)/i
|
|
768
810
|
], [[MODEL, /^/, 'SmartTV'], [VENDOR, SAMSUNG], [TYPE, SMARTTV]], [
|
|
811
|
+
/(vizio)(?: |.+model\/)(\w+-\w+)/i, // Vizio
|
|
769
812
|
/tcast.+(lg)e?. ([-\w]+)/i // LG SmartTV
|
|
770
813
|
], [VENDOR, MODEL, [TYPE, SMARTTV]], [
|
|
771
814
|
/(nux; netcast.+smarttv|lg (netcast\.tv-201\d|android tv))/i
|
|
@@ -797,26 +840,22 @@
|
|
|
797
840
|
], [VENDOR, MODEL, [TYPE, SMARTTV]], [
|
|
798
841
|
/\b(roku)[\dx]*[\)\/]((?:dvp-)?[\d\.]*)/i, // Roku
|
|
799
842
|
/hbbtv\/\d+\.\d+\.\d+ +\([\w\+ ]*; *([\w\d][^;]*);([^;]*)/i // HbbTV devices
|
|
800
|
-
], [[VENDOR,
|
|
801
|
-
// SmartTV from Unidentified Vendors
|
|
802
|
-
/droid.+; ([\w- ]+) (?:android tv|smart[- ]?tv)/i
|
|
803
|
-
], [MODEL, [TYPE, SMARTTV]], [
|
|
804
|
-
/\b(android tv|smart[- ]?tv|opera tv|tv; rv:)\b/i
|
|
805
|
-
], [[TYPE, SMARTTV]], [
|
|
843
|
+
], [[VENDOR, /.+\/(\w+)/, '$1', strMapper, {'LG':'lge'}], [MODEL, trim], [TYPE, SMARTTV]], [
|
|
806
844
|
|
|
807
845
|
///////////////////
|
|
808
846
|
// CONSOLES
|
|
809
847
|
///////////////////
|
|
810
848
|
|
|
811
|
-
/(ouya)/i, // Ouya
|
|
812
|
-
/(nintendo) (\w+)/i // Nintendo
|
|
813
|
-
], [VENDOR, MODEL, [TYPE, CONSOLE]], [
|
|
814
|
-
/droid.+; (shield)( bui|\))/i // Nvidia Portable
|
|
815
|
-
], [MODEL, [VENDOR, NVIDIA], [TYPE, CONSOLE]], [
|
|
816
849
|
/(playstation \w+)/i // Playstation
|
|
817
850
|
], [MODEL, [VENDOR, SONY], [TYPE, CONSOLE]], [
|
|
818
851
|
/\b(xbox(?: one)?(?!; xbox))[\); ]/i // Microsoft Xbox
|
|
819
852
|
], [MODEL, [VENDOR, MICROSOFT], [TYPE, CONSOLE]], [
|
|
853
|
+
/(ouya)/i, // Ouya
|
|
854
|
+
/(nintendo) (\w+)/i, // Nintendo
|
|
855
|
+
/(retroid) (pocket ([^\)]+))/i // Retroid Pocket
|
|
856
|
+
], [VENDOR, MODEL, [TYPE, CONSOLE]], [
|
|
857
|
+
/droid.+; (shield)( bui|\))/i // Nvidia Portable
|
|
858
|
+
], [MODEL, [VENDOR, NVIDIA], [TYPE, CONSOLE]], [
|
|
820
859
|
|
|
821
860
|
///////////////////
|
|
822
861
|
// WEARABLES
|
|
@@ -848,10 +887,12 @@
|
|
|
848
887
|
|
|
849
888
|
/droid.+; (glass) \d/i // Google Glass
|
|
850
889
|
], [MODEL, [VENDOR, GOOGLE], [TYPE, XR]], [
|
|
851
|
-
/(pico) (
|
|
890
|
+
/(pico) ([\w ]+) os\d/i // Pico
|
|
852
891
|
], [VENDOR, MODEL, [TYPE, XR]], [
|
|
853
892
|
/(quest( \d| pro)?s?).+vr/i // Meta Quest
|
|
854
893
|
], [MODEL, [VENDOR, FACEBOOK], [TYPE, XR]], [
|
|
894
|
+
/mobile vr; rv.+firefox/i // Unidentifiable VR device using Firefox Reality / Wolvic
|
|
895
|
+
], [[TYPE, XR]], [
|
|
855
896
|
|
|
856
897
|
///////////////////
|
|
857
898
|
// EMBEDDED
|
|
@@ -863,14 +904,18 @@
|
|
|
863
904
|
], [MODEL, [VENDOR, AMAZON], [TYPE, EMBEDDED]], [
|
|
864
905
|
/(homepod).+mac os/i // Apple HomePod
|
|
865
906
|
], [MODEL, [VENDOR, APPLE], [TYPE, EMBEDDED]], [
|
|
866
|
-
/windows iot/i
|
|
907
|
+
/windows iot/i // Unidentifiable embedded device using Windows IoT
|
|
867
908
|
], [[TYPE, EMBEDDED]], [
|
|
868
909
|
|
|
869
910
|
////////////////////
|
|
870
911
|
// MIXED (GENERIC)
|
|
871
912
|
///////////////////
|
|
872
913
|
|
|
873
|
-
/droid
|
|
914
|
+
/droid.+; ([\w- ]+) (4k|android|smart|google)[- ]?tv/i // Unidentifiable SmartTV
|
|
915
|
+
], [MODEL, [TYPE, SMARTTV]], [
|
|
916
|
+
/\b((4k|android|smart|opera)[- ]?tv|tv; rv:|large screen[\w ]+safari)\b/i
|
|
917
|
+
], [[TYPE, SMARTTV]], [
|
|
918
|
+
/droid .+?; ([^;]+?)(?: bui|; wv\)|\) applew|; hmsc).+?(mobile|vr|\d) safari/i
|
|
874
919
|
], [MODEL, [TYPE, strMapper, { 'mobile' : 'Mobile', 'xr' : 'VR', '*' : TABLET }]], [
|
|
875
920
|
/\b((tablet|tab)[;\/]|focus\/\d(?!.+mobile))/i // Unidentifiable Tablet
|
|
876
921
|
], [[TYPE, TABLET]], [
|
|
@@ -909,22 +954,25 @@
|
|
|
909
954
|
os : [[
|
|
910
955
|
|
|
911
956
|
// Windows
|
|
912
|
-
/
|
|
957
|
+
/(windows nt) (6\.[23]); arm/i // Windows RT
|
|
958
|
+
], [[NAME, /N/, 'R'], [VERSION, strMapper, windowsVersionMap]], [
|
|
959
|
+
/(windows (?:phone|mobile|iot))(?: os)?[\/ ]?([\d\.]*( se)?)/i, // Windows IoT/Mobile/Phone
|
|
960
|
+
// Windows NT/3.1/95/98/ME/2000/XP/Vista/7/8/8.1/10/11
|
|
961
|
+
/(windows)[\/ ](1[01]|2000|3\.1|7|8(\.1)?|9[58]|me|server 20\d\d( r2)?|vista|xp)/i
|
|
962
|
+
], [NAME, VERSION], [
|
|
963
|
+
/windows nt ?([\d\.\)]*)(?!.+xbox)/i,
|
|
964
|
+
/\bwin(?=3| ?9|n)(?:nt| 9x )?([\d\.;]*)/i
|
|
965
|
+
], [[VERSION, /(;|\))/g, '', strMapper, windowsVersionMap], [NAME, WINDOWS]], [
|
|
966
|
+
/(windows ce)\/?([\d\.]*)/i // Windows CE
|
|
913
967
|
], [NAME, VERSION], [
|
|
914
|
-
/(windows (?:phone(?: os)?|mobile|iot))[\/ ]?([\d\.\w ]*)/i // Windows Phone
|
|
915
|
-
], [NAME, [VERSION, strMapper, windowsVersionMap]], [
|
|
916
|
-
/windows nt 6\.2; (arm)/i, // Windows RT
|
|
917
|
-
/windows[\/ ]([ntce\d\. ]+\w)(?!.+xbox)/i,
|
|
918
|
-
/(?:win(?=3|9|n)|win 9x )([nt\d\.]+)/i
|
|
919
|
-
], [[VERSION, strMapper, windowsVersionMap], [NAME, WINDOWS]], [
|
|
920
968
|
|
|
921
969
|
// iOS/macOS
|
|
922
970
|
/[adehimnop]{4,7}\b(?:.*os ([\w]+) like mac|; opera)/i, // iOS
|
|
923
|
-
/(?:ios;fbsv
|
|
971
|
+
/(?:ios;fbsv|ios(?=.+ip(?:ad|hone))|ip(?:ad|hone)(?: |.+i(?:pad)?)os)[\/ ]([\w\.]+)/i,
|
|
924
972
|
/cfnetwork\/.+darwin/i
|
|
925
973
|
], [[VERSION, /_/g, '.'], [NAME, 'iOS']], [
|
|
926
974
|
/(mac os x) ?([\w\. ]*)/i,
|
|
927
|
-
/(macintosh|mac_powerpc\b)(?!.+haiku)/i
|
|
975
|
+
/(macintosh|mac_powerpc\b)(?!.+(haiku|morphos))/i // Mac OS
|
|
928
976
|
], [[NAME, 'macOS'], [VERSION, /_/g, '.']], [
|
|
929
977
|
|
|
930
978
|
// Google Chromecast
|
|
@@ -940,12 +988,13 @@
|
|
|
940
988
|
], [VERSION, [NAME, CHROMECAST]], [
|
|
941
989
|
|
|
942
990
|
// Mobile OSes
|
|
943
|
-
/droid ([\w\.]+)\b.+(android[- ]x86
|
|
991
|
+
/droid ([\w\.]+)\b.+(android[- ]x86)/i // Android-x86
|
|
944
992
|
], [VERSION, NAME], [
|
|
945
993
|
/(ubuntu) ([\w\.]+) like android/i // Ubuntu Touch
|
|
946
994
|
], [[NAME, /(.+)/, '$1 Touch'], VERSION], [
|
|
995
|
+
/(harmonyos)[\/ ]?([\d\.]*)/i, // HarmonyOS
|
|
947
996
|
// Android/Blackberry/WebOS/QNX/Bada/RIM/KaiOS/Maemo/MeeGo/S40/Sailfish OS/OpenHarmony/Tizen
|
|
948
|
-
/(android|bada|blackberry|kaios|maemo|meego|openharmony|qnx|rim tablet os|sailfish|series40|symbian|tizen
|
|
997
|
+
/(android|bada|blackberry|kaios|maemo|meego|openharmony|qnx|rim tablet os|sailfish|series40|symbian|tizen)\w*[-\/\.; ]?([\d\.]*)/i
|
|
949
998
|
], [NAME, VERSION], [
|
|
950
999
|
/\(bb(10);/i // BlackBerry 10
|
|
951
1000
|
], [VERSION, [NAME, BLACKBERRY]], [
|
|
@@ -953,9 +1002,12 @@
|
|
|
953
1002
|
], [VERSION, [NAME, 'Symbian']], [
|
|
954
1003
|
/mozilla\/[\d\.]+ \((?:mobile|tablet|tv|mobile; [\w ]+); rv:.+ gecko\/([\w\.]+)/i // Firefox OS
|
|
955
1004
|
], [VERSION, [NAME, FIREFOX+' OS']], [
|
|
956
|
-
|
|
957
|
-
|
|
1005
|
+
/\b(?:hp)?wos(?:browser)?\/([\w\.]+)/i, // WebOS
|
|
1006
|
+
/webos(?:[ \/]?|\.tv-20(?=2[2-9]))(\d[\d\.]*)/i
|
|
958
1007
|
], [VERSION, [NAME, 'webOS']], [
|
|
1008
|
+
/web0s;.+?(?:chr[o0]me|safari)\/(\d+)/i
|
|
1009
|
+
// https://webostv.developer.lge.com/develop/specifications/web-api-and-web-engine
|
|
1010
|
+
], [[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']], [
|
|
959
1011
|
/watch(?: ?os[,\/]|\d,\d\/)([\d\.]+)/i // watchOS
|
|
960
1012
|
], [VERSION, [NAME, 'watchOS']], [
|
|
961
1013
|
|
|
@@ -975,20 +1027,20 @@
|
|
|
975
1027
|
|
|
976
1028
|
// Other
|
|
977
1029
|
/\b(joli|palm)\b ?(?:os)?\/?([\w\.]*)/i, // Joli/Palm
|
|
978
|
-
/(mint)[\/\(\) ]?(\w*)/i,
|
|
979
|
-
/(mageia|vectorlinux)[; ]/i,
|
|
980
|
-
/([kxln]?ubuntu|debian|suse|opensuse|gentoo|
|
|
981
|
-
// Ubuntu/Debian/SUSE/Gentoo/
|
|
982
|
-
/(
|
|
1030
|
+
/linux.+(mint)[\/\(\) ]?([\w\.]*)/i, // Mint
|
|
1031
|
+
/(mageia|vectorlinux|fuchsia|arcaos|arch(?= ?linux))[;l ]([\d\.]*)/i, // Mageia/VectorLinux/Fuchsia/ArcaOS/Arch
|
|
1032
|
+
/([kxln]?ubuntu|debian|suse|opensuse|gentoo|slackware|fedora|mandriva|centos|pclinuxos|red ?hat|zenwalk|linpus|raspbian|plan 9|minix|risc os|contiki|deepin|manjaro|elementary os|sabayon|linspire|knoppix)(?: gnu[\/ ]linux)?(?: enterprise)?(?:[- ]linux)?(?:-gnu)?[-\/ ]?(?!chrom|package)([-\w\.]*)/i,
|
|
1033
|
+
// Ubuntu/Debian/SUSE/Gentoo/Slackware/Fedora/Mandriva/CentOS/PCLinuxOS/RedHat/Zenwalk/Linpus/Raspbian/Plan9/Minix/RISCOS/Contiki/Deepin/Manjaro/elementary/Sabayon/Linspire/Knoppix
|
|
1034
|
+
/((?:open)?solaris)[-\/ ]?([\w\.]*)/i, // Solaris
|
|
1035
|
+
/\b(aix)[; ]([1-9\.]{0,4})/i, // AIX
|
|
1036
|
+
/(hurd|linux|morphos)(?: (?:arm|x86|ppc)\w*| ?)([\w\.]*)/i, // Hurd/Linux/MorphOS
|
|
983
1037
|
/(gnu) ?([\w\.]*)/i, // GNU
|
|
984
1038
|
/\b([-frentopcghs]{0,5}bsd|dragonfly)[\/ ]?(?!amd|[ix346]{1,2}86)([\w\.]*)/i, // FreeBSD/NetBSD/OpenBSD/PC-BSD/GhostBSD/DragonFly
|
|
985
|
-
/(haiku) (\
|
|
1039
|
+
/(haiku) ?(r\d)?/i // Haiku
|
|
986
1040
|
], [NAME, VERSION], [
|
|
987
|
-
/(sunos) ?([\
|
|
1041
|
+
/(sunos) ?([\d\.]*)/i // Solaris
|
|
988
1042
|
], [[NAME, 'Solaris'], VERSION], [
|
|
989
|
-
|
|
990
|
-
/(aix) ((\d)(?=\.|\)| )[\w\.])*/i, // AIX
|
|
991
|
-
/\b(beos|os\/2|amigaos|morphos|openvms|fuchsia|hp-ux|serenityos)/i, // BeOS/OS2/AmigaOS/MorphOS/OpenVMS/Fuchsia/HP-UX/SerenityOS
|
|
1043
|
+
/\b(beos|os\/2|amigaos|openvms|hp-ux|serenityos)/i, // BeOS/OS2/AmigaOS/OpenVMS/HP-UX/SerenityOS
|
|
992
1044
|
/(unix) ?([\w\.]*)/i // UNIX
|
|
993
1045
|
], [NAME, VERSION]
|
|
994
1046
|
]
|
|
@@ -1001,27 +1053,27 @@
|
|
|
1001
1053
|
var defaultProps = (function () {
|
|
1002
1054
|
var props = { init : {}, isIgnore : {}, isIgnoreRgx : {}, toString : {}};
|
|
1003
1055
|
setProps.call(props.init, [
|
|
1004
|
-
[
|
|
1005
|
-
[
|
|
1006
|
-
[
|
|
1007
|
-
[
|
|
1008
|
-
[
|
|
1056
|
+
[BROWSER, [NAME, VERSION, MAJOR, TYPE]],
|
|
1057
|
+
[CPU, [ARCHITECTURE]],
|
|
1058
|
+
[DEVICE, [TYPE, MODEL, VENDOR]],
|
|
1059
|
+
[ENGINE, [NAME, VERSION]],
|
|
1060
|
+
[OS, [NAME, VERSION]]
|
|
1009
1061
|
]);
|
|
1010
1062
|
setProps.call(props.isIgnore, [
|
|
1011
|
-
[
|
|
1012
|
-
[
|
|
1013
|
-
[
|
|
1063
|
+
[BROWSER, [VERSION, MAJOR]],
|
|
1064
|
+
[ENGINE, [VERSION]],
|
|
1065
|
+
[OS, [VERSION]]
|
|
1014
1066
|
]);
|
|
1015
1067
|
setProps.call(props.isIgnoreRgx, [
|
|
1016
|
-
[
|
|
1017
|
-
[
|
|
1068
|
+
[BROWSER, / ?browser$/i],
|
|
1069
|
+
[OS, / ?os$/i]
|
|
1018
1070
|
]);
|
|
1019
1071
|
setProps.call(props.toString, [
|
|
1020
|
-
[
|
|
1021
|
-
[
|
|
1022
|
-
[
|
|
1023
|
-
[
|
|
1024
|
-
[
|
|
1072
|
+
[BROWSER, [NAME, VERSION]],
|
|
1073
|
+
[CPU, [ARCHITECTURE]],
|
|
1074
|
+
[DEVICE, [VENDOR, MODEL]],
|
|
1075
|
+
[ENGINE, [NAME, VERSION]],
|
|
1076
|
+
[OS, [NAME, VERSION]]
|
|
1025
1077
|
]);
|
|
1026
1078
|
return props;
|
|
1027
1079
|
})();
|
|
@@ -1065,14 +1117,14 @@
|
|
|
1065
1117
|
return item.detectFeature().get();
|
|
1066
1118
|
};
|
|
1067
1119
|
|
|
1068
|
-
if (itemType !=
|
|
1120
|
+
if (itemType != RESULT) {
|
|
1069
1121
|
IData.prototype.is = function (strToCheck) {
|
|
1070
1122
|
var is = false;
|
|
1071
1123
|
for (var i in this) {
|
|
1072
1124
|
if (this.hasOwnProperty(i) && !has(is_ignoreProps, i) && lowerize(is_ignoreRgx ? strip(is_ignoreRgx, this[i]) : this[i]) == lowerize(is_ignoreRgx ? strip(is_ignoreRgx, strToCheck) : strToCheck)) {
|
|
1073
1125
|
is = true;
|
|
1074
|
-
if (strToCheck !=
|
|
1075
|
-
} else if (strToCheck ==
|
|
1126
|
+
if (strToCheck != TYPEOF.UNDEFINED) break;
|
|
1127
|
+
} else if (strToCheck == TYPEOF.UNDEFINED && is) {
|
|
1076
1128
|
is = !is;
|
|
1077
1129
|
break;
|
|
1078
1130
|
}
|
|
@@ -1082,11 +1134,11 @@
|
|
|
1082
1134
|
IData.prototype.toString = function () {
|
|
1083
1135
|
var str = EMPTY;
|
|
1084
1136
|
for (var i in toString_props) {
|
|
1085
|
-
if (typeof(this[toString_props[i]]) !==
|
|
1137
|
+
if (typeof(this[toString_props[i]]) !== TYPEOF.UNDEFINED) {
|
|
1086
1138
|
str += (str ? ' ' : EMPTY) + this[toString_props[i]];
|
|
1087
1139
|
}
|
|
1088
1140
|
}
|
|
1089
|
-
return str ||
|
|
1141
|
+
return str || TYPEOF.UNDEFINED;
|
|
1090
1142
|
};
|
|
1091
1143
|
}
|
|
1092
1144
|
|
|
@@ -1122,19 +1174,19 @@
|
|
|
1122
1174
|
setProps.call(this, CH_ALL_VALUES);
|
|
1123
1175
|
if (isHttpUACH) {
|
|
1124
1176
|
setProps.call(this, [
|
|
1125
|
-
[BRANDS, itemListToArray(uach[
|
|
1126
|
-
[FULLVERLIST, itemListToArray(uach[
|
|
1127
|
-
[MOBILE, /\?1/.test(uach[
|
|
1128
|
-
[MODEL, stripQuotes(uach[
|
|
1129
|
-
[PLATFORM, stripQuotes(uach[
|
|
1130
|
-
[PLATFORMVER, stripQuotes(uach[
|
|
1131
|
-
[ARCHITECTURE, stripQuotes(uach[
|
|
1132
|
-
[FORMFACTORS, itemListToArray(uach[
|
|
1133
|
-
[BITNESS, stripQuotes(uach[
|
|
1177
|
+
[BRANDS, itemListToArray(uach[CH])],
|
|
1178
|
+
[FULLVERLIST, itemListToArray(uach[CH_FULL_VER_LIST])],
|
|
1179
|
+
[MOBILE, /\?1/.test(uach[CH_MOBILE])],
|
|
1180
|
+
[MODEL, stripQuotes(uach[CH_MODEL])],
|
|
1181
|
+
[PLATFORM, stripQuotes(uach[CH_PLATFORM])],
|
|
1182
|
+
[PLATFORMVER, stripQuotes(uach[CH_PLATFORM_VER])],
|
|
1183
|
+
[ARCHITECTURE, stripQuotes(uach[CH_ARCH])],
|
|
1184
|
+
[FORMFACTORS, itemListToArray(uach[CH_FORM_FACTORS])],
|
|
1185
|
+
[BITNESS, stripQuotes(uach[CH_BITNESS])]
|
|
1134
1186
|
]);
|
|
1135
1187
|
} else {
|
|
1136
1188
|
for (var prop in uach) {
|
|
1137
|
-
if(this.hasOwnProperty(prop) && typeof uach[prop] !==
|
|
1189
|
+
if(this.hasOwnProperty(prop) && typeof uach[prop] !== TYPEOF.UNDEFINED) this[prop] = uach[prop];
|
|
1138
1190
|
}
|
|
1139
1191
|
}
|
|
1140
1192
|
}
|
|
@@ -1159,30 +1211,30 @@
|
|
|
1159
1211
|
this.detectFeature = function () {
|
|
1160
1212
|
if (NAVIGATOR && NAVIGATOR.userAgent == this.ua) {
|
|
1161
1213
|
switch (this.itemType) {
|
|
1162
|
-
case
|
|
1214
|
+
case BROWSER:
|
|
1163
1215
|
// Brave-specific detection
|
|
1164
|
-
if (NAVIGATOR.brave && typeof NAVIGATOR.brave.isBrave ==
|
|
1216
|
+
if (NAVIGATOR.brave && typeof NAVIGATOR.brave.isBrave == TYPEOF.FUNCTION) {
|
|
1165
1217
|
this.set(NAME, 'Brave');
|
|
1166
1218
|
}
|
|
1167
1219
|
break;
|
|
1168
|
-
case
|
|
1220
|
+
case DEVICE:
|
|
1169
1221
|
// Chrome-specific detection: check for 'mobile' value of navigator.userAgentData
|
|
1170
1222
|
if (!this.get(TYPE) && NAVIGATOR_UADATA && NAVIGATOR_UADATA[MOBILE]) {
|
|
1171
1223
|
this.set(TYPE, MOBILE);
|
|
1172
1224
|
}
|
|
1173
1225
|
// iPadOS-specific detection: identified as Mac, but has some iOS-only properties
|
|
1174
|
-
if (this.get(MODEL) == 'Macintosh' && NAVIGATOR && typeof NAVIGATOR.standalone !==
|
|
1226
|
+
if (this.get(MODEL) == 'Macintosh' && NAVIGATOR && typeof NAVIGATOR.standalone !== TYPEOF.UNDEFINED && NAVIGATOR.maxTouchPoints && NAVIGATOR.maxTouchPoints > 2) {
|
|
1175
1227
|
this.set(MODEL, 'iPad')
|
|
1176
1228
|
.set(TYPE, TABLET);
|
|
1177
1229
|
}
|
|
1178
1230
|
break;
|
|
1179
|
-
case
|
|
1231
|
+
case OS:
|
|
1180
1232
|
// Chrome-specific detection: check for 'platform' value of navigator.userAgentData
|
|
1181
1233
|
if (!this.get(NAME) && NAVIGATOR_UADATA && NAVIGATOR_UADATA[PLATFORM]) {
|
|
1182
1234
|
this.set(NAME, NAVIGATOR_UADATA[PLATFORM]);
|
|
1183
1235
|
}
|
|
1184
1236
|
break;
|
|
1185
|
-
case
|
|
1237
|
+
case RESULT:
|
|
1186
1238
|
var data = this.data;
|
|
1187
1239
|
var detect = function (itemType) {
|
|
1188
1240
|
return data[itemType]
|
|
@@ -1190,22 +1242,33 @@
|
|
|
1190
1242
|
.detectFeature()
|
|
1191
1243
|
.get();
|
|
1192
1244
|
};
|
|
1193
|
-
this.set(
|
|
1194
|
-
.set(
|
|
1195
|
-
.set(
|
|
1196
|
-
.set(
|
|
1197
|
-
.set(
|
|
1245
|
+
this.set(BROWSER, detect(BROWSER))
|
|
1246
|
+
.set(CPU, detect(CPU))
|
|
1247
|
+
.set(DEVICE, detect(DEVICE))
|
|
1248
|
+
.set(ENGINE, detect(ENGINE))
|
|
1249
|
+
.set(OS, detect(OS));
|
|
1198
1250
|
}
|
|
1199
1251
|
}
|
|
1200
1252
|
return this;
|
|
1201
1253
|
};
|
|
1202
1254
|
|
|
1203
1255
|
this.parseUA = function () {
|
|
1204
|
-
if (this.itemType !=
|
|
1256
|
+
if (this.itemType != RESULT) {
|
|
1205
1257
|
rgxMapper.call(this.data, this.ua, this.rgxMap);
|
|
1206
1258
|
}
|
|
1207
|
-
|
|
1208
|
-
|
|
1259
|
+
switch (this.itemType) {
|
|
1260
|
+
case BROWSER:
|
|
1261
|
+
this.set(MAJOR, majorize(this.get(VERSION)));
|
|
1262
|
+
break;
|
|
1263
|
+
case OS:
|
|
1264
|
+
if (this.get(NAME) == 'iOS' && this.get(VERSION) == '18.6') {
|
|
1265
|
+
// Based on the assumption that iOS version is tightly coupled with Safari version
|
|
1266
|
+
var realVersion = /\) Version\/([\d\.]+)/.exec(this.ua); // Get Safari version
|
|
1267
|
+
if (realVersion && parseInt(realVersion[1].substring(0,2), 10) >= 26) {
|
|
1268
|
+
this.set(VERSION, realVersion[1]); // Set as iOS version
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
break;
|
|
1209
1272
|
}
|
|
1210
1273
|
return this;
|
|
1211
1274
|
};
|
|
@@ -1215,43 +1278,42 @@
|
|
|
1215
1278
|
rgxMap = this.rgxMap;
|
|
1216
1279
|
|
|
1217
1280
|
switch (this.itemType) {
|
|
1218
|
-
case
|
|
1219
|
-
case
|
|
1281
|
+
case BROWSER:
|
|
1282
|
+
case ENGINE:
|
|
1220
1283
|
var brands = uaCH[FULLVERLIST] || uaCH[BRANDS], prevName;
|
|
1221
1284
|
if (brands) {
|
|
1222
|
-
for (var i
|
|
1285
|
+
for (var i=0; i<brands.length; i++) {
|
|
1223
1286
|
var brandName = brands[i].brand || brands[i],
|
|
1224
1287
|
brandVersion = brands[i].version;
|
|
1225
|
-
if (this.itemType ==
|
|
1226
|
-
brandName
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
prevName = brandName;
|
|
1288
|
+
if (this.itemType == BROWSER &&
|
|
1289
|
+
!/not.a.brand/i.test(brandName) &&
|
|
1290
|
+
(!prevName ||
|
|
1291
|
+
(/Chrom/.test(prevName) && brandName != CHROMIUM) ||
|
|
1292
|
+
(prevName == EDGE && /WebView2/.test(brandName))
|
|
1293
|
+
)) {
|
|
1294
|
+
brandName = strMapper(brandName, browserHintsMap);
|
|
1295
|
+
prevName = this.get(NAME);
|
|
1296
|
+
if (!(prevName && !/Chrom/.test(prevName) && /Chrom/.test(brandName))) {
|
|
1297
|
+
this.set(NAME, brandName)
|
|
1298
|
+
.set(VERSION, brandVersion)
|
|
1299
|
+
.set(MAJOR, majorize(brandVersion));
|
|
1300
|
+
}
|
|
1301
|
+
prevName = brandName;
|
|
1240
1302
|
}
|
|
1241
|
-
if (this.itemType ==
|
|
1303
|
+
if (this.itemType == ENGINE && brandName == CHROMIUM) {
|
|
1242
1304
|
this.set(VERSION, brandVersion);
|
|
1243
1305
|
}
|
|
1244
1306
|
}
|
|
1245
1307
|
}
|
|
1246
1308
|
break;
|
|
1247
|
-
case
|
|
1309
|
+
case CPU:
|
|
1248
1310
|
var archName = uaCH[ARCHITECTURE];
|
|
1249
1311
|
if (archName) {
|
|
1250
1312
|
if (archName && uaCH[BITNESS] == '64') archName += '64';
|
|
1251
1313
|
rgxMapper.call(this.data, archName + ';', rgxMap);
|
|
1252
1314
|
}
|
|
1253
1315
|
break;
|
|
1254
|
-
case
|
|
1316
|
+
case DEVICE:
|
|
1255
1317
|
if (uaCH[MOBILE]) {
|
|
1256
1318
|
this.set(TYPE, MOBILE);
|
|
1257
1319
|
}
|
|
@@ -1281,7 +1343,7 @@
|
|
|
1281
1343
|
this.set(TYPE, ff);
|
|
1282
1344
|
}
|
|
1283
1345
|
break;
|
|
1284
|
-
case
|
|
1346
|
+
case OS:
|
|
1285
1347
|
var osName = uaCH[PLATFORM];
|
|
1286
1348
|
if(osName) {
|
|
1287
1349
|
var osVersion = uaCH[PLATFORMVER];
|
|
@@ -1295,7 +1357,7 @@
|
|
|
1295
1357
|
.set(VERSION, undefined);
|
|
1296
1358
|
}
|
|
1297
1359
|
break;
|
|
1298
|
-
case
|
|
1360
|
+
case RESULT:
|
|
1299
1361
|
var data = this.data;
|
|
1300
1362
|
var parse = function (itemType) {
|
|
1301
1363
|
return data[itemType]
|
|
@@ -1304,11 +1366,11 @@
|
|
|
1304
1366
|
.parseCH()
|
|
1305
1367
|
.get();
|
|
1306
1368
|
};
|
|
1307
|
-
this.set(
|
|
1308
|
-
.set(
|
|
1309
|
-
.set(
|
|
1310
|
-
.set(
|
|
1311
|
-
.set(
|
|
1369
|
+
this.set(BROWSER, parse(BROWSER))
|
|
1370
|
+
.set(CPU, parse(CPU))
|
|
1371
|
+
.set(DEVICE, parse(DEVICE))
|
|
1372
|
+
.set(ENGINE, parse(ENGINE))
|
|
1373
|
+
.set(OS, parse(OS));
|
|
1312
1374
|
}
|
|
1313
1375
|
return this;
|
|
1314
1376
|
};
|
|
@@ -1326,9 +1388,9 @@
|
|
|
1326
1388
|
|
|
1327
1389
|
function UAParser (ua, extensions, headers) {
|
|
1328
1390
|
|
|
1329
|
-
if (typeof ua ===
|
|
1391
|
+
if (typeof ua === TYPEOF.OBJECT) {
|
|
1330
1392
|
if (isExtensions(ua, true)) {
|
|
1331
|
-
if (typeof extensions ===
|
|
1393
|
+
if (typeof extensions === TYPEOF.OBJECT) {
|
|
1332
1394
|
headers = extensions; // case UAParser(extensions, headers)
|
|
1333
1395
|
}
|
|
1334
1396
|
extensions = ua; // case UAParser(extensions)
|
|
@@ -1337,23 +1399,34 @@
|
|
|
1337
1399
|
extensions = undefined;
|
|
1338
1400
|
}
|
|
1339
1401
|
ua = undefined;
|
|
1340
|
-
} else if (typeof ua ===
|
|
1402
|
+
} else if (typeof ua === TYPEOF.STRING && !isExtensions(extensions, true)) {
|
|
1341
1403
|
headers = extensions; // case UAParser(ua, headers)
|
|
1342
1404
|
extensions = undefined;
|
|
1343
1405
|
}
|
|
1344
1406
|
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1407
|
+
if (headers) {
|
|
1408
|
+
if (typeof headers.append === TYPEOF.FUNCTION) {
|
|
1409
|
+
// Convert Headers object into a plain object
|
|
1410
|
+
var kv = {};
|
|
1411
|
+
headers.forEach(function (v, k) { kv[String(k).toLowerCase()] = v; });
|
|
1412
|
+
headers = kv;
|
|
1413
|
+
} else {
|
|
1414
|
+
// Normalize headers field name into lowercase
|
|
1415
|
+
var normalized = {};
|
|
1416
|
+
for (var header in headers) {
|
|
1417
|
+
if (headers.hasOwnProperty(header)) {
|
|
1418
|
+
normalized[String(header).toLowerCase()] = headers[header];
|
|
1419
|
+
}
|
|
1420
|
+
}
|
|
1421
|
+
headers = normalized;
|
|
1422
|
+
}
|
|
1350
1423
|
}
|
|
1351
1424
|
|
|
1352
1425
|
if (!(this instanceof UAParser)) {
|
|
1353
1426
|
return new UAParser(ua, extensions, headers).getResult();
|
|
1354
1427
|
}
|
|
1355
1428
|
|
|
1356
|
-
var userAgent = typeof ua ===
|
|
1429
|
+
var userAgent = typeof ua === TYPEOF.STRING ? ua : // Passed user-agent string
|
|
1357
1430
|
(headers && headers[USER_AGENT] ? headers[USER_AGENT] : // User-Agent from passed headers
|
|
1358
1431
|
((NAVIGATOR && NAVIGATOR.userAgent) ? NAVIGATOR.userAgent : // navigator.userAgent
|
|
1359
1432
|
EMPTY)), // empty string
|
|
@@ -1364,15 +1437,15 @@
|
|
|
1364
1437
|
defaultRegexes,
|
|
1365
1438
|
|
|
1366
1439
|
createItemFunc = function (itemType) {
|
|
1367
|
-
if (itemType ==
|
|
1440
|
+
if (itemType == RESULT) {
|
|
1368
1441
|
return function () {
|
|
1369
1442
|
return new UAItem(itemType, userAgent, regexMap, httpUACH)
|
|
1370
1443
|
.set('ua', userAgent)
|
|
1371
|
-
.set(
|
|
1372
|
-
.set(
|
|
1373
|
-
.set(
|
|
1374
|
-
.set(
|
|
1375
|
-
.set(
|
|
1444
|
+
.set(BROWSER, this.getBrowser())
|
|
1445
|
+
.set(CPU, this.getCPU())
|
|
1446
|
+
.set(DEVICE, this.getDevice())
|
|
1447
|
+
.set(ENGINE, this.getEngine())
|
|
1448
|
+
.set(OS, this.getOS())
|
|
1376
1449
|
.get();
|
|
1377
1450
|
};
|
|
1378
1451
|
} else {
|
|
@@ -1386,16 +1459,15 @@
|
|
|
1386
1459
|
|
|
1387
1460
|
// public methods
|
|
1388
1461
|
setProps.call(this, [
|
|
1389
|
-
['getBrowser', createItemFunc(
|
|
1390
|
-
['getCPU', createItemFunc(
|
|
1391
|
-
['getDevice', createItemFunc(
|
|
1392
|
-
['getEngine', createItemFunc(
|
|
1393
|
-
['getOS', createItemFunc(
|
|
1394
|
-
['getResult', createItemFunc(
|
|
1462
|
+
['getBrowser', createItemFunc(BROWSER)],
|
|
1463
|
+
['getCPU', createItemFunc(CPU)],
|
|
1464
|
+
['getDevice', createItemFunc(DEVICE)],
|
|
1465
|
+
['getEngine', createItemFunc(ENGINE)],
|
|
1466
|
+
['getOS', createItemFunc(OS)],
|
|
1467
|
+
['getResult', createItemFunc(RESULT)],
|
|
1395
1468
|
['getUA', function () { return userAgent; }],
|
|
1396
1469
|
['setUA', function (ua) {
|
|
1397
|
-
if (isString(ua))
|
|
1398
|
-
userAgent = ua.length > UA_MAX_LENGTH ? trim(ua, UA_MAX_LENGTH) : ua;
|
|
1470
|
+
if (isString(ua)) userAgent = trim(ua, UA_MAX_LENGTH);
|
|
1399
1471
|
return this;
|
|
1400
1472
|
}]
|
|
1401
1473
|
])
|
|
@@ -1415,15 +1487,15 @@
|
|
|
1415
1487
|
//////////
|
|
1416
1488
|
|
|
1417
1489
|
// check js environment
|
|
1418
|
-
if (typeof exports !==
|
|
1490
|
+
if (typeof exports !== TYPEOF.UNDEFINED) {
|
|
1419
1491
|
// nodejs env
|
|
1420
|
-
if (typeof module !==
|
|
1492
|
+
if (typeof module !== TYPEOF.UNDEFINED && module.exports) {
|
|
1421
1493
|
exports = module.exports = UAParser;
|
|
1422
1494
|
}
|
|
1423
1495
|
exports.UAParser = UAParser;
|
|
1424
1496
|
} else {
|
|
1425
1497
|
// requirejs env (optional)
|
|
1426
|
-
if (typeof define ===
|
|
1498
|
+
if (typeof define === TYPEOF.FUNCTION && define.amd) {
|
|
1427
1499
|
define(function () {
|
|
1428
1500
|
return UAParser;
|
|
1429
1501
|
});
|