ua-parser-js 2.0.3 → 2.0.4

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.
@@ -3,7 +3,7 @@
3
3
  // Source: /src/main/ua-parser.js
4
4
 
5
5
  /////////////////////////////////////////////////////////////////////////////////
6
- /* UAParser.js v2.0.3
6
+ /* UAParser.js v2.0.4
7
7
  Copyright © 2012-2025 Faisal Salman <f@faisalman.com>
8
8
  AGPLv3 License *//*
9
9
  Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data.
@@ -21,7 +21,7 @@
21
21
  // Constants
22
22
  /////////////
23
23
 
24
- var LIBVERSION = '2.0.3',
24
+ var LIBVERSION = '2.0.4',
25
25
  UA_MAX_LENGTH = 500,
26
26
  USER_AGENT = 'user-agent',
27
27
  EMPTY = '',
@@ -154,11 +154,11 @@
154
154
  has = function (str1, str2) {
155
155
  if (typeof str1 === OBJ_TYPE && str1.length > 0) {
156
156
  for (var i in str1) {
157
- if (lowerize(str1[i]) == lowerize(str2)) return true;
157
+ if (lowerize(str2) == lowerize(str1[i])) return true;
158
158
  }
159
159
  return false;
160
160
  }
161
- return isString(str1) ? lowerize(str2).indexOf(lowerize(str1)) !== -1 : false;
161
+ return isString(str1) ? lowerize(str2) == lowerize(str1) : false;
162
162
  },
163
163
  isExtensions = function (obj, deep) {
164
164
  for (var prop in obj) {
@@ -249,17 +249,25 @@
249
249
  // assign given value, ignore regex match
250
250
  this[q[0]] = q[1];
251
251
  }
252
- } else if (q.length === 3) {
253
- // check whether function or regex
252
+ } else if (q.length >= 3) {
253
+ // Check whether q[1] FUNCTION or REGEX
254
254
  if (typeof q[1] === FUNC_TYPE && !(q[1].exec && q[1].test)) {
255
- // call function (usually string mapper)
256
- this[q[0]] = match ? q[1].call(this, match, q[2]) : undefined;
255
+ if (q.length > 3) {
256
+ this[q[0]] = match ? q[1].apply(this, q.slice(2)) : undefined;
257
+ } else {
258
+ // call function (usually string mapper)
259
+ this[q[0]] = match ? q[1].call(this, match, q[2]) : undefined;
260
+ }
257
261
  } else {
258
- // sanitize match using given regex
259
- this[q[0]] = match ? match.replace(q[1], q[2]) : undefined;
262
+ if (q.length == 3) {
263
+ // sanitize match using given regex
264
+ this[q[0]] = match ? match.replace(q[1], q[2]) : undefined;
265
+ } else if (q.length == 4) {
266
+ this[q[0]] = match ? q[3].call(this, match.replace(q[1], q[2])) : undefined;
267
+ } else if (q.length > 4) {
268
+ this[q[0]] = match ? q[3].apply(this, [match.replace(q[1], q[2])].concat(q.slice(4))) : undefined;
269
+ }
260
270
  }
261
- } else if (q.length === 4) {
262
- this[q[0]] = match ? q[3].call(this, match.replace(q[1], q[2])) : undefined;
263
271
  }
264
272
  } else {
265
273
  this[q] = match ? match : undefined;
@@ -293,17 +301,17 @@
293
301
  //////////////
294
302
 
295
303
  var windowsVersionMap = {
296
- 'ME' : '4.90',
297
- 'NT 3.11' : 'NT3.51',
298
- 'NT 4.0' : 'NT4.0',
299
- '2000' : 'NT 5.0',
300
- 'XP' : ['NT 5.1', 'NT 5.2'],
301
- 'Vista' : 'NT 6.0',
302
- '7' : 'NT 6.1',
303
- '8' : 'NT 6.2',
304
- '8.1' : 'NT 6.3',
305
- '10' : ['NT 6.4', 'NT 10.0'],
306
- 'RT' : 'ARM'
304
+ 'ME' : '4.90',
305
+ 'NT 3.51': '3.51',
306
+ 'NT 4.0': '4.0',
307
+ '2000' : ['5.0', '5.01'],
308
+ 'XP' : ['5.1', '5.2'],
309
+ 'Vista' : '6.0',
310
+ '7' : '6.1',
311
+ '8' : '6.2',
312
+ '8.1' : '6.3',
313
+ '10' : ['6.4', '10.0'],
314
+ 'NT' : ''
307
315
  },
308
316
 
309
317
  formFactorsMap = {
@@ -315,6 +323,18 @@
315
323
  'xr' : ['VR', 'XR'],
316
324
  '?' : ['Desktop', 'Unknown'],
317
325
  '*' : undefined
326
+ },
327
+
328
+ browserHintsMap = {
329
+ 'Chrome' : 'Google Chrome',
330
+ 'Edge' : 'Microsoft Edge',
331
+ 'Edge WebView2' : 'Microsoft Edge WebView2',
332
+ 'Chrome WebView': 'Android WebView',
333
+ 'Chrome Headless':'HeadlessChrome',
334
+ 'Huawei Browser': 'HuaweiBrowser',
335
+ 'MIUI Browser' : 'Miui Browser',
336
+ 'Opera Mobi' : 'OperaMobile',
337
+ 'Yandex' : 'YaBrowser'
318
338
  };
319
339
 
320
340
  //////////////
@@ -328,7 +348,9 @@
328
348
  // Most common regardless engine
329
349
  /\b(?:crmo|crios)\/([\w\.]+)/i // Chrome for Android/iOS
330
350
  ], [VERSION, [NAME, PREFIX_MOBILE + 'Chrome']], [
331
- /edg(?:e|ios|a)?\/([\w\.]+)/i // Microsoft Edge
351
+ /webview.+edge\/([\w\.]+)/i // Microsoft Edge
352
+ ], [VERSION, [NAME, EDGE+' WebView']], [
353
+ /edg(?:e|ios|a)?\/([\w\.]+)/i
332
354
  ], [VERSION, [NAME, 'Edge']], [
333
355
 
334
356
  // Presto based
@@ -420,7 +442,6 @@
420
442
  // WebView
421
443
  /((?:fban\/fbios|fb_iab\/fb4a)(?!.+fbav)|;fbav\/([\w\.]+);)/i // Facebook App for iOS & Android
422
444
  ], [[NAME, FACEBOOK], VERSION, [TYPE, INAPP]], [
423
- /(Klarna)\/([\w\.]+)/i, // Klarna Shopping Browser for iOS & Android
424
445
  /(kakao(?:talk|story))[\/ ]([\w\.]+)/i, // Kakao App
425
446
  /(naver)\(.*?(\d+\.[\w\.]+).*\)/i, // Naver InApp
426
447
  /(daum)apps[\/ ]([\w\.]+)/i, // Daum App
@@ -428,7 +449,7 @@
428
449
  /\b(line)\/([\w\.]+)\/iab/i, // Line App for Android
429
450
  /(alipay)client\/([\w\.]+)/i, // Alipay
430
451
  /(twitter)(?:and| f.+e\/([\w\.]+))/i, // Twitter
431
- /(instagram|snapchat)[\/ ]([-\w\.]+)/i // Instagram/Snapchat
452
+ /(instagram|snapchat|klarna)[\/ ]([-\w\.]+)/i // Instagram/Snapchat/Klarna
432
453
  ], [NAME, VERSION, [TYPE, INAPP]], [
433
454
  /\bgsa\/([\w\.]+) .*safari\//i // Google Search Appliance on iOS
434
455
  ], [VERSION, [NAME, 'GSA'], [TYPE, INAPP]], [
@@ -443,6 +464,9 @@
443
464
  /headlesschrome(?:\/([\w\.]+)| )/i // Chrome Headless
444
465
  ], [VERSION, [NAME, CHROME+' Headless']], [
445
466
 
467
+ /wv\).+chrome\/([\w\.]+).+edgw\//i // Edge WebView2
468
+ ], [VERSION, [NAME, EDGE+' WebView2']], [
469
+
446
470
  / wv\).+(chrome)\/([\w\.]+)/i // Chrome WebView
447
471
  ], [[NAME, CHROME+' WebView'], VERSION], [
448
472
 
@@ -535,7 +559,7 @@
535
559
  /\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
536
560
  ], [MODEL, [VENDOR, SAMSUNG], [TYPE, TABLET]], [
537
561
  /\b((?:s[cgp]h|gt|sm)-(?![lr])\w+|sc[g-]?[\d]+a?|galaxy nexus)/i,
538
- /samsung[- ]((?!sm-[lr])[-\w]+)/i,
562
+ /samsung[- ]((?!sm-[lr]|browser)[-\w]+)/i,
539
563
  /sec-(sgh\w+)/i
540
564
  ], [MODEL, [VENDOR, SAMSUNG], [TYPE, MOBILE]], [
541
565
 
@@ -580,16 +604,22 @@
580
604
  / ([\w ]+) miui\/v?\d/i
581
605
  ], [[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, MOBILE]], [
582
606
 
607
+ // OnePlus
608
+ /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,
609
+ /(?:one)?(?:plus)? (a\d0\d\d)(?: b|\))/i
610
+ ], [MODEL, [VENDOR, ONEPLUS], [TYPE, MOBILE]], [
611
+
583
612
  // OPPO
584
613
  /; (\w+) bui.+ oppo/i,
585
614
  /\b(cph[12]\d{3}|p(?:af|c[al]|d\w|e[ar])[mt]\d0|x9007|a101op)\b/i
586
615
  ], [MODEL, [VENDOR, OPPO], [TYPE, MOBILE]], [
587
616
  /\b(opd2(\d{3}a?))(?: bui|\))/i
588
- ], [MODEL, [VENDOR, strMapper, { 'OnePlus' : ['304', '403', '203'], '*' : OPPO }], [TYPE, TABLET]], [
617
+ ], [MODEL, [VENDOR, strMapper, { 'OnePlus' : ['203', '304', '403', '404', '413', '415'], '*' : OPPO }], [TYPE, TABLET]], [
618
+
619
+ // BLU
620
+ /(vivo (5r?|6|8l?|go|one|s|x[il]?[2-4]?)[\w\+ ]*)(?: bui|\))/i // Vivo series
621
+ ], [MODEL, [VENDOR, 'BLU'], [TYPE, MOBILE]], [
589
622
 
590
- // BLU Vivo Series
591
- /(vivo (5r?|6|8l?|go|one|s|x[il]?[2-4]?)[\w\+ ]*)(?: bui|\))/i
592
- ], [MODEL, [VENDOR, 'BLU'], [TYPE, MOBILE]], [
593
623
  // Vivo
594
624
  /; vivo (\w+)(?: bui|\))/i,
595
625
  /\b(v[12]\d{3}\w?[at])(?: bui|;)/i
@@ -599,10 +629,17 @@
599
629
  /\b(rmx[1-3]\d{3})(?: bui|;|\))/i
600
630
  ], [MODEL, [VENDOR, 'Realme'], [TYPE, MOBILE]], [
601
631
 
632
+ // Lenovo
633
+ /(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,
634
+ /lenovo ?(b[68]0[08]0-?[hf]?|tab(?:[\w- ]+?)|tb[\w-]{6,7})( bui|;|\)|\/)/i
635
+ ], [MODEL, [VENDOR, LENOVO], [TYPE, TABLET]], [
636
+ /lenovo[-_ ]?([-\w ]+?)(?: bui|\)|\/)/i
637
+ ], [MODEL, [VENDOR, LENOVO], [TYPE, MOBILE]], [
638
+
602
639
  // Motorola
603
640
  /\b(milestone|droid(?:[2-4x]| (?:bionic|x2|pro|razr))?:?( 4g)?)\b[\w ]+build\//i,
604
- /\bmot(?:orola)?[- ](\w*)/i,
605
- /((?:moto(?! 360)[\w\(\) ]+|xt\d{3,4}|nexus 6)(?= bui|\)))/i
641
+ /\bmot(?:orola)?[- ]([\w\s]+)(\)| bui)/i,
642
+ /((?:moto(?! 360)[-\w\(\) ]+|xt\d{3,4}[cgkosw\+]?[-\d]*|nexus 6)(?= bui|\)))/i
606
643
  ], [MODEL, [VENDOR, MOTOROLA], [TYPE, MOBILE]], [
607
644
  /\b(mz60\d|xoom[2 ]{0,2}) build\//i
608
645
  ], [MODEL, [VENDOR, MOTOROLA], [TYPE, TABLET]], [
@@ -611,15 +648,10 @@
611
648
  /((?=lg)?[vl]k\-?\d{3}) bui| 3\.[-\w; ]{10}lg?-([06cv9]{3,4})/i
612
649
  ], [MODEL, [VENDOR, LG], [TYPE, TABLET]], [
613
650
  /(lm(?:-?f100[nv]?|-[\w\.]+)(?= bui|\))|nexus [45])/i,
614
- /\blg[-e;\/ ]+(?!.*(?:browser|netcast|android tv|watch))(\w+)/i,
651
+ /\blg[-e;\/ ]+(?!.*(?:browser|netcast|android tv|watch|webos))(\w+)/i,
615
652
  /\blg-?([\d\w]+) bui/i
616
653
  ], [MODEL, [VENDOR, LG], [TYPE, MOBILE]], [
617
654
 
618
- // Lenovo
619
- /(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,
620
- /lenovo ?(b[68]0[08]0-?[hf]?|tab(?:[\w- ]+?)|tb[\w-]{6,7})( bui|;|\)|\/)/i
621
- ], [MODEL, [VENDOR, LENOVO], [TYPE, TABLET]], [
622
-
623
655
  // Nokia
624
656
  /(nokia) (t[12][01])/i
625
657
  ], [VENDOR, MODEL, [TYPE, TABLET]], [
@@ -630,21 +662,19 @@
630
662
  // Google
631
663
  /(pixel (c|tablet))\b/i // Google Pixel C/Tablet
632
664
  ], [MODEL, [VENDOR, GOOGLE], [TYPE, TABLET]], [
633
- /droid.+; (pixel[\daxl ]{0,6})(?: bui|\))/i // Google Pixel
665
+ // Google Pixel
666
+ /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
634
667
  ], [MODEL, [VENDOR, GOOGLE], [TYPE, MOBILE]], [
668
+ /(google) (pixelbook( go)?)/i
669
+ ], [VENDOR, MODEL], [
635
670
 
636
671
  // Sony
637
- /droid.+; (a?\d[0-2]{2}so|[c-g]\d{4}|so[-gl]\w+|xq-a\w[4-7][12])(?= bui|\).+chrome\/(?![1-6]{0,1}\d\.))/i
672
+ /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
638
673
  ], [MODEL, [VENDOR, SONY], [TYPE, MOBILE]], [
639
674
  /sony tablet [ps]/i,
640
675
  /\b(?:sony)?sgp\w+(?: bui|\))/i
641
676
  ], [[MODEL, 'Xperia Tablet'], [VENDOR, SONY], [TYPE, TABLET]], [
642
677
 
643
- // OnePlus
644
- / (kb2005|in20[12]5|be20[12][59])\b/i,
645
- /(?:one)?(?:plus)? (a\d0\d\d)(?: b|\))/i
646
- ], [MODEL, [VENDOR, ONEPLUS], [TYPE, MOBILE]], [
647
-
648
678
  // Amazon
649
679
  /(alexa)webm/i,
650
680
  /(kf[a-z]{2}wi|aeo(?!bc)\w\w)( bui|\))/i, // Kindle Fire without Silk / Echo Show
@@ -715,7 +745,7 @@
715
745
  ], [MODEL, [VENDOR, 'Smartfren'], [TYPE, MOBILE]], [
716
746
 
717
747
  // Nothing
718
- /droid.+; (a(?:015|06[35]|142p?))/i
748
+ /droid.+; (a(in)?(0(15|59|6[35])|142)p?)/i
719
749
  ], [MODEL, [VENDOR, 'Nothing'], [TYPE, MOBILE]], [
720
750
 
721
751
  // Archos
@@ -726,17 +756,20 @@
726
756
  /; (ac[3-6]\d\w{2,8})( b|\))/i
727
757
  ], [MODEL, [VENDOR, 'Archos'], [TYPE, MOBILE]], [
728
758
 
759
+ // HMD
760
+ /; (n159v)/i
761
+ ], [MODEL, [VENDOR, 'HMD'], [TYPE, MOBILE]], [
762
+
729
763
  // MIXED
730
764
  /(imo) (tab \w+)/i, // IMO
731
- /(infinix) (x1101b?)/i // Infinix XPad
765
+ /(infinix|tecno) (x1101b?|p904|dp(7c|8d|10a)( pro)?|p70[1-3]a?|p904|t1101)/i // Infinix XPad / Tecno
732
766
  ], [VENDOR, MODEL, [TYPE, TABLET]], [
733
767
 
734
- /(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus(?! zenw)|dell|jolla|meizu|motorola|polytron|infinix|tecno|micromax|advan)[-_ ]?([-\w]*)/i,
735
- // BlackBerry/BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron/Infinix/Tecno/Micromax/Advan
736
- /; (blu|hmd|imo|tcl)[_ ]([\w\+ ]+?)(?: bui|\)|; r)/i, // BLU/HMD/IMO/TCL
768
+ /(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus(?! zenw)|dell|jolla|meizu|motorola|polytron|tecno|micromax|advan)[-_ ]?([-\w]*)/i,
769
+ // BlackBerry/BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron/Tecno/Micromax/Advan
770
+ /; (blu|hmd|imo|infinix|lava|oneplus|tcl)[_ ]([\w\+ ]+?)(?: bui|\)|; r)/i, // BLU/HMD/IMO/Infinix/Lava/OnePlus/TCL
737
771
  /(hp) ([\w ]+\w)/i, // HP iPAQ
738
772
  /(microsoft); (lumia[\w ]+)/i, // Microsoft Lumia
739
- /(lenovo)[-_ ]?([-\w ]+?)(?: bui|\)|\/)/i, // Lenovo
740
773
  /(oppo) ?([\w ]+) bui/i // OPPO
741
774
  ], [VENDOR, MODEL, [TYPE, MOBILE]], [
742
775
 
@@ -768,6 +801,7 @@
768
801
  ], [VENDOR, [TYPE, SMARTTV]], [
769
802
  /hbbtv.+maple;(\d+)/i
770
803
  ], [[MODEL, /^/, 'SmartTV'], [VENDOR, SAMSUNG], [TYPE, SMARTTV]], [
804
+ /(vizio)(?: |.+model\/)(\w+-\w+)/i, // Vizio
771
805
  /tcast.+(lg)e?. ([-\w]+)/i // LG SmartTV
772
806
  ], [VENDOR, MODEL, [TYPE, SMARTTV]], [
773
807
  /(nux; netcast.+smarttv|lg (netcast\.tv-201\d|android tv))/i
@@ -799,26 +833,27 @@
799
833
  ], [VENDOR, MODEL, [TYPE, SMARTTV]], [
800
834
  /\b(roku)[\dx]*[\)\/]((?:dvp-)?[\d\.]*)/i, // Roku
801
835
  /hbbtv\/\d+\.\d+\.\d+ +\([\w\+ ]*; *([\w\d][^;]*);([^;]*)/i // HbbTV devices
802
- ], [[VENDOR, trim], [MODEL, trim], [TYPE, SMARTTV]], [
836
+ ], [[VENDOR, /.+\/(\w+)/, '$1', strMapper, {'LG':'lge'}], [MODEL, trim], [TYPE, SMARTTV]], [
803
837
  // SmartTV from Unidentified Vendors
804
838
  /droid.+; ([\w- ]+) (?:android tv|smart[- ]?tv)/i
805
839
  ], [MODEL, [TYPE, SMARTTV]], [
806
- /\b(android tv|smart[- ]?tv|opera tv|tv; rv:)\b/i
840
+ /\b(android tv|smart[- ]?tv|opera tv|tv; rv:|large screen[\w ]+safari)\b/i
807
841
  ], [[TYPE, SMARTTV]], [
808
842
 
809
843
  ///////////////////
810
844
  // CONSOLES
811
845
  ///////////////////
812
846
 
813
- /(ouya)/i, // Ouya
814
- /(nintendo) (\w+)/i // Nintendo
815
- ], [VENDOR, MODEL, [TYPE, CONSOLE]], [
816
- /droid.+; (shield)( bui|\))/i // Nvidia Portable
817
- ], [MODEL, [VENDOR, NVIDIA], [TYPE, CONSOLE]], [
818
847
  /(playstation \w+)/i // Playstation
819
848
  ], [MODEL, [VENDOR, SONY], [TYPE, CONSOLE]], [
820
849
  /\b(xbox(?: one)?(?!; xbox))[\); ]/i // Microsoft Xbox
821
850
  ], [MODEL, [VENDOR, MICROSOFT], [TYPE, CONSOLE]], [
851
+ /(ouya)/i, // Ouya
852
+ /(nintendo) (\w+)/i, // Nintendo
853
+ /(retroid) (pocket ([^\)]+))/i // Retroid Pocket
854
+ ], [VENDOR, MODEL, [TYPE, CONSOLE]], [
855
+ /droid.+; (shield)( bui|\))/i // Nvidia Portable
856
+ ], [MODEL, [VENDOR, NVIDIA], [TYPE, CONSOLE]], [
822
857
 
823
858
  ///////////////////
824
859
  // WEARABLES
@@ -854,6 +889,8 @@
854
889
  ], [VENDOR, MODEL, [TYPE, XR]], [
855
890
  /(quest( \d| pro)?s?).+vr/i // Meta Quest
856
891
  ], [MODEL, [VENDOR, FACEBOOK], [TYPE, XR]], [
892
+ /mobile vr; rv.+firefox/i // Unidentifiable VR device using Firefox Reality / Wolvic
893
+ ], [[TYPE, XR]], [
857
894
 
858
895
  ///////////////////
859
896
  // EMBEDDED
@@ -865,7 +902,7 @@
865
902
  ], [MODEL, [VENDOR, AMAZON], [TYPE, EMBEDDED]], [
866
903
  /(homepod).+mac os/i // Apple HomePod
867
904
  ], [MODEL, [VENDOR, APPLE], [TYPE, EMBEDDED]], [
868
- /windows iot/i
905
+ /windows iot/i // Unidentifiable embedded device using Windows IoT
869
906
  ], [[TYPE, EMBEDDED]], [
870
907
 
871
908
  ////////////////////
@@ -911,14 +948,17 @@
911
948
  os : [[
912
949
 
913
950
  // Windows
914
- /microsoft (windows) (vista|xp)/i // Windows (iTunes)
951
+ /(windows nt) (6\.[23]); arm/i // Windows RT
952
+ ], [[NAME, /N/, 'R'], [VERSION, strMapper, windowsVersionMap]], [
953
+ /(windows (?:phone|mobile|iot))(?: os)?[\/ ]?([\d\.]*( se)?)/i, // Windows IoT/Mobile/Phone
954
+ // Windows NT/3.1/95/98/ME/2000/XP/Vista/7/8/8.1/10/11
955
+ /(windows)[\/ ](1[01]|2000|3\.1|7|8(\.1)?|9[58]|me|server 20\d\d( r2)?|vista|xp)/i
956
+ ], [NAME, VERSION], [
957
+ /windows nt ?([\d\.\)]*)(?!.+xbox)/i,
958
+ /\bwin(?=3| ?9|n)(?:nt| 9x )?([\d\.;]*)/i
959
+ ], [[VERSION, /(;|\))/g, '', strMapper, windowsVersionMap], [NAME, WINDOWS]], [
960
+ /(windows ce)\/?([\d\.]*)/i // Windows CE
915
961
  ], [NAME, VERSION], [
916
- /(windows (?:phone(?: os)?|mobile|iot))[\/ ]?([\d\.\w ]*)/i // Windows Phone
917
- ], [NAME, [VERSION, strMapper, windowsVersionMap]], [
918
- /windows nt 6\.2; (arm)/i, // Windows RT
919
- /windows[\/ ]([ntce\d\. ]+\w)(?!.+xbox)/i,
920
- /(?:win(?=3|9|n)|win 9x )([nt\d\.]+)/i
921
- ], [[VERSION, strMapper, windowsVersionMap], [NAME, WINDOWS]], [
922
962
 
923
963
  // iOS/macOS
924
964
  /[adehimnop]{4,7}\b(?:.*os ([\w]+) like mac|; opera)/i, // iOS
@@ -926,7 +966,7 @@
926
966
  /cfnetwork\/.+darwin/i
927
967
  ], [[VERSION, /_/g, '.'], [NAME, 'iOS']], [
928
968
  /(mac os x) ?([\w\. ]*)/i,
929
- /(macintosh|mac_powerpc\b)(?!.+haiku)/i // Mac OS
969
+ /(macintosh|mac_powerpc\b)(?!.+(haiku|morphos))/i // Mac OS
930
970
  ], [[NAME, 'macOS'], [VERSION, /_/g, '.']], [
931
971
 
932
972
  // Google Chromecast
@@ -942,12 +982,13 @@
942
982
  ], [VERSION, [NAME, CHROMECAST]], [
943
983
 
944
984
  // Mobile OSes
945
- /droid ([\w\.]+)\b.+(android[- ]x86|harmonyos)/i // Android-x86/HarmonyOS
985
+ /droid ([\w\.]+)\b.+(android[- ]x86)/i // Android-x86
946
986
  ], [VERSION, NAME], [
947
987
  /(ubuntu) ([\w\.]+) like android/i // Ubuntu Touch
948
988
  ], [[NAME, /(.+)/, '$1 Touch'], VERSION], [
989
+ /(harmonyos)[\/ ]?([\d\.]*)/i, // HarmonyOS
949
990
  // Android/Blackberry/WebOS/QNX/Bada/RIM/KaiOS/Maemo/MeeGo/S40/Sailfish OS/OpenHarmony/Tizen
950
- /(android|bada|blackberry|kaios|maemo|meego|openharmony|qnx|rim tablet os|sailfish|series40|symbian|tizen|webos)\w*[-\/\.; ]?([\d\.]*)/i
991
+ /(android|bada|blackberry|kaios|maemo|meego|openharmony|qnx|rim tablet os|sailfish|series40|symbian|tizen)\w*[-\/\.; ]?([\d\.]*)/i
951
992
  ], [NAME, VERSION], [
952
993
  /\(bb(10);/i // BlackBerry 10
953
994
  ], [VERSION, [NAME, BLACKBERRY]], [
@@ -955,9 +996,12 @@
955
996
  ], [VERSION, [NAME, 'Symbian']], [
956
997
  /mozilla\/[\d\.]+ \((?:mobile|tablet|tv|mobile; [\w ]+); rv:.+ gecko\/([\w\.]+)/i // Firefox OS
957
998
  ], [VERSION, [NAME, FIREFOX+' OS']], [
958
- /web0s;.+rt(tv)/i,
959
- /\b(?:hp)?wos(?:browser)?\/([\w\.]+)/i // WebOS
999
+ /\b(?:hp)?wos(?:browser)?\/([\w\.]+)/i, // WebOS
1000
+ /webos(?:[ \/]?|\.tv-20(?=2[2-9]))(\d[\d\.]*)/i
960
1001
  ], [VERSION, [NAME, 'webOS']], [
1002
+ /web0s;.+?(?:chr[o0]me|safari)\/(\d+)/i
1003
+ // https://webostv.developer.lge.com/develop/specifications/web-api-and-web-engine
1004
+ ], [[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']], [
961
1005
  /watch(?: ?os[,\/]|\d,\d\/)([\d\.]+)/i // watchOS
962
1006
  ], [VERSION, [NAME, 'watchOS']], [
963
1007
 
@@ -977,20 +1021,20 @@
977
1021
 
978
1022
  // Other
979
1023
  /\b(joli|palm)\b ?(?:os)?\/?([\w\.]*)/i, // Joli/Palm
980
- /(mint)[\/\(\) ]?(\w*)/i, // Mint
981
- /(mageia|vectorlinux)[; ]/i, // Mageia/VectorLinux
982
- /([kxln]?ubuntu|debian|suse|opensuse|gentoo|arch(?= linux)|slackware|fedora|mandriva|centos|pclinuxos|red ?hat|zenwalk|linpus|raspbian|plan 9|minix|risc os|contiki|deepin|manjaro|elementary os|sabayon|linspire)(?: gnu\/linux)?(?: enterprise)?(?:[- ]linux)?(?:-gnu)?[-\/ ]?(?!chrom|package)([-\w\.]*)/i,
983
- // Ubuntu/Debian/SUSE/Gentoo/Arch/Slackware/Fedora/Mandriva/CentOS/PCLinuxOS/RedHat/Zenwalk/Linpus/Raspbian/Plan9/Minix/RISCOS/Contiki/Deepin/Manjaro/elementary/Sabayon/Linspire
984
- /(hurd|linux)(?: arm\w*| x86\w*| ?)([\w\.]*)/i, // Hurd/Linux
1024
+ /linux.+(mint)[\/\(\) ]?([\w\.]*)/i, // Mint
1025
+ /(mageia|vectorlinux|fuchsia|arcaos|arch(?= ?linux))[;l ]([\d\.]*)/i, // Mageia/VectorLinux/Fuchsia/ArcaOS/Arch
1026
+ /([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,
1027
+ // Ubuntu/Debian/SUSE/Gentoo/Slackware/Fedora/Mandriva/CentOS/PCLinuxOS/RedHat/Zenwalk/Linpus/Raspbian/Plan9/Minix/RISCOS/Contiki/Deepin/Manjaro/elementary/Sabayon/Linspire/Knoppix
1028
+ /((?:open)?solaris)[-\/ ]?([\w\.]*)/i, // Solaris
1029
+ /\b(aix)[; ]([1-9\.]{0,4})/i, // AIX
1030
+ /(hurd|linux|morphos)(?: (?:arm|x86|ppc)\w*| ?)([\w\.]*)/i, // Hurd/Linux/MorphOS
985
1031
  /(gnu) ?([\w\.]*)/i, // GNU
986
1032
  /\b([-frentopcghs]{0,5}bsd|dragonfly)[\/ ]?(?!amd|[ix346]{1,2}86)([\w\.]*)/i, // FreeBSD/NetBSD/OpenBSD/PC-BSD/GhostBSD/DragonFly
987
- /(haiku) (\w+)/i // Haiku
1033
+ /(haiku) ?(r\d)?/i // Haiku
988
1034
  ], [NAME, VERSION], [
989
- /(sunos) ?([\w\.\d]*)/i // Solaris
1035
+ /(sunos) ?([\d\.]*)/i // Solaris
990
1036
  ], [[NAME, 'Solaris'], VERSION], [
991
- /((?:open)?solaris)[-\/ ]?([\w\.]*)/i, // Solaris
992
- /(aix) ((\d)(?=\.|\)| )[\w\.])*/i, // AIX
993
- /\b(beos|os\/2|amigaos|morphos|openvms|fuchsia|hp-ux|serenityos)/i, // BeOS/OS2/AmigaOS/MorphOS/OpenVMS/Fuchsia/HP-UX/SerenityOS
1037
+ /\b(beos|os\/2|amigaos|openvms|hp-ux|serenityos)/i, // BeOS/OS2/AmigaOS/OpenVMS/HP-UX/SerenityOS
994
1038
  /(unix) ?([\w\.]*)/i // UNIX
995
1039
  ], [NAME, VERSION]
996
1040
  ]
@@ -1224,21 +1268,20 @@
1224
1268
  for (var i in brands) {
1225
1269
  var brandName = brands[i].brand || brands[i],
1226
1270
  brandVersion = brands[i].version;
1227
- if (this.itemType == UA_BROWSER && !/not.a.brand/i.test(brandName) && (!prevName || (/chrom/i.test(prevName) && brandName != CHROMIUM))) {
1228
- brandName = strMapper(brandName, {
1229
- 'Chrome' : 'Google Chrome',
1230
- 'Edge' : 'Microsoft Edge',
1231
- 'Chrome WebView' : 'Android WebView',
1232
- 'Chrome Headless' : 'HeadlessChrome',
1233
- 'Huawei Browser' : 'HuaweiBrowser',
1234
- 'MIUI Browser' : 'Miui Browser',
1235
- 'Opera Mobi' : 'OperaMobile',
1236
- 'Yandex' : 'YaBrowser'
1237
- });
1238
- this.set(NAME, brandName)
1239
- .set(VERSION, brandVersion)
1240
- .set(MAJOR, majorize(brandVersion));
1241
- prevName = brandName;
1271
+ if (this.itemType == UA_BROWSER &&
1272
+ !/not.a.brand/i.test(brandName) &&
1273
+ (!prevName ||
1274
+ (/Chrom/.test(prevName) && brandName != CHROMIUM) ||
1275
+ (prevName == EDGE && /WebView2/.test(brandName))
1276
+ )) {
1277
+ brandName = strMapper(brandName, browserHintsMap);
1278
+ prevName = this.get(NAME);
1279
+ if (!(prevName && !/Chrom/.test(prevName) && /Chrom/.test(brandName))) {
1280
+ this.set(NAME, brandName)
1281
+ .set(VERSION, brandVersion)
1282
+ .set(MAJOR, majorize(brandVersion));
1283
+ }
1284
+ prevName = brandName;
1242
1285
  }
1243
1286
  if (this.itemType == UA_ENGINE && brandName == CHROMIUM) {
1244
1287
  this.set(VERSION, brandVersion);