ua-parser-js 2.0.0-alpha.2 → 2.0.0-alpha.3

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.
@@ -1,5 +1,5 @@
1
1
  /////////////////////////////////////////////////////////////////////////////////
2
- /* UAParser.js v2.0.0-alpha.2
2
+ /* UAParser.js v2.0.0-alpha.3
3
3
  Copyright © 2012-2023 Faisal Salman <f@faisalman.com>
4
4
  MIT License *//*
5
5
  Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data.
@@ -8,16 +8,19 @@
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-alpha.2',
23
+ var LIBVERSION = '2.0.0-alpha.3',
21
24
  EMPTY = '',
22
25
  UNKNOWN = '?',
23
26
  FUNC_TYPE = 'function',
@@ -47,12 +50,12 @@
47
50
  CH_HEADER = 'sec-ch-ua',
48
51
  CH_HEADER_FULL_VER_LIST = CH_HEADER + '-full-version-list',
49
52
  CH_HEADER_ARCH = CH_HEADER + '-arch',
50
- CH_HEADER_BITNESS = CH_HEADER + '-bitness',
51
- CH_HEADER_MOBILE = CH_HEADER + '-mobile',
52
- CH_HEADER_MODEL = CH_HEADER + '-model',
53
- CH_HEADER_PLATFORM = CH_HEADER + '-platform',
53
+ CH_HEADER_BITNESS = CH_HEADER + '-' + BITNESS,
54
+ CH_HEADER_MOBILE = CH_HEADER + '-' + MOBILE,
55
+ CH_HEADER_MODEL = CH_HEADER + '-' + MODEL,
56
+ CH_HEADER_PLATFORM = CH_HEADER + '-' + PLATFORM,
54
57
  CH_HEADER_PLATFORM_VER = CH_HEADER_PLATFORM + '-version',
55
- CH_ALL_VALUES = ['brands', 'fullVersionList', MOBILE, MODEL, 'platform', 'platformVersion', ARCHITECTURE, 'bitness'],
58
+ CH_ALL_VALUES = [BRANDS, FULLVERLIST, MOBILE, MODEL, PLATFORM, PLATFORMVER, ARCHITECTURE, BITNESS],
56
59
  UA_BROWSER = 'browser',
57
60
  UA_CPU = 'cpu',
58
61
  UA_DEVICE = 'device',
@@ -93,18 +96,7 @@
93
96
  // Helper
94
97
  //////////
95
98
 
96
- var assignFromEntries = function (arr) {
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) {
99
+ var extend = function (regexes, extensions) {
108
100
  var mergedRegexes = {};
109
101
  for (var i in regexes) {
110
102
  mergedRegexes[i] = extensions[i] && extensions[i].length % 2 === 0 ? extensions[i].concat(regexes[i]) : regexes[i];
@@ -148,6 +140,17 @@
148
140
  majorize = function (version) {
149
141
  return typeof(version) === STR_TYPE ? strip(/[^\d\.]/g, version).split('.')[0] : undefined;
150
142
  },
143
+ setProps = function (arr) {
144
+ for (var i in arr) {
145
+ var propName = arr[i];
146
+ if (typeof propName == OBJ_TYPE && propName.length == 2) {
147
+ this[propName[0]] = propName[1];
148
+ } else {
149
+ this[propName] = undefined;
150
+ }
151
+ }
152
+ return this;
153
+ },
151
154
  strip = function (pattern, str) {
152
155
  return str.replace(pattern, EMPTY);
153
156
  },
@@ -241,18 +244,7 @@
241
244
  // String map
242
245
  //////////////
243
246
 
244
- // Safari < 3.0
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 = {
247
+ var windowsVersionMap = {
256
248
  'ME' : '4.90',
257
249
  'NT 3.11' : 'NT3.51',
258
250
  'NT 4.0' : 'NT4.0',
@@ -355,7 +347,7 @@
355
347
  /(naver)\(.*?(\d+\.[\w\.]+).*\)/i, // Naver InApp
356
348
  /safari (line)\/([\w\.]+)/i, // Line App for iOS
357
349
  /\b(line)\/([\w\.]+)\/iab/i, // Line App for Android
358
- /(chromium|instagram)[\/ ]([-\w\.]+)/i // Chromium/Instagram
350
+ /(chromium|instagram|snapchat)[\/ ]([-\w\.]+)/i // Chromium/Instagram/Snapchat
359
351
  ], [NAME, VERSION], [
360
352
  /\bgsa\/([\w\.]+) .*safari\//i // Google Search Appliance on iOS
361
353
  ], [VERSION, [NAME, 'GSA']], [
@@ -384,7 +376,7 @@
384
376
  /version\/([\w\.\,]+) .*(safari)/i // Safari
385
377
  ], [VERSION, NAME], [
386
378
  /webkit.+?(mobile ?safari|safari)(\/[\w\.]+)/i // Safari < 3.0
387
- ], [NAME, [VERSION, strMapper, oldSafariMap]], [
379
+ ], [NAME, [VERSION, '1']], [
388
380
 
389
381
  /(webkit|khtml)\/([\w\.]+)/i
390
382
  ], [NAME, VERSION], [
@@ -425,7 +417,7 @@
425
417
  /((?:i[346]|x)86)[;\)]/i // IA32 (x86)
426
418
  ], [[ARCHITECTURE, 'ia32']], [
427
419
 
428
- /\b(aarch64|arm(v?8e?l?|_?64))\b/i // ARM64
420
+ /\b(aarch64|arm(v?8e?l?|_?64))\b/i // ARM64
429
421
  ], [[ARCHITECTURE, 'arm64']], [
430
422
 
431
423
  /\b(arm(?:v[67])?ht?n?[fl]p?)\b/i // ARMHF
@@ -482,7 +474,7 @@
482
474
  ], [MODEL, [VENDOR, HUAWEI], [TYPE, MOBILE]], [
483
475
 
484
476
  // Xiaomi
485
- /\b(poco[\w ]+)(?: bui|\))/i, // Xiaomi POCO
477
+ /\b(poco[\w ]+|m2\d{3}j\d\d[a-z]{2})(?: bui|\))/i, // Xiaomi POCO
486
478
  /\b; (\w+) build\/hm\1/i, // Xiaomi Hongmi 'numeric' models
487
479
  /\b(hm[-_ ]?note?[_ ]?(?:\d\w)?) bui/i, // Xiaomi Hongmi
488
480
  /\b(redmi[\-_ ]?(?:note|k)?[\w_ ]+)(?: bui|\))/i, // Xiaomi Redmi
@@ -590,7 +582,7 @@
590
582
  ], [MODEL, [VENDOR, 'Meizu'], [TYPE, MOBILE]], [
591
583
 
592
584
  // MIXED
593
- /(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus|dell|meizu|motorola|polytron)[-_ ]?([-\w]*)/i,
585
+ /(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus|dell|meizu|motorola|polytron|infinix|tecno)[-_ ]?([-\w]*)/i,
594
586
  // BlackBerry/BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron
595
587
  /(hp) ([\w ]+\w)/i, // HP iPAQ
596
588
  /(asus)-?(\w+)/i, // Asus
@@ -635,7 +627,7 @@
635
627
  ], [VENDOR, [MODEL, APPLE+' TV'], [TYPE, SMARTTV]], [
636
628
  /crkey/i // Google Chromecast
637
629
  ], [[MODEL, CHROME+'cast'], [VENDOR, GOOGLE], [TYPE, SMARTTV]], [
638
- /droid.+aft(\w)( bui|\))/i // Fire TV
630
+ /droid.+aft(\w+)( bui|\))/i // Fire TV
639
631
  ], [MODEL, [VENDOR, AMAZON], [TYPE, SMARTTV]], [
640
632
  /\(dtv[\);].+(aquos)/i,
641
633
  /(aquos-tv[\w ]+)\)/i // Sharp
@@ -740,7 +732,7 @@
740
732
 
741
733
  // iOS/macOS
742
734
  /ip[honead]{2,4}\b(?:.*os ([\w]+) like mac|; opera)/i, // iOS
743
- /ios;fbsv\/([\d\.]+)/i,
735
+ /(?:ios;fbsv\/|iphone.+ios[\/ ])([\d\.]+)/i,
744
736
  /cfnetwork\/.+darwin/i
745
737
  ], [[VERSION, /_/g, '.'], [NAME, 'iOS']], [
746
738
  /(mac os x) ?([\w\. ]*)/i,
@@ -809,23 +801,23 @@
809
801
 
810
802
  var defaultProps = (function () {
811
803
  var props = { init : {}, isIgnore : {}, isIgnoreRgx : {}, toString : {}};
812
- assignFromEntries.call(props.init, [
804
+ setProps.call(props.init, [
813
805
  [UA_BROWSER, [NAME, VERSION, MAJOR]],
814
806
  [UA_CPU, [ARCHITECTURE]],
815
807
  [UA_DEVICE, [TYPE, MODEL, VENDOR]],
816
808
  [UA_ENGINE, [NAME, VERSION]],
817
809
  [UA_OS, [NAME, VERSION]]
818
810
  ]);
819
- assignFromEntries.call(props.isIgnore, [
811
+ setProps.call(props.isIgnore, [
820
812
  [UA_BROWSER, [VERSION, MAJOR]],
821
813
  [UA_ENGINE, [VERSION]],
822
814
  [UA_OS, [VERSION]]
823
815
  ]);
824
- assignFromEntries.call(props.isIgnoreRgx, [
816
+ setProps.call(props.isIgnoreRgx, [
825
817
  [UA_BROWSER, / ?browser$/i],
826
818
  [UA_OS, / ?os$/i]
827
819
  ]);
828
- assignFromEntries.call(props.toString, [
820
+ setProps.call(props.toString, [
829
821
  [UA_BROWSER, [NAME, VERSION]],
830
822
  [UA_CPU, [ARCHITECTURE]],
831
823
  [UA_DEVICE, [VENDOR, MODEL]],
@@ -835,34 +827,47 @@
835
827
  return props;
836
828
  })();
837
829
 
838
- var createUAParserData = function (itemType, ua, rgxMap, uaCH) {
830
+ var createIData = function (item, itemType) {
839
831
 
840
832
  var init_props = defaultProps.init[itemType],
841
833
  is_ignoreProps = defaultProps.isIgnore[itemType] || 0,
842
834
  is_ignoreRgx = defaultProps.isIgnoreRgx[itemType] || 0,
843
835
  toString_props = defaultProps.toString[itemType] || 0;
844
836
 
845
- function UAParserData () {
846
- assignFromEntries.call(this, init_props);
837
+ function IData () {
838
+ setProps.call(this, init_props);
847
839
  }
848
- UAParserData.prototype.withClientHints = function () {
849
-
840
+
841
+ IData.prototype.getItem = function () {
842
+ return item;
843
+ };
844
+
845
+ IData.prototype.withClientHints = function () {
846
+
850
847
  // nodejs / non-client-hints browsers
851
848
  if (!NAVIGATOR_UADATA) {
852
- return new UAParserItem(itemType, ua, rgxMap, uaCH).parseCH().get();
849
+ return item
850
+ .parseCH()
851
+ .get();
853
852
  }
854
853
 
855
854
  // browsers based on chromium 85+
856
855
  return NAVIGATOR_UADATA
857
856
  .getHighEntropyValues(CH_ALL_VALUES)
858
857
  .then(function (res) {
859
- var JS_UACH = new UAParserDataCH(res, false);
860
- return new UAParserItem(itemType, ua, rgxMap, JS_UACH).parseCH().get();
858
+ return item
859
+ .setCH(new UACHData(res, false))
860
+ .parseCH()
861
+ .get();
861
862
  });
862
863
  };
863
864
 
865
+ IData.prototype.withFeatureCheck = function () {
866
+ return item.detectFeature().get();
867
+ };
868
+
864
869
  if (itemType != UA_RESULT) {
865
- UAParserData.prototype.is = function (strToCheck) {
870
+ IData.prototype.is = function (strToCheck) {
866
871
  var is = false;
867
872
  for (var i in this) {
868
873
  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 +880,7 @@
875
880
  }
876
881
  return is;
877
882
  };
878
- UAParserData.prototype.toString = function () {
883
+ IData.prototype.toString = function () {
879
884
  var str = EMPTY;
880
885
  for (var i in toString_props) {
881
886
  if (typeof(this[toString_props[i]]) !== UNDEF_TYPE) {
@@ -887,40 +892,39 @@
887
892
  }
888
893
 
889
894
  if (!NAVIGATOR_UADATA) {
890
- UAParserData.prototype.then = function (cb) {
895
+ IData.prototype.then = function (cb) {
891
896
  var that = this;
892
- var UAParserDataResolve = function () {
897
+ var IDataResolve = function () {
893
898
  for (var prop in that) {
894
899
  if (that.hasOwnProperty(prop)) {
895
900
  this[prop] = that[prop];
896
901
  }
897
902
  }
898
903
  };
899
- UAParserDataResolve.prototype = {
900
- is : UAParserData.prototype.is,
901
- toString : UAParserData.prototype.toString
904
+ IDataResolve.prototype = {
905
+ is : IData.prototype.is,
906
+ toString : IData.prototype.toString
902
907
  };
903
- var resolveData = new UAParserDataResolve();
908
+ var resolveData = new IDataResolve();
904
909
  cb(resolveData);
905
910
  return resolveData;
906
911
  };
907
912
  }
908
913
 
909
- return new UAParserData();
914
+ return new IData();
910
915
  };
911
916
 
912
917
  /////////////////
913
918
  // Constructor
914
919
  ////////////////
915
920
 
916
- function UAParserDataCH (uach, isHTTP_UACH) {
921
+ function UACHData (uach, isHttpUACH) {
917
922
  uach = uach || {};
918
- assignFromEntries.call(this, CH_ALL_VALUES);
919
- if (isHTTP_UACH) {
920
- assignFromEntries.call(this, [
923
+ setProps.call(this, CH_ALL_VALUES);
924
+ if (isHttpUACH) {
925
+ setProps.call(this, [
921
926
  [BRANDS, itemListToArray(uach[CH_HEADER])],
922
927
  [FULLVERLIST, itemListToArray(uach[CH_HEADER_FULL_VER_LIST])],
923
- [BRANDS, itemListToArray(uach[CH_HEADER])],
924
928
  [MOBILE, /\?1/.test(uach[CH_HEADER_MOBILE])],
925
929
  [MODEL, stripQuotes(uach[CH_HEADER_MODEL])],
926
930
  [PLATFORM, stripQuotes(uach[CH_HEADER_PLATFORM])],
@@ -933,127 +937,151 @@
933
937
  if(this.hasOwnProperty(prop) && typeof uach[prop] !== UNDEF_TYPE) this[prop] = uach[prop];
934
938
  }
935
939
  }
936
- return this;
937
940
  }
938
941
 
939
- function UAParserItem (itemType, ua, rgxMap, uaCH) {
940
- assignFromEntries.call(this, [
942
+ function UAItem (itemType, ua, rgxMap, uaCH) {
943
+
944
+ this.get = function (prop) {
945
+ if (!prop) return this.data;
946
+ return this.data.hasOwnProperty(prop) ? this.data[prop] : undefined;
947
+ };
948
+
949
+ this.set = function (prop, val) {
950
+ this.data[prop] = val;
951
+ return this;
952
+ };
953
+
954
+ this.setCH = function (ch) {
955
+ this.uaCH = ch;
956
+ return this;
957
+ };
958
+
959
+ this.detectFeature = function () {
960
+ if (NAVIGATOR && NAVIGATOR.userAgent == this.ua) {
961
+ switch (this.itemType) {
962
+ case UA_BROWSER:
963
+ // Brave-specific detection
964
+ if (NAVIGATOR.brave && typeof NAVIGATOR.brave.isBrave == FUNC_TYPE) {
965
+ this.set(NAME, 'Brave');
966
+ }
967
+ break;
968
+ case UA_DEVICE:
969
+ // Chrome-specific detection: check for 'mobile' value of navigator.userAgentData
970
+ if (!this.get(TYPE) && NAVIGATOR_UADATA && NAVIGATOR_UADATA[MOBILE]) {
971
+ this.set(TYPE, MOBILE);
972
+ }
973
+ // iPadOS-specific detection: identified as Mac, but has some iOS-only properties
974
+ if (this.get(MODEL) == 'Macintosh' && NAVIGATOR && typeof NAVIGATOR.standalone !== UNDEF_TYPE && NAVIGATOR.maxTouchPoints && NAVIGATOR.maxTouchPoints > 2) {
975
+ this.set(MODEL, 'iPad')
976
+ .set(TYPE, TABLET);
977
+ }
978
+ break;
979
+ case UA_OS:
980
+ // Chrome-specific detection: check for 'platform' value of navigator.userAgentData
981
+ if (!this.get(NAME) && NAVIGATOR_UADATA && NAVIGATOR_UADATA[PLATFORM]) {
982
+ this.set(NAME, NAVIGATOR_UADATA[PLATFORM]);
983
+ }
984
+ break;
985
+ case UA_RESULT:
986
+ var data = this.data;
987
+ var detect = function (itemType) {
988
+ return data[itemType]
989
+ .getItem()
990
+ .detectFeature()
991
+ .get();
992
+ };
993
+ this.set(UA_BROWSER, detect(UA_BROWSER))
994
+ .set(UA_CPU, detect(UA_CPU))
995
+ .set(UA_DEVICE, detect(UA_DEVICE))
996
+ .set(UA_ENGINE, detect(UA_ENGINE))
997
+ .set(UA_OS, detect(UA_OS));
998
+ }
999
+ }
1000
+ return this;
1001
+ };
1002
+
1003
+ this.parseUA = function () {
1004
+ if (this.itemType != UA_RESULT) {
1005
+ rgxMapper.call(this.data, this.ua, this.rgxMap);
1006
+ }
1007
+ if (this.itemType == UA_BROWSER) {
1008
+ this.set(MAJOR, majorize(this.get(VERSION)));
1009
+ }
1010
+ return this;
1011
+ };
1012
+
1013
+ this.parseCH = function () {
1014
+ var ua = this.ua,
1015
+ uaCH = this.uaCH,
1016
+ rgxMap = this.rgxMap;
1017
+
1018
+ switch (this.itemType) {
1019
+ case UA_BROWSER:
1020
+ var brands = uaCH[FULLVERLIST] || uaCH[BRANDS];
1021
+ if (brands) {
1022
+ for (var i in brands) {
1023
+ var brandName = brands[i].brand,
1024
+ brandVersion = brands[i].version;
1025
+ if (!/not.a.brand/i.test(brandName) && (i < 1 || /chromi/i.test(this.get(NAME)))) {
1026
+ this.set(NAME, strip(GOOGLE+' ', brandName))
1027
+ .set(VERSION, brandVersion)
1028
+ .set(MAJOR, majorize(brandVersion));
1029
+ }
1030
+ }
1031
+ }
1032
+ break;
1033
+ case UA_CPU:
1034
+ var archName = uaCH[ARCHITECTURE];
1035
+ if (archName) {
1036
+ if (archName && uaCH[BITNESS] == '64') archName += '64';
1037
+ rgxMapper.call(this.data, archName + ';', rgxMap);
1038
+ }
1039
+ break;
1040
+ case UA_DEVICE:
1041
+ if (uaCH[MOBILE]) {
1042
+ this.set(TYPE, MOBILE);
1043
+ }
1044
+ if (uaCH[MODEL]) {
1045
+ this.set(MODEL, uaCH[MODEL]);
1046
+ }
1047
+ break;
1048
+ case UA_OS:
1049
+ var osName = uaCH[PLATFORM];
1050
+ if(osName) {
1051
+ var osVersion = uaCH[PLATFORMVER];
1052
+ if (osName == WINDOWS) osVersion = (parseInt(majorize(osVersion), 10) >= 13 ? '11' : '10');
1053
+ this.set(NAME, osName)
1054
+ .set(VERSION, osVersion);
1055
+ }
1056
+ break;
1057
+ case UA_RESULT:
1058
+ var data = this.data;
1059
+ var parse = function (itemType) {
1060
+ return data[itemType]
1061
+ .getItem()
1062
+ .setCH(uaCH)
1063
+ .parseCH()
1064
+ .get();
1065
+ };
1066
+ this.set(UA_BROWSER, parse(UA_BROWSER))
1067
+ .set(UA_CPU, parse(UA_CPU))
1068
+ .set(UA_DEVICE, parse(UA_DEVICE))
1069
+ .set(UA_ENGINE, parse(UA_ENGINE))
1070
+ .set(UA_OS, parse(UA_OS));
1071
+ }
1072
+ return this;
1073
+ };
1074
+
1075
+ setProps.call(this, [
941
1076
  ['itemType', itemType],
942
1077
  ['ua', ua],
943
1078
  ['uaCH', uaCH],
944
1079
  ['rgxMap', rgxMap],
945
- ['data', createUAParserData(itemType, ua, rgxMap, uaCH)]
1080
+ ['data', createIData(this, itemType)]
946
1081
  ]);
947
- this.parse();
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
- }
1082
+
984
1083
  return this;
985
1084
  }
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
1085
 
1058
1086
  function UAParser (ua, extensions, headers) {
1059
1087
 
@@ -1077,39 +1105,54 @@
1077
1105
  return new UAParser(ua, extensions, headers).getResult();
1078
1106
  }
1079
1107
 
1080
- var userAgent = ua ||
1081
- ((NAVIGATOR && NAVIGATOR.userAgent) ?
1082
- NAVIGATOR.userAgent :
1083
- (headers && headers[USER_AGENT] ?
1084
- headers[USER_AGENT] :
1085
- EMPTY)),
1086
-
1087
- HTTP_UACH = new UAParserDataCH(headers, true),
1108
+ var userAgent = typeof ua === STR_TYPE ? ua : // Passed user-agent string
1109
+ ((NAVIGATOR && NAVIGATOR.userAgent) ? NAVIGATOR.userAgent : // navigator.userAgent
1110
+ (headers && headers[USER_AGENT] ? headers[USER_AGENT] : // User-Agent from passed headers
1111
+ EMPTY)), // empty string
1088
1112
 
1113
+ httpUACH = new UACHData(headers, true),
1089
1114
  regexMap = extensions ?
1090
1115
  extend(defaultRegexes, extensions) :
1091
1116
  defaultRegexes,
1092
1117
 
1093
- createUAParserItemFunc = function (itemType) {
1094
- return function () {
1095
- return new UAParserItem(itemType, userAgent, itemType == UA_RESULT ? regexMap : regexMap[itemType], HTTP_UACH).get();
1096
- };
1118
+ createItemFunc = function (itemType) {
1119
+ if (itemType == UA_RESULT) {
1120
+ return function () {
1121
+ return new UAItem(itemType, userAgent, regexMap, httpUACH)
1122
+ .set('ua', userAgent)
1123
+ .set(UA_BROWSER, this.getBrowser())
1124
+ .set(UA_CPU, this.getCPU())
1125
+ .set(UA_DEVICE, this.getDevice())
1126
+ .set(UA_ENGINE, this.getEngine())
1127
+ .set(UA_OS, this.getOS())
1128
+ .get();
1129
+ };
1130
+ } else {
1131
+ return function () {
1132
+ return new UAItem(itemType, userAgent, regexMap[itemType], httpUACH)
1133
+ .parseUA()
1134
+ .get();
1135
+ };
1136
+ }
1097
1137
  };
1098
-
1138
+
1099
1139
  // public methods
1100
- assignFromEntries.call(this, [
1101
- ['getBrowser', createUAParserItemFunc(UA_BROWSER)],
1102
- ['getCPU', createUAParserItemFunc(UA_CPU)],
1103
- ['getDevice', createUAParserItemFunc(UA_DEVICE)],
1104
- ['getEngine', createUAParserItemFunc(UA_ENGINE)],
1105
- ['getOS', createUAParserItemFunc(UA_OS)],
1106
- ['getResult', createUAParserItemFunc(UA_RESULT)],
1140
+ setProps.call(this, [
1141
+ ['getBrowser', createItemFunc(UA_BROWSER)],
1142
+ ['getCPU', createItemFunc(UA_CPU)],
1143
+ ['getDevice', createItemFunc(UA_DEVICE)],
1144
+ ['getEngine', createItemFunc(UA_ENGINE)],
1145
+ ['getOS', createItemFunc(UA_OS)],
1146
+ ['getResult', createItemFunc(UA_RESULT)],
1107
1147
  ['getUA', function () { return userAgent; }],
1108
1148
  ['setUA', function (ua) {
1109
- userAgent = (typeof ua === STR_TYPE && ua.length > UA_MAX_LENGTH) ? trim(ua, UA_MAX_LENGTH) : ua;
1149
+ if (typeof ua === STR_TYPE)
1150
+ userAgent = ua.length > UA_MAX_LENGTH ? trim(ua, UA_MAX_LENGTH) : ua;
1110
1151
  return this;
1111
1152
  }]
1112
- ]).setUA(userAgent);
1153
+ ])
1154
+ .setUA(userAgent);
1155
+
1113
1156
  return this;
1114
1157
  }
1115
1158