ua-parser-js 2.0.0-alpha.2 → 2.0.0-beta.1
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/LICENSE.md +616 -0
- package/README.md +66 -0
- package/dist/ua-parser.min.js +3 -3
- package/dist/ua-parser.pack.js +3 -3
- package/package.json +60 -35
- package/src/enums/ua-parser-enums.js +236 -0
- package/src/enums/ua-parser-enums.mjs +240 -0
- package/src/extensions/ua-parser-extensions.js +248 -0
- package/src/extensions/ua-parser-extensions.mjs +252 -0
- package/src/main/ua-parser.d.ts +104 -0
- package/src/{ua-parser.js → main/ua-parser.js} +283 -206
- package/src/{ua-parser.mjs → main/ua-parser.mjs} +284 -209
- package/license.md +0 -21
- package/readme.md +0 -603
- package/src/enum/ua-parser-enum.js +0 -101
- package/src/enum/ua-parser-enum.mjs +0 -105
- package/src/extension/ua-parser-extension.js +0 -120
- package/src/extension/ua-parser-extension.mjs +0 -124
@@ -1,23 +1,26 @@
|
|
1
1
|
/////////////////////////////////////////////////////////////////////////////////
|
2
|
-
/* UAParser.js v2.0.0-
|
2
|
+
/* UAParser.js v2.0.0-beta.1
|
3
3
|
Copyright © 2012-2023 Faisal Salman <f@faisalman.com>
|
4
|
-
|
4
|
+
AGPLv3 License *//*
|
5
5
|
Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data.
|
6
6
|
Supports browser & node.js environment.
|
7
7
|
Demo : https://faisalman.github.io/ua-parser-js
|
8
8
|
Source : https://github.com/faisalman/ua-parser-js */
|
9
9
|
/////////////////////////////////////////////////////////////////////////////////
|
10
10
|
|
11
|
+
/* jshint esversion: 3 */
|
12
|
+
/* globals window */
|
13
|
+
|
11
14
|
(function (window, undefined) {
|
12
15
|
|
13
16
|
'use strict';
|
14
|
-
|
17
|
+
|
15
18
|
//////////////
|
16
19
|
// Constants
|
17
20
|
/////////////
|
18
21
|
|
19
22
|
|
20
|
-
var LIBVERSION = '2.0.0-
|
23
|
+
var LIBVERSION = '2.0.0-beta.1',
|
21
24
|
EMPTY = '',
|
22
25
|
UNKNOWN = '?',
|
23
26
|
FUNC_TYPE = 'function',
|
@@ -40,6 +43,7 @@
|
|
40
43
|
USER_AGENT = 'user-agent',
|
41
44
|
UA_MAX_LENGTH = 350,
|
42
45
|
BRANDS = 'brands',
|
46
|
+
FORMFACTOR = 'formFactor',
|
43
47
|
FULLVERLIST = 'fullVersionList',
|
44
48
|
PLATFORM = 'platform',
|
45
49
|
PLATFORMVER = 'platformVersion',
|
@@ -47,12 +51,13 @@
|
|
47
51
|
CH_HEADER = 'sec-ch-ua',
|
48
52
|
CH_HEADER_FULL_VER_LIST = CH_HEADER + '-full-version-list',
|
49
53
|
CH_HEADER_ARCH = CH_HEADER + '-arch',
|
50
|
-
CH_HEADER_BITNESS = CH_HEADER + '-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
+
CH_HEADER_BITNESS = CH_HEADER + '-' + BITNESS,
|
55
|
+
CH_HEADER_FORM_FACTOR = CH_HEADER + '-form-factor',
|
56
|
+
CH_HEADER_MOBILE = CH_HEADER + '-' + MOBILE,
|
57
|
+
CH_HEADER_MODEL = CH_HEADER + '-' + MODEL,
|
58
|
+
CH_HEADER_PLATFORM = CH_HEADER + '-' + PLATFORM,
|
54
59
|
CH_HEADER_PLATFORM_VER = CH_HEADER_PLATFORM + '-version',
|
55
|
-
CH_ALL_VALUES = [
|
60
|
+
CH_ALL_VALUES = [BRANDS, FULLVERLIST, MOBILE, MODEL, PLATFORM, PLATFORMVER, ARCHITECTURE, FORMFACTOR, BITNESS],
|
56
61
|
UA_BROWSER = 'browser',
|
57
62
|
UA_CPU = 'cpu',
|
58
63
|
UA_DEVICE = 'device',
|
@@ -93,18 +98,7 @@
|
|
93
98
|
// Helper
|
94
99
|
//////////
|
95
100
|
|
96
|
-
var
|
97
|
-
for (var i in arr) {
|
98
|
-
var propName = arr[i];
|
99
|
-
if (typeof propName == OBJ_TYPE && propName.length == 2) {
|
100
|
-
this[propName[0]] = propName[1];
|
101
|
-
} else {
|
102
|
-
this[propName] = undefined;
|
103
|
-
}
|
104
|
-
}
|
105
|
-
return this;
|
106
|
-
},
|
107
|
-
extend = function (regexes, extensions) {
|
101
|
+
var extend = function (regexes, extensions) {
|
108
102
|
var mergedRegexes = {};
|
109
103
|
for (var i in regexes) {
|
110
104
|
mergedRegexes[i] = extensions[i] && extensions[i].length % 2 === 0 ? extensions[i].concat(regexes[i]) : regexes[i];
|
@@ -135,10 +129,14 @@
|
|
135
129
|
itemListToArray = function (header) {
|
136
130
|
if (!header) return undefined;
|
137
131
|
var arr = [];
|
138
|
-
var tokens = strip(/\\?\"/g, header).split(',
|
132
|
+
var tokens = strip(/\\?\"/g, header).split(',');
|
139
133
|
for (var i = 0; i < tokens.length; i++) {
|
140
|
-
|
141
|
-
|
134
|
+
if (tokens[i].indexOf(';') > -1) {
|
135
|
+
var token = trim(tokens[i]).split(';v=');
|
136
|
+
arr[i] = { brand : token[0], version : token[1] };
|
137
|
+
} else {
|
138
|
+
arr[i] = tokens[i];
|
139
|
+
}
|
142
140
|
}
|
143
141
|
return arr;
|
144
142
|
},
|
@@ -148,11 +146,22 @@
|
|
148
146
|
majorize = function (version) {
|
149
147
|
return typeof(version) === STR_TYPE ? strip(/[^\d\.]/g, version).split('.')[0] : undefined;
|
150
148
|
},
|
149
|
+
setProps = function (arr) {
|
150
|
+
for (var i in arr) {
|
151
|
+
var propName = arr[i];
|
152
|
+
if (typeof propName == OBJ_TYPE && propName.length == 2) {
|
153
|
+
this[propName[0]] = propName[1];
|
154
|
+
} else {
|
155
|
+
this[propName] = undefined;
|
156
|
+
}
|
157
|
+
}
|
158
|
+
return this;
|
159
|
+
},
|
151
160
|
strip = function (pattern, str) {
|
152
161
|
return str.replace(pattern, EMPTY);
|
153
162
|
},
|
154
163
|
stripQuotes = function (val) {
|
155
|
-
return typeof val === STR_TYPE ? strip(
|
164
|
+
return typeof val === STR_TYPE ? strip(/\\?\"/g, val) : val;
|
156
165
|
},
|
157
166
|
trim = function (str, len) {
|
158
167
|
if (typeof(str) === STR_TYPE) {
|
@@ -234,25 +243,14 @@
|
|
234
243
|
return (i === UNKNOWN) ? undefined : i;
|
235
244
|
}
|
236
245
|
}
|
237
|
-
return str;
|
246
|
+
return map.hasOwnProperty('*') ? map['*'] : str;
|
238
247
|
};
|
239
248
|
|
240
249
|
///////////////
|
241
250
|
// String map
|
242
251
|
//////////////
|
243
252
|
|
244
|
-
|
245
|
-
var oldSafariMap = {
|
246
|
-
'1.0' : '/8',
|
247
|
-
'1.2' : '/1',
|
248
|
-
'1.3' : '/3',
|
249
|
-
'2.0' : '/412',
|
250
|
-
'2.0.2' : '/416',
|
251
|
-
'2.0.3' : '/417',
|
252
|
-
'2.0.4' : '/419',
|
253
|
-
'?' : '/'
|
254
|
-
},
|
255
|
-
windowsVersionMap = {
|
253
|
+
var windowsVersionMap = {
|
256
254
|
'ME' : '4.90',
|
257
255
|
'NT 3.11' : 'NT3.51',
|
258
256
|
'NT 4.0' : 'NT4.0',
|
@@ -264,6 +262,16 @@
|
|
264
262
|
'8.1' : 'NT 6.3',
|
265
263
|
'10' : ['NT 6.4', 'NT 10.0'],
|
266
264
|
'RT' : 'ARM'
|
265
|
+
},
|
266
|
+
|
267
|
+
formFactorMap = {
|
268
|
+
'embedded' : 'Automotive',
|
269
|
+
'mobile' : 'Mobile',
|
270
|
+
'tablet' : ['Tablet', 'EInk'],
|
271
|
+
'smarttv' : 'TV',
|
272
|
+
'wearable' : ['VR', 'XR', 'Watch'],
|
273
|
+
'?' : ['Desktop', 'Unknown'],
|
274
|
+
'*' : undefined
|
267
275
|
};
|
268
276
|
|
269
277
|
//////////////
|
@@ -355,7 +363,7 @@
|
|
355
363
|
/(naver)\(.*?(\d+\.[\w\.]+).*\)/i, // Naver InApp
|
356
364
|
/safari (line)\/([\w\.]+)/i, // Line App for iOS
|
357
365
|
/\b(line)\/([\w\.]+)\/iab/i, // Line App for Android
|
358
|
-
/(chromium|instagram)[\/ ]([-\w\.]+)/i
|
366
|
+
/(chromium|instagram|snapchat)[\/ ]([-\w\.]+)/i // Chromium/Instagram/Snapchat
|
359
367
|
], [NAME, VERSION], [
|
360
368
|
/\bgsa\/([\w\.]+) .*safari\//i // Google Search Appliance on iOS
|
361
369
|
], [VERSION, [NAME, 'GSA']], [
|
@@ -384,7 +392,7 @@
|
|
384
392
|
/version\/([\w\.\,]+) .*(safari)/i // Safari
|
385
393
|
], [VERSION, NAME], [
|
386
394
|
/webkit.+?(mobile ?safari|safari)(\/[\w\.]+)/i // Safari < 3.0
|
387
|
-
], [NAME, [VERSION,
|
395
|
+
], [NAME, [VERSION, '1']], [
|
388
396
|
|
389
397
|
/(webkit|khtml)\/([\w\.]+)/i
|
390
398
|
], [NAME, VERSION], [
|
@@ -425,7 +433,7 @@
|
|
425
433
|
/((?:i[346]|x)86)[;\)]/i // IA32 (x86)
|
426
434
|
], [[ARCHITECTURE, 'ia32']], [
|
427
435
|
|
428
|
-
/\b(aarch64|arm(v?8e?l?|_?64))\b/i
|
436
|
+
/\b(aarch64|arm(v?8e?l?|_?64))\b/i // ARM64
|
429
437
|
], [[ARCHITECTURE, 'arm64']], [
|
430
438
|
|
431
439
|
/\b(arm(?:v[67])?ht?n?[fl]p?)\b/i // ARMHF
|
@@ -482,12 +490,14 @@
|
|
482
490
|
], [MODEL, [VENDOR, HUAWEI], [TYPE, MOBILE]], [
|
483
491
|
|
484
492
|
// Xiaomi
|
485
|
-
/\b(poco[\w ]
|
493
|
+
/\b(poco[\w ]+|m2\d{3}j\d\d[a-z]{2})(?: bui|\))/i, // Xiaomi POCO
|
486
494
|
/\b; (\w+) build\/hm\1/i, // Xiaomi Hongmi 'numeric' models
|
487
495
|
/\b(hm[-_ ]?note?[_ ]?(?:\d\w)?) bui/i, // Xiaomi Hongmi
|
488
496
|
/\b(redmi[\-_ ]?(?:note|k)?[\w_ ]+)(?: bui|\))/i, // Xiaomi Redmi
|
497
|
+
/oid[^\)]+; (m?[12][0-389][01]\w{3,6}[c-y])( bui|\))/i, // Xiaomi Redmi 'numeric' models
|
489
498
|
/\b(mi[-_ ]?(?:a\d|one|one[_ ]plus|note lte|max|cc)?[_ ]?(?:\d?\w?)[_ ]?(?:plus|se|lite)?)(?: bui|\))/i // Xiaomi Mi
|
490
499
|
], [[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, MOBILE]], [
|
500
|
+
/oid[^\)]+; (2\d{4}(283|rpbf)[cgl])( bui|\))/i, // Redmi Pad
|
491
501
|
/\b(mi[-_ ]?(?:pad)(?:[\w_ ]+))(?: bui|\))/i // Mi Pad tablets
|
492
502
|
],[[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, TABLET]], [
|
493
503
|
|
@@ -502,7 +512,7 @@
|
|
502
512
|
], [MODEL, [VENDOR, 'Vivo'], [TYPE, MOBILE]], [
|
503
513
|
|
504
514
|
// Realme
|
505
|
-
/\b(rmx[
|
515
|
+
/\b(rmx[1-3]\d{3})(?: bui|;|\))/i
|
506
516
|
], [MODEL, [VENDOR, 'Realme'], [TYPE, MOBILE]], [
|
507
517
|
|
508
518
|
// Motorola
|
@@ -588,9 +598,13 @@
|
|
588
598
|
/droid.+; (m[1-5] note) bui/i,
|
589
599
|
/\bmz-([-\w]{2,})/i
|
590
600
|
], [MODEL, [VENDOR, 'Meizu'], [TYPE, MOBILE]], [
|
601
|
+
|
602
|
+
// Ulefone
|
603
|
+
/; ((?:power )?armor(?:[\w ]{0,8}))(?: bui|\))/i
|
604
|
+
], [MODEL, [VENDOR, 'Ulefone'], [TYPE, MOBILE]], [
|
591
605
|
|
592
606
|
// MIXED
|
593
|
-
/(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus|dell|meizu|motorola|polytron)[-_ ]?([-\w]*)/i,
|
607
|
+
/(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus|dell|meizu|motorola|polytron|infinix|tecno)[-_ ]?([-\w]*)/i,
|
594
608
|
// BlackBerry/BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron
|
595
609
|
/(hp) ([\w ]+\w)/i, // HP iPAQ
|
596
610
|
/(asus)-?(\w+)/i, // Asus
|
@@ -635,7 +649,7 @@
|
|
635
649
|
], [VENDOR, [MODEL, APPLE+' TV'], [TYPE, SMARTTV]], [
|
636
650
|
/crkey/i // Google Chromecast
|
637
651
|
], [[MODEL, CHROME+'cast'], [VENDOR, GOOGLE], [TYPE, SMARTTV]], [
|
638
|
-
/droid.+aft(\w)( bui|\))/i
|
652
|
+
/droid.+aft(\w+)( bui|\))/i // Fire TV
|
639
653
|
], [MODEL, [VENDOR, AMAZON], [TYPE, SMARTTV]], [
|
640
654
|
/\(dtv[\);].+(aquos)/i,
|
641
655
|
/(aquos-tv[\w ]+)\)/i // Sharp
|
@@ -740,7 +754,7 @@
|
|
740
754
|
|
741
755
|
// iOS/macOS
|
742
756
|
/ip[honead]{2,4}\b(?:.*os ([\w]+) like mac|; opera)/i, // iOS
|
743
|
-
/ios;fbsv\/([\d\.]+)/i,
|
757
|
+
/(?:ios;fbsv\/|iphone.+ios[\/ ])([\d\.]+)/i,
|
744
758
|
/cfnetwork\/.+darwin/i
|
745
759
|
], [[VERSION, /_/g, '.'], [NAME, 'iOS']], [
|
746
760
|
/(mac os x) ?([\w\. ]*)/i,
|
@@ -809,23 +823,23 @@
|
|
809
823
|
|
810
824
|
var defaultProps = (function () {
|
811
825
|
var props = { init : {}, isIgnore : {}, isIgnoreRgx : {}, toString : {}};
|
812
|
-
|
826
|
+
setProps.call(props.init, [
|
813
827
|
[UA_BROWSER, [NAME, VERSION, MAJOR]],
|
814
828
|
[UA_CPU, [ARCHITECTURE]],
|
815
829
|
[UA_DEVICE, [TYPE, MODEL, VENDOR]],
|
816
830
|
[UA_ENGINE, [NAME, VERSION]],
|
817
831
|
[UA_OS, [NAME, VERSION]]
|
818
832
|
]);
|
819
|
-
|
833
|
+
setProps.call(props.isIgnore, [
|
820
834
|
[UA_BROWSER, [VERSION, MAJOR]],
|
821
835
|
[UA_ENGINE, [VERSION]],
|
822
836
|
[UA_OS, [VERSION]]
|
823
837
|
]);
|
824
|
-
|
838
|
+
setProps.call(props.isIgnoreRgx, [
|
825
839
|
[UA_BROWSER, / ?browser$/i],
|
826
840
|
[UA_OS, / ?os$/i]
|
827
841
|
]);
|
828
|
-
|
842
|
+
setProps.call(props.toString, [
|
829
843
|
[UA_BROWSER, [NAME, VERSION]],
|
830
844
|
[UA_CPU, [ARCHITECTURE]],
|
831
845
|
[UA_DEVICE, [VENDOR, MODEL]],
|
@@ -835,34 +849,47 @@
|
|
835
849
|
return props;
|
836
850
|
})();
|
837
851
|
|
838
|
-
var
|
852
|
+
var createIData = function (item, itemType) {
|
839
853
|
|
840
854
|
var init_props = defaultProps.init[itemType],
|
841
855
|
is_ignoreProps = defaultProps.isIgnore[itemType] || 0,
|
842
856
|
is_ignoreRgx = defaultProps.isIgnoreRgx[itemType] || 0,
|
843
857
|
toString_props = defaultProps.toString[itemType] || 0;
|
844
858
|
|
845
|
-
function
|
846
|
-
|
859
|
+
function IData () {
|
860
|
+
setProps.call(this, init_props);
|
847
861
|
}
|
848
|
-
|
849
|
-
|
862
|
+
|
863
|
+
IData.prototype.getItem = function () {
|
864
|
+
return item;
|
865
|
+
};
|
866
|
+
|
867
|
+
IData.prototype.withClientHints = function () {
|
868
|
+
|
850
869
|
// nodejs / non-client-hints browsers
|
851
870
|
if (!NAVIGATOR_UADATA) {
|
852
|
-
return
|
871
|
+
return item
|
872
|
+
.parseCH()
|
873
|
+
.get();
|
853
874
|
}
|
854
875
|
|
855
876
|
// browsers based on chromium 85+
|
856
877
|
return NAVIGATOR_UADATA
|
857
878
|
.getHighEntropyValues(CH_ALL_VALUES)
|
858
879
|
.then(function (res) {
|
859
|
-
|
860
|
-
|
880
|
+
return item
|
881
|
+
.setCH(new UACHData(res, false))
|
882
|
+
.parseCH()
|
883
|
+
.get();
|
861
884
|
});
|
862
885
|
};
|
863
886
|
|
887
|
+
IData.prototype.withFeatureCheck = function () {
|
888
|
+
return item.detectFeature().get();
|
889
|
+
};
|
890
|
+
|
864
891
|
if (itemType != UA_RESULT) {
|
865
|
-
|
892
|
+
IData.prototype.is = function (strToCheck) {
|
866
893
|
var is = false;
|
867
894
|
for (var i in this) {
|
868
895
|
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)) {
|
@@ -875,7 +902,7 @@
|
|
875
902
|
}
|
876
903
|
return is;
|
877
904
|
};
|
878
|
-
|
905
|
+
IData.prototype.toString = function () {
|
879
906
|
var str = EMPTY;
|
880
907
|
for (var i in toString_props) {
|
881
908
|
if (typeof(this[toString_props[i]]) !== UNDEF_TYPE) {
|
@@ -887,45 +914,45 @@
|
|
887
914
|
}
|
888
915
|
|
889
916
|
if (!NAVIGATOR_UADATA) {
|
890
|
-
|
917
|
+
IData.prototype.then = function (cb) {
|
891
918
|
var that = this;
|
892
|
-
var
|
919
|
+
var IDataResolve = function () {
|
893
920
|
for (var prop in that) {
|
894
921
|
if (that.hasOwnProperty(prop)) {
|
895
922
|
this[prop] = that[prop];
|
896
923
|
}
|
897
924
|
}
|
898
925
|
};
|
899
|
-
|
900
|
-
is :
|
901
|
-
toString :
|
926
|
+
IDataResolve.prototype = {
|
927
|
+
is : IData.prototype.is,
|
928
|
+
toString : IData.prototype.toString
|
902
929
|
};
|
903
|
-
var resolveData = new
|
930
|
+
var resolveData = new IDataResolve();
|
904
931
|
cb(resolveData);
|
905
932
|
return resolveData;
|
906
933
|
};
|
907
934
|
}
|
908
935
|
|
909
|
-
return new
|
936
|
+
return new IData();
|
910
937
|
};
|
911
938
|
|
912
939
|
/////////////////
|
913
940
|
// Constructor
|
914
941
|
////////////////
|
915
942
|
|
916
|
-
function
|
943
|
+
function UACHData (uach, isHttpUACH) {
|
917
944
|
uach = uach || {};
|
918
|
-
|
919
|
-
if (
|
920
|
-
|
945
|
+
setProps.call(this, CH_ALL_VALUES);
|
946
|
+
if (isHttpUACH) {
|
947
|
+
setProps.call(this, [
|
921
948
|
[BRANDS, itemListToArray(uach[CH_HEADER])],
|
922
949
|
[FULLVERLIST, itemListToArray(uach[CH_HEADER_FULL_VER_LIST])],
|
923
|
-
[BRANDS, itemListToArray(uach[CH_HEADER])],
|
924
950
|
[MOBILE, /\?1/.test(uach[CH_HEADER_MOBILE])],
|
925
951
|
[MODEL, stripQuotes(uach[CH_HEADER_MODEL])],
|
926
952
|
[PLATFORM, stripQuotes(uach[CH_HEADER_PLATFORM])],
|
927
953
|
[PLATFORMVER, stripQuotes(uach[CH_HEADER_PLATFORM_VER])],
|
928
954
|
[ARCHITECTURE, stripQuotes(uach[CH_HEADER_ARCH])],
|
955
|
+
[FORMFACTOR, itemListToArray(uach[CH_HEADER_FORM_FACTOR])],
|
929
956
|
[BITNESS, stripQuotes(uach[CH_HEADER_BITNESS])]
|
930
957
|
]);
|
931
958
|
} else {
|
@@ -933,127 +960,162 @@
|
|
933
960
|
if(this.hasOwnProperty(prop) && typeof uach[prop] !== UNDEF_TYPE) this[prop] = uach[prop];
|
934
961
|
}
|
935
962
|
}
|
936
|
-
return this;
|
937
963
|
}
|
938
964
|
|
939
|
-
function
|
940
|
-
|
965
|
+
function UAItem (itemType, ua, rgxMap, uaCH) {
|
966
|
+
|
967
|
+
this.get = function (prop) {
|
968
|
+
if (!prop) return this.data;
|
969
|
+
return this.data.hasOwnProperty(prop) ? this.data[prop] : undefined;
|
970
|
+
};
|
971
|
+
|
972
|
+
this.set = function (prop, val) {
|
973
|
+
this.data[prop] = val;
|
974
|
+
return this;
|
975
|
+
};
|
976
|
+
|
977
|
+
this.setCH = function (ch) {
|
978
|
+
this.uaCH = ch;
|
979
|
+
return this;
|
980
|
+
};
|
981
|
+
|
982
|
+
this.detectFeature = function () {
|
983
|
+
if (NAVIGATOR && NAVIGATOR.userAgent == this.ua) {
|
984
|
+
switch (this.itemType) {
|
985
|
+
case UA_BROWSER:
|
986
|
+
// Brave-specific detection
|
987
|
+
if (NAVIGATOR.brave && typeof NAVIGATOR.brave.isBrave == FUNC_TYPE) {
|
988
|
+
this.set(NAME, 'Brave');
|
989
|
+
}
|
990
|
+
break;
|
991
|
+
case UA_DEVICE:
|
992
|
+
// Chrome-specific detection: check for 'mobile' value of navigator.userAgentData
|
993
|
+
if (!this.get(TYPE) && NAVIGATOR_UADATA && NAVIGATOR_UADATA[MOBILE]) {
|
994
|
+
this.set(TYPE, MOBILE);
|
995
|
+
}
|
996
|
+
// iPadOS-specific detection: identified as Mac, but has some iOS-only properties
|
997
|
+
if (this.get(MODEL) == 'Macintosh' && NAVIGATOR && typeof NAVIGATOR.standalone !== UNDEF_TYPE && NAVIGATOR.maxTouchPoints && NAVIGATOR.maxTouchPoints > 2) {
|
998
|
+
this.set(MODEL, 'iPad')
|
999
|
+
.set(TYPE, TABLET);
|
1000
|
+
}
|
1001
|
+
break;
|
1002
|
+
case UA_OS:
|
1003
|
+
// Chrome-specific detection: check for 'platform' value of navigator.userAgentData
|
1004
|
+
if (!this.get(NAME) && NAVIGATOR_UADATA && NAVIGATOR_UADATA[PLATFORM]) {
|
1005
|
+
this.set(NAME, NAVIGATOR_UADATA[PLATFORM]);
|
1006
|
+
}
|
1007
|
+
break;
|
1008
|
+
case UA_RESULT:
|
1009
|
+
var data = this.data;
|
1010
|
+
var detect = function (itemType) {
|
1011
|
+
return data[itemType]
|
1012
|
+
.getItem()
|
1013
|
+
.detectFeature()
|
1014
|
+
.get();
|
1015
|
+
};
|
1016
|
+
this.set(UA_BROWSER, detect(UA_BROWSER))
|
1017
|
+
.set(UA_CPU, detect(UA_CPU))
|
1018
|
+
.set(UA_DEVICE, detect(UA_DEVICE))
|
1019
|
+
.set(UA_ENGINE, detect(UA_ENGINE))
|
1020
|
+
.set(UA_OS, detect(UA_OS));
|
1021
|
+
}
|
1022
|
+
}
|
1023
|
+
return this;
|
1024
|
+
};
|
1025
|
+
|
1026
|
+
this.parseUA = function () {
|
1027
|
+
if (this.itemType != UA_RESULT) {
|
1028
|
+
rgxMapper.call(this.data, this.ua, this.rgxMap);
|
1029
|
+
}
|
1030
|
+
if (this.itemType == UA_BROWSER) {
|
1031
|
+
this.set(MAJOR, majorize(this.get(VERSION)));
|
1032
|
+
}
|
1033
|
+
return this;
|
1034
|
+
};
|
1035
|
+
|
1036
|
+
this.parseCH = function () {
|
1037
|
+
var uaCH = this.uaCH,
|
1038
|
+
rgxMap = this.rgxMap;
|
1039
|
+
|
1040
|
+
switch (this.itemType) {
|
1041
|
+
case UA_BROWSER:
|
1042
|
+
var brands = uaCH[FULLVERLIST] || uaCH[BRANDS];
|
1043
|
+
if (brands) {
|
1044
|
+
for (var i in brands) {
|
1045
|
+
var brandName = brands[i].brand,
|
1046
|
+
brandVersion = brands[i].version;
|
1047
|
+
if (!/not.a.brand/i.test(brandName) && (i < 1 || /chromi/i.test(this.get(NAME)))) {
|
1048
|
+
this.set(NAME, strip(GOOGLE+' ', brandName))
|
1049
|
+
.set(VERSION, brandVersion)
|
1050
|
+
.set(MAJOR, majorize(brandVersion));
|
1051
|
+
}
|
1052
|
+
}
|
1053
|
+
}
|
1054
|
+
break;
|
1055
|
+
case UA_CPU:
|
1056
|
+
var archName = uaCH[ARCHITECTURE];
|
1057
|
+
if (archName) {
|
1058
|
+
if (archName && uaCH[BITNESS] == '64') archName += '64';
|
1059
|
+
rgxMapper.call(this.data, archName + ';', rgxMap);
|
1060
|
+
}
|
1061
|
+
break;
|
1062
|
+
case UA_DEVICE:
|
1063
|
+
if (uaCH[MOBILE]) {
|
1064
|
+
this.set(TYPE, MOBILE);
|
1065
|
+
}
|
1066
|
+
if (uaCH[MODEL]) {
|
1067
|
+
this.set(MODEL, uaCH[MODEL]);
|
1068
|
+
}
|
1069
|
+
if (uaCH[FORMFACTOR]) {
|
1070
|
+
var ff;
|
1071
|
+
if (typeof uaCH[FORMFACTOR] !== 'string') {
|
1072
|
+
var idx = 0;
|
1073
|
+
while (!ff && idx < uaCH[FORMFACTOR].length) {
|
1074
|
+
ff = strMapper(uaCH[FORMFACTOR][idx++], formFactorMap);
|
1075
|
+
}
|
1076
|
+
} else {
|
1077
|
+
ff = strMapper(uaCH[FORMFACTOR], formFactorMap);
|
1078
|
+
}
|
1079
|
+
this.set(TYPE, ff);
|
1080
|
+
}
|
1081
|
+
break;
|
1082
|
+
case UA_OS:
|
1083
|
+
var osName = uaCH[PLATFORM];
|
1084
|
+
if(osName) {
|
1085
|
+
var osVersion = uaCH[PLATFORMVER];
|
1086
|
+
if (osName == WINDOWS) osVersion = (parseInt(majorize(osVersion), 10) >= 13 ? '11' : '10');
|
1087
|
+
this.set(NAME, osName)
|
1088
|
+
.set(VERSION, osVersion);
|
1089
|
+
}
|
1090
|
+
break;
|
1091
|
+
case UA_RESULT:
|
1092
|
+
var data = this.data;
|
1093
|
+
var parse = function (itemType) {
|
1094
|
+
return data[itemType]
|
1095
|
+
.getItem()
|
1096
|
+
.setCH(uaCH)
|
1097
|
+
.parseCH()
|
1098
|
+
.get();
|
1099
|
+
};
|
1100
|
+
this.set(UA_BROWSER, parse(UA_BROWSER))
|
1101
|
+
.set(UA_CPU, parse(UA_CPU))
|
1102
|
+
.set(UA_DEVICE, parse(UA_DEVICE))
|
1103
|
+
.set(UA_ENGINE, parse(UA_ENGINE))
|
1104
|
+
.set(UA_OS, parse(UA_OS));
|
1105
|
+
}
|
1106
|
+
return this;
|
1107
|
+
};
|
1108
|
+
|
1109
|
+
setProps.call(this, [
|
941
1110
|
['itemType', itemType],
|
942
1111
|
['ua', ua],
|
943
1112
|
['uaCH', uaCH],
|
944
1113
|
['rgxMap', rgxMap],
|
945
|
-
['data',
|
1114
|
+
['data', createIData(this, itemType)]
|
946
1115
|
]);
|
947
|
-
|
948
|
-
var isSelfNav = NAVIGATOR && NAVIGATOR.userAgent == ua;
|
949
|
-
switch(this.itemType) {
|
950
|
-
case UA_BROWSER:
|
951
|
-
// Brave-specific detection
|
952
|
-
if (isSelfNav && NAVIGATOR.brave && typeof NAVIGATOR.brave.isBrave == FUNC_TYPE) {
|
953
|
-
this.set(NAME, 'Brave');
|
954
|
-
}
|
955
|
-
this.set(MAJOR, majorize(this.get(VERSION)));
|
956
|
-
break;
|
957
|
-
case UA_DEVICE:
|
958
|
-
if (isSelfNav && !this.get(TYPE) && NAVIGATOR_UADATA && NAVIGATOR_UADATA[MOBILE]) {
|
959
|
-
this.set(TYPE, MOBILE);
|
960
|
-
}
|
961
|
-
// iPadOS-specific detection: identified as Mac, but has some iOS-only properties
|
962
|
-
if (isSelfNav && this.get(MODEL) == 'Macintosh' && NAVIGATOR && typeof NAVIGATOR.standalone !== UNDEF_TYPE && NAVIGATOR.maxTouchPoints && NAVIGATOR.maxTouchPoints > 2) {
|
963
|
-
this.set(MODEL, 'iPad')
|
964
|
-
.set(TYPE, TABLET);
|
965
|
-
}
|
966
|
-
break;
|
967
|
-
case UA_OS:
|
968
|
-
if (isSelfNav && !this.get(NAME) && NAVIGATOR_UADATA && NAVIGATOR_UADATA[PLATFORM]) {
|
969
|
-
this.set(NAME, NAVIGATOR_UADATA[PLATFORM]);
|
970
|
-
}
|
971
|
-
break;
|
972
|
-
case UA_RESULT:
|
973
|
-
var createUAParserItem = function (itemType) {
|
974
|
-
return new UAParserItem(itemType, ua, rgxMap[itemType], uaCH).get();
|
975
|
-
};
|
976
|
-
this.set('ua', ua)
|
977
|
-
.set(UA_BROWSER, createUAParserItem(UA_BROWSER))
|
978
|
-
.set(UA_CPU, createUAParserItem(UA_CPU))
|
979
|
-
.set(UA_DEVICE, createUAParserItem(UA_DEVICE))
|
980
|
-
.set(UA_ENGINE, createUAParserItem(UA_ENGINE))
|
981
|
-
.set(UA_OS, createUAParserItem(UA_OS))
|
982
|
-
.get();
|
983
|
-
}
|
1116
|
+
|
984
1117
|
return this;
|
985
1118
|
}
|
986
|
-
UAParserItem.prototype.get = function (prop) {
|
987
|
-
if (!prop) return this.data;
|
988
|
-
return this.data.hasOwnProperty(prop) ? this.data[prop] : undefined;
|
989
|
-
};
|
990
|
-
UAParserItem.prototype.parse = function () {
|
991
|
-
if (this.itemType != UA_RESULT) {
|
992
|
-
rgxMapper.call(this.data, this.ua, this.rgxMap);
|
993
|
-
}
|
994
|
-
return this;
|
995
|
-
};
|
996
|
-
UAParserItem.prototype.parseCH = function () {
|
997
|
-
var ua = this.ua,
|
998
|
-
uaCH = this.uaCH,
|
999
|
-
rgxMap = this.rgxMap;
|
1000
|
-
|
1001
|
-
switch (this.itemType) {
|
1002
|
-
case UA_BROWSER:
|
1003
|
-
var brands = uaCH[FULLVERLIST] || uaCH[BRANDS];
|
1004
|
-
if (brands) {
|
1005
|
-
for (var i in brands) {
|
1006
|
-
var brandName = brands[i].brand,
|
1007
|
-
brandVersion = brands[i].version;
|
1008
|
-
if (!/not.a.brand/i.test(brandName) && (i < 1 || /chromi/i.test(this.get(NAME)))) {
|
1009
|
-
this.set(NAME, strip(GOOGLE+' ', brandName))
|
1010
|
-
.set(VERSION, brandVersion)
|
1011
|
-
.set(MAJOR, majorize(brandVersion));
|
1012
|
-
}
|
1013
|
-
}
|
1014
|
-
}
|
1015
|
-
break;
|
1016
|
-
case UA_CPU:
|
1017
|
-
var archName = uaCH[ARCHITECTURE];
|
1018
|
-
if (archName) {
|
1019
|
-
if (archName && uaCH[BITNESS] == '64') archName += '64';
|
1020
|
-
rgxMapper.call(this.data, archName + ';', rgxMap);
|
1021
|
-
}
|
1022
|
-
break;
|
1023
|
-
case UA_DEVICE:
|
1024
|
-
if (uaCH[MOBILE]) {
|
1025
|
-
this.set(TYPE, MOBILE);
|
1026
|
-
}
|
1027
|
-
if (uaCH[MODEL]) {
|
1028
|
-
this.set(MODEL, uaCH[MODEL]);
|
1029
|
-
}
|
1030
|
-
break;
|
1031
|
-
case UA_OS:
|
1032
|
-
var osName = uaCH[PLATFORM];
|
1033
|
-
if(osName) {
|
1034
|
-
var osVersion = uaCH[PLATFORMVER];
|
1035
|
-
if (osName == WINDOWS) osVersion = (parseInt(majorize(osVersion), 10) >= 13 ? '11' : '10');
|
1036
|
-
this.set(NAME, osName)
|
1037
|
-
.set(VERSION, osVersion);
|
1038
|
-
}
|
1039
|
-
break;
|
1040
|
-
case UA_RESULT:
|
1041
|
-
var createUAParserItemWithCH = function (itemType) {
|
1042
|
-
return new UAParserItem(itemType, ua, rgxMap[itemType], uaCH).parseCH().get();
|
1043
|
-
};
|
1044
|
-
this.set('ua', ua)
|
1045
|
-
.set(UA_BROWSER, createUAParserItemWithCH(UA_BROWSER))
|
1046
|
-
.set(UA_CPU, createUAParserItemWithCH(UA_CPU))
|
1047
|
-
.set(UA_DEVICE, createUAParserItemWithCH(UA_DEVICE))
|
1048
|
-
.set(UA_ENGINE, createUAParserItemWithCH(UA_ENGINE))
|
1049
|
-
.set(UA_OS, createUAParserItemWithCH(UA_OS));
|
1050
|
-
}
|
1051
|
-
return this;
|
1052
|
-
};
|
1053
|
-
UAParserItem.prototype.set = function (prop, val) {
|
1054
|
-
this.data[prop] = val;
|
1055
|
-
return this;
|
1056
|
-
};
|
1057
1119
|
|
1058
1120
|
function UAParser (ua, extensions, headers) {
|
1059
1121
|
|
@@ -1077,39 +1139,54 @@
|
|
1077
1139
|
return new UAParser(ua, extensions, headers).getResult();
|
1078
1140
|
}
|
1079
1141
|
|
1080
|
-
var userAgent = ua
|
1081
|
-
|
1082
|
-
|
1083
|
-
|
1084
|
-
headers[USER_AGENT] :
|
1085
|
-
EMPTY)),
|
1086
|
-
|
1087
|
-
HTTP_UACH = new UAParserDataCH(headers, true),
|
1142
|
+
var userAgent = typeof ua === STR_TYPE ? ua : // Passed user-agent string
|
1143
|
+
((NAVIGATOR && NAVIGATOR.userAgent) ? NAVIGATOR.userAgent : // navigator.userAgent
|
1144
|
+
(headers && headers[USER_AGENT] ? headers[USER_AGENT] : // User-Agent from passed headers
|
1145
|
+
EMPTY)), // empty string
|
1088
1146
|
|
1147
|
+
httpUACH = new UACHData(headers, true),
|
1089
1148
|
regexMap = extensions ?
|
1090
1149
|
extend(defaultRegexes, extensions) :
|
1091
1150
|
defaultRegexes,
|
1092
1151
|
|
1093
|
-
|
1094
|
-
|
1095
|
-
return
|
1096
|
-
|
1152
|
+
createItemFunc = function (itemType) {
|
1153
|
+
if (itemType == UA_RESULT) {
|
1154
|
+
return function () {
|
1155
|
+
return new UAItem(itemType, userAgent, regexMap, httpUACH)
|
1156
|
+
.set('ua', userAgent)
|
1157
|
+
.set(UA_BROWSER, this.getBrowser())
|
1158
|
+
.set(UA_CPU, this.getCPU())
|
1159
|
+
.set(UA_DEVICE, this.getDevice())
|
1160
|
+
.set(UA_ENGINE, this.getEngine())
|
1161
|
+
.set(UA_OS, this.getOS())
|
1162
|
+
.get();
|
1163
|
+
};
|
1164
|
+
} else {
|
1165
|
+
return function () {
|
1166
|
+
return new UAItem(itemType, userAgent, regexMap[itemType], httpUACH)
|
1167
|
+
.parseUA()
|
1168
|
+
.get();
|
1169
|
+
};
|
1170
|
+
}
|
1097
1171
|
};
|
1098
|
-
|
1172
|
+
|
1099
1173
|
// public methods
|
1100
|
-
|
1101
|
-
['getBrowser',
|
1102
|
-
['getCPU',
|
1103
|
-
['getDevice',
|
1104
|
-
['getEngine',
|
1105
|
-
['getOS',
|
1106
|
-
['getResult',
|
1174
|
+
setProps.call(this, [
|
1175
|
+
['getBrowser', createItemFunc(UA_BROWSER)],
|
1176
|
+
['getCPU', createItemFunc(UA_CPU)],
|
1177
|
+
['getDevice', createItemFunc(UA_DEVICE)],
|
1178
|
+
['getEngine', createItemFunc(UA_ENGINE)],
|
1179
|
+
['getOS', createItemFunc(UA_OS)],
|
1180
|
+
['getResult', createItemFunc(UA_RESULT)],
|
1107
1181
|
['getUA', function () { return userAgent; }],
|
1108
1182
|
['setUA', function (ua) {
|
1109
|
-
|
1183
|
+
if (typeof ua === STR_TYPE)
|
1184
|
+
userAgent = ua.length > UA_MAX_LENGTH ? trim(ua, UA_MAX_LENGTH) : ua;
|
1110
1185
|
return this;
|
1111
1186
|
}]
|
1112
|
-
])
|
1187
|
+
])
|
1188
|
+
.setUA(userAgent);
|
1189
|
+
|
1113
1190
|
return this;
|
1114
1191
|
}
|
1115
1192
|
|