ua-parser-js 0.7.37 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of ua-parser-js might be problematic. Click here for more details.

package/src/ua-parser.js CHANGED
@@ -1,12 +1,11 @@
1
- /////////////////////////////////////////////////////////////////////////////////
2
- /* UAParser.js v0.7.37
3
- Copyright © 2012-2021 Faisal Salman <f@faisalman.com>
4
- MIT License *//*
5
- Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data.
6
- Supports browser & node.js environment.
7
- Demo : https://faisalman.github.io/ua-parser-js
8
- Source : https://github.com/faisalman/ua-parser-js */
9
- /////////////////////////////////////////////////////////////////////////////////
1
+ /*!@license
2
+ * UAParser.js v0.7.28
3
+ * Lightweight JavaScript-based User-Agent string parser
4
+ * https://github.com/faisalman/ua-parser-js
5
+ *
6
+ * Copyright © 2012-2021 Faisal Salman <f@faisalman.com>
7
+ * Licensed under MIT License
8
+ */
10
9
 
11
10
  (function (window, undefined) {
12
11
 
@@ -17,14 +16,14 @@
17
16
  /////////////
18
17
 
19
18
 
20
- var LIBVERSION = '0.7.37',
19
+ var LIBVERSION = '0.7.28',
21
20
  EMPTY = '',
22
21
  UNKNOWN = '?',
23
22
  FUNC_TYPE = 'function',
24
23
  UNDEF_TYPE = 'undefined',
25
24
  OBJ_TYPE = 'object',
26
25
  STR_TYPE = 'string',
27
- MAJOR = 'major',
26
+ MAJOR = 'major', // deprecated
28
27
  MODEL = 'model',
29
28
  NAME = 'name',
30
29
  TYPE = 'type',
@@ -37,36 +36,16 @@
37
36
  SMARTTV = 'smarttv',
38
37
  WEARABLE = 'wearable',
39
38
  EMBEDDED = 'embedded',
40
- UA_MAX_LENGTH = 500;
41
-
42
- var AMAZON = 'Amazon',
43
- APPLE = 'Apple',
44
- ASUS = 'ASUS',
45
- BLACKBERRY = 'BlackBerry',
46
- BROWSER = 'Browser',
47
- CHROME = 'Chrome',
48
- EDGE = 'Edge',
49
- FIREFOX = 'Firefox',
50
- GOOGLE = 'Google',
51
- HUAWEI = 'Huawei',
52
- LG = 'LG',
53
- MICROSOFT = 'Microsoft',
54
- MOTOROLA = 'Motorola',
55
- OPERA = 'Opera',
56
- SAMSUNG = 'Samsung',
57
- SHARP = 'Sharp',
58
- SONY = 'Sony',
59
- XIAOMI = 'Xiaomi',
60
- ZEBRA = 'Zebra',
61
- FACEBOOK = 'Facebook',
62
- CHROMIUM_OS = 'Chromium OS',
63
- MAC_OS = 'Mac OS';
39
+ UA_MAX_LENGTH = 255;
40
+
64
41
 
65
42
  ///////////
66
43
  // Helper
67
44
  //////////
68
45
 
69
- var extend = function (regexes, extensions) {
46
+
47
+ var util = {
48
+ extend : function (regexes, extensions) {
70
49
  var mergedRegexes = {};
71
50
  for (var i in regexes) {
72
51
  if (extensions[i] && extensions[i].length % 2 === 0) {
@@ -77,34 +56,30 @@
77
56
  }
78
57
  return mergedRegexes;
79
58
  },
80
- enumerize = function (arr) {
81
- var enums = {};
82
- for (var i=0; i<arr.length; i++) {
83
- enums[arr[i].toUpperCase()] = arr[i];
84
- }
85
- return enums;
86
- },
87
- has = function (str1, str2) {
88
- return typeof str1 === STR_TYPE ? lowerize(str2).indexOf(lowerize(str1)) !== -1 : false;
59
+ has : function (str1, str2) {
60
+ return typeof str1 === STR_TYPE ? str2.toLowerCase().indexOf(str1.toLowerCase()) !== -1 : false;
89
61
  },
90
- lowerize = function (str) {
62
+ lowerize : function (str) {
91
63
  return str.toLowerCase();
92
64
  },
93
- majorize = function (version) {
94
- return typeof(version) === STR_TYPE ? version.replace(/[^\d\.]/g, EMPTY).split('.')[0] : undefined;
65
+ major : function (version) {
66
+ return typeof(version) === STR_TYPE ? version.replace(/[^\d\.]/g,'').split(".")[0] : undefined;
95
67
  },
96
- trim = function (str, len) {
97
- if (typeof(str) === STR_TYPE) {
98
- str = str.replace(/^\s\s*/, EMPTY);
99
- return typeof(len) === UNDEF_TYPE ? str : str.substring(0, UA_MAX_LENGTH);
100
- }
68
+ trim : function (str, len) {
69
+ str = str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
70
+ return typeof(len) === UNDEF_TYPE ? str : str.substring(0, UA_MAX_LENGTH);
71
+ }
101
72
  };
102
73
 
74
+
103
75
  ///////////////
104
76
  // Map helper
105
77
  //////////////
106
78
 
107
- var rgxMapper = function (ua, arrays) {
79
+
80
+ var mapper = {
81
+
82
+ rgx : function (ua, arrays) {
108
83
 
109
84
  var i = 0, j, k, p, q, matches, match;
110
85
 
@@ -118,7 +93,6 @@
118
93
  // try matching uastring with regexes
119
94
  while (j < regex.length && !matches) {
120
95
 
121
- if (!regex[j]) { break; }
122
96
  matches = regex[j++].exec(ua);
123
97
 
124
98
  if (!!matches) {
@@ -127,7 +101,7 @@
127
101
  q = props[p];
128
102
  // check if given property is actually array
129
103
  if (typeof q === OBJ_TYPE && q.length > 0) {
130
- if (q.length === 2) {
104
+ if (q.length == 2) {
131
105
  if (typeof q[1] == FUNC_TYPE) {
132
106
  // assign modified match
133
107
  this[q[0]] = q[1].call(this, match);
@@ -135,7 +109,7 @@
135
109
  // assign given value, ignore regex match
136
110
  this[q[0]] = q[1];
137
111
  }
138
- } else if (q.length === 3) {
112
+ } else if (q.length == 3) {
139
113
  // check whether function or regex
140
114
  if (typeof q[1] === FUNC_TYPE && !(q[1].exec && q[1].test)) {
141
115
  // call function (usually string mapper)
@@ -144,7 +118,7 @@
144
118
  // sanitize match using given regex
145
119
  this[q[0]] = match ? match.replace(q[1], q[2]) : undefined;
146
120
  }
147
- } else if (q.length === 4) {
121
+ } else if (q.length == 4) {
148
122
  this[q[0]] = match ? q[3].call(this, match.replace(q[1], q[2])) : undefined;
149
123
  }
150
124
  } else {
@@ -157,56 +131,84 @@
157
131
  }
158
132
  },
159
133
 
160
- strMapper = function (str, map) {
134
+ str : function (str, map) {
161
135
 
162
136
  for (var i in map) {
163
- // check if current value is array
137
+ // check if array
164
138
  if (typeof map[i] === OBJ_TYPE && map[i].length > 0) {
165
139
  for (var j = 0; j < map[i].length; j++) {
166
- if (has(map[i][j], str)) {
140
+ if (util.has(map[i][j], str)) {
167
141
  return (i === UNKNOWN) ? undefined : i;
168
142
  }
169
143
  }
170
- } else if (has(map[i], str)) {
144
+ } else if (util.has(map[i], str)) {
171
145
  return (i === UNKNOWN) ? undefined : i;
172
146
  }
173
147
  }
174
148
  return str;
149
+ }
175
150
  };
176
151
 
152
+
177
153
  ///////////////
178
154
  // String map
179
155
  //////////////
180
156
 
181
- // Safari < 3.0
182
- var oldSafariMap = {
183
- '1.0' : '/8',
184
- '1.2' : '/1',
185
- '1.3' : '/3',
186
- '2.0' : '/412',
187
- '2.0.2' : '/416',
188
- '2.0.3' : '/417',
189
- '2.0.4' : '/419',
190
- '?' : '/'
157
+
158
+ var maps = {
159
+
160
+ browser : {
161
+ // Safari < 3.0
162
+ oldSafari : {
163
+ version : {
164
+ '1.0' : '/8',
165
+ '1.2' : '/1',
166
+ '1.3' : '/3',
167
+ '2.0' : '/412',
168
+ '2.0.2' : '/416',
169
+ '2.0.3' : '/417',
170
+ '2.0.4' : '/419',
171
+ '?' : '/'
172
+ }
173
+ },
174
+ oldEdge : {
175
+ version : {
176
+ '0.1' : '12.',
177
+ '21' : '13.',
178
+ '31' : '14.',
179
+ '39' : '15.',
180
+ '41' : '16.',
181
+ '42' : '17.',
182
+ '44' : '18.'
183
+ }
184
+ }
191
185
  },
192
- windowsVersionMap = {
193
- 'ME' : '4.90',
194
- 'NT 3.11' : 'NT3.51',
195
- 'NT 4.0' : 'NT4.0',
196
- '2000' : 'NT 5.0',
197
- 'XP' : ['NT 5.1', 'NT 5.2'],
198
- 'Vista' : 'NT 6.0',
199
- '7' : 'NT 6.1',
200
- '8' : 'NT 6.2',
201
- '8.1' : 'NT 6.3',
202
- '10' : ['NT 6.4', 'NT 10.0'],
203
- 'RT' : 'ARM'
186
+
187
+ os : {
188
+ windows : {
189
+ version : {
190
+ 'ME' : '4.90',
191
+ 'NT 3.11' : 'NT3.51',
192
+ 'NT 4.0' : 'NT4.0',
193
+ '2000' : 'NT 5.0',
194
+ 'XP' : ['NT 5.1', 'NT 5.2'],
195
+ 'Vista' : 'NT 6.0',
196
+ '7' : 'NT 6.1',
197
+ '8' : 'NT 6.2',
198
+ '8.1' : 'NT 6.3',
199
+ '10' : ['NT 6.4', 'NT 10.0'],
200
+ 'RT' : 'ARM'
201
+ }
202
+ }
203
+ }
204
204
  };
205
205
 
206
+
206
207
  //////////////
207
208
  // Regex map
208
209
  /////////////
209
210
 
211
+
210
212
  var regexes = {
211
213
 
212
214
  browser : [[
@@ -215,406 +217,399 @@
215
217
  ], [VERSION, [NAME, 'Chrome']], [
216
218
  /edg(?:e|ios|a)?\/([\w\.]+)/i // Microsoft Edge
217
219
  ], [VERSION, [NAME, 'Edge']], [
220
+ // breaking change (reserved for next major release):
221
+ ///edge\/([\w\.]+)/i // Old Edge (Trident)
222
+ //], [[VERSION, mapper.str, maps.browser.oldEdge.version], [NAME, 'Edge']], [
218
223
 
219
224
  // Presto based
220
- /(opera mini)\/([-\w\.]+)/i, // Opera Mini
221
- /(opera [mobiletab]{3,6})\b.+version\/([-\w\.]+)/i, // Opera Mobi/Tablet
222
- /(opera)(?:.+version\/|[\/ ]+)([\w\.]+)/i // Opera
225
+ /(opera\smini)\/([\w\.-]+)/i, // Opera Mini
226
+ /(opera\s[mobiletab]{3,6})\b.+version\/([\w\.-]+)/i, // Opera Mobi/Tablet
227
+ /(opera)(?:.+version\/|[\/\s]+)([\w\.]+)/i, // Opera
223
228
  ], [NAME, VERSION], [
224
- /opios[\/ ]+([\w\.]+)/i // Opera mini on iphone >= 8.0
225
- ], [VERSION, [NAME, OPERA+' Mini']], [
226
- /\bopr\/([\w\.]+)/i // Opera Webkit
227
- ], [VERSION, [NAME, OPERA]], [
229
+ /opios[\/\s]+([\w\.]+)/i // Opera mini on iphone >= 8.0
230
+ ], [VERSION, [NAME, 'Opera Mini']], [
231
+ /\sopr\/([\w\.]+)/i // Opera Webkit
232
+ ], [VERSION, [NAME, 'Opera']], [
228
233
 
229
234
  // Mixed
230
- /\bb[ai]*d(?:uhd|[ub]*[aekoprswx]{5,6})[\/ ]?([\w\.]+)/i // Baidu
231
- ], [VERSION, [NAME, 'Baidu']], [
232
235
  /(kindle)\/([\w\.]+)/i, // Kindle
233
- /(lunascape|maxthon|netfront|jasmine|blazer)[\/ ]?([\w\.]*)/i, // Lunascape/Maxthon/Netfront/Jasmine/Blazer
236
+ /(lunascape|maxthon|netfront|jasmine|blazer)[\/\s]?([\w\.]*)/i, // Lunascape/Maxthon/Netfront/Jasmine/Blazer
234
237
  // Trident based
235
- /(avant|iemobile|slim)\s?(?:browser)?[\/ ]?([\w\.]*)/i, // Avant/IEMobile/SlimBrowser
236
- /(?:ms|\()(ie) ([\w\.]+)/i, // Internet Explorer
237
-
238
- // Webkit/KHTML based // Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS/Bowser/QupZilla/Falkon
239
- /(flock|rockmelt|midori|epiphany|silk|skyfire|bolt|iron|vivaldi|iridium|phantomjs|bowser|quark|qupzilla|falkon|rekonq|puffin|brave|whale(?!.+naver)|qqbrowserlite|qq|duckduckgo)\/([-\w\.]+)/i,
240
- // Rekonq/Puffin/Brave/Whale/QQBrowserLite/QQ, aka ShouQ
241
- /(heytap|ovi)browser\/([\d\.]+)/i, // Heytap/Ovi
238
+ /(avant\s|iemobile|slim)(?:browser)?[\/\s]?([\w\.]*)/i, // Avant/IEMobile/SlimBrowser
239
+ /(ba?idubrowser)[\/\s]?([\w\.]+)/i, // Baidu Browser
240
+ /(?:ms|\()(ie)\s([\w\.]+)/i, // Internet Explorer
241
+
242
+ // Webkit/KHTML based
243
+ /(flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi|iridium|phantomjs|bowser|quark|qupzilla|falkon)\/([\w\.-]+)/i,
244
+ // Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS/Bowser/QupZilla/Falkon
245
+ /(rekonq|puffin|brave|whale|qqbrowserlite|qq)\/([\w\.]+)/i, // Rekonq/Puffin/Brave/Whale/QQBrowserLite/QQ, aka ShouQ
242
246
  /(weibo)__([\d\.]+)/i // Weibo
243
247
  ], [NAME, VERSION], [
244
- /(?:\buc? ?browser|(?:juc.+)ucweb)[\/ ]?([\w\.]+)/i // UCBrowser
245
- ], [VERSION, [NAME, 'UC'+BROWSER]], [
246
- /microm.+\bqbcore\/([\w\.]+)/i, // WeChat Desktop for Windows Built-in Browser
247
- /\bqbcore\/([\w\.]+).+microm/i,
248
+ /(?:[\s\/]uc?\s?browser|(?:juc.+)ucweb)[\/\s]?([\w\.]+)/i // UCBrowser
249
+ ], [VERSION, [NAME, 'UCBrowser']], [
250
+ /(?:windowswechat)?\sqbcore\/([\w\.]+)\b.*(?:windowswechat)?/i // WeChat Desktop for Windows Built-in Browser
251
+ ], [VERSION, [NAME, 'WeChat(Win) Desktop']], [
248
252
  /micromessenger\/([\w\.]+)/i // WeChat
249
253
  ], [VERSION, [NAME, 'WeChat']], [
250
254
  /konqueror\/([\w\.]+)/i // Konqueror
251
255
  ], [VERSION, [NAME, 'Konqueror']], [
252
- /trident.+rv[: ]([\w\.]{1,9})\b.+like gecko/i // IE11
256
+ /trident.+rv[:\s]([\w\.]{1,9})\b.+like\sgecko/i // IE11
253
257
  ], [VERSION, [NAME, 'IE']], [
254
- /ya(?:search)?browser\/([\w\.]+)/i // Yandex
258
+ /yabrowser\/([\w\.]+)/i // Yandex
255
259
  ], [VERSION, [NAME, 'Yandex']], [
256
- /slbrowser\/([\w\.]+)/i // Smart Lenovo Browser
257
- ], [VERSION, [NAME, 'Smart Lenovo '+BROWSER]], [
258
260
  /(avast|avg)\/([\w\.]+)/i // Avast/AVG Secure Browser
259
- ], [[NAME, /(.+)/, '$1 Secure '+BROWSER], VERSION], [
260
- /\bfocus\/([\w\.]+)/i // Firefox Focus
261
- ], [VERSION, [NAME, FIREFOX+' Focus']], [
262
- /\bopt\/([\w\.]+)/i // Opera Touch
263
- ], [VERSION, [NAME, OPERA+' Touch']], [
264
- /coc_coc\w+\/([\w\.]+)/i // Coc Coc Browser
261
+ ], [[NAME, /(.+)/, '$1 Secure Browser'], VERSION], [
262
+ /focus\/([\w\.]+)/i // Firefox Focus
263
+ ], [VERSION, [NAME, 'Firefox Focus']], [
264
+ /opt\/([\w\.]+)/i // Opera Touch
265
+ ], [VERSION, [NAME, 'Opera Touch']], [
266
+ /coc_coc_browser\/([\w\.]+)/i // Coc Coc Browser
265
267
  ], [VERSION, [NAME, 'Coc Coc']], [
266
268
  /dolfin\/([\w\.]+)/i // Dolphin
267
269
  ], [VERSION, [NAME, 'Dolphin']], [
268
270
  /coast\/([\w\.]+)/i // Opera Coast
269
- ], [VERSION, [NAME, OPERA+' Coast']], [
270
- /miuibrowser\/([\w\.]+)/i // MIUI Browser
271
- ], [VERSION, [NAME, 'MIUI '+BROWSER]], [
272
- /fxios\/([-\w\.]+)/i // Firefox for iOS
273
- ], [VERSION, [NAME, FIREFOX]], [
274
- /\bqihu|(qi?ho?o?|360)browser/i // 360
275
- ], [[NAME, '360 ' + BROWSER]], [
276
- /(oculus|sailfish|huawei|vivo)browser\/([\w\.]+)/i
277
- ], [[NAME, /(.+)/, '$1 ' + BROWSER], VERSION], [ // Oculus/Sailfish/HuaweiBrowser/VivoBrowser
278
- /samsungbrowser\/([\w\.]+)/i // Samsung Internet
279
- ], [VERSION, [NAME, SAMSUNG + ' Internet']], [
271
+ ], [VERSION, [NAME, 'Opera Coast']],
272
+ [/xiaomi\/miuibrowser\/([\w\.]+)/i // MIUI Browser
273
+ ], [VERSION, [NAME, 'MIUI Browser']], [
274
+ /fxios\/([\w\.-]+)/i // Firefox for iOS
275
+ ], [VERSION, [NAME, 'Firefox']], [
276
+ /(qihu|qhbrowser|qihoobrowser|360browser)/i // 360
277
+ ], [[NAME, '360 Browser']], [
278
+ /(oculus|samsung|sailfish)browser\/([\w\.]+)/i
279
+ ], [[NAME, /(.+)/, '$1 Browser'], VERSION], [ // Oculus/Samsung/Sailfish Browser
280
280
  /(comodo_dragon)\/([\w\.]+)/i // Comodo Dragon
281
281
  ], [[NAME, /_/g, ' '], VERSION], [
282
- /metasr[\/ ]?([\d\.]+)/i // Sogou Explorer
283
- ], [VERSION, [NAME, 'Sogou Explorer']], [
284
- /(sogou)mo\w+\/([\d\.]+)/i // Sogou Mobile
285
- ], [[NAME, 'Sogou Mobile'], VERSION], [
286
- /(electron)\/([\w\.]+) safari/i, // Electron-based App
287
- /(tesla)(?: qtcarbrowser|\/(20\d\d\.[-\w\.]+))/i, // Tesla
288
- /m?(qqbrowser|2345Explorer)[\/ ]?([\w\.]+)/i // QQBrowser/2345 Browser
282
+ /\s(electron)\/([\w\.]+)\ssafari/i, // Electron-based App
283
+ /(tesla)(?:\sqtcarbrowser|\/(20[12]\d\.[\w\.-]+))/i, // Tesla
284
+ /m?(qqbrowser|baiduboxapp|2345Explorer)[\/\s]?([\w\.]+)/i // QQBrowser/Baidu App/2345 Browser
289
285
  ], [NAME, VERSION], [
290
- /(lbbrowser)/i, // LieBao Browser
291
- /\[(linkedin)app\]/i // LinkedIn App for iOS & Android
286
+ /(MetaSr)[\/\s]?([\w\.]+)/i, // SouGouBrowser
287
+ /(LBBROWSER)/i // LieBao Browser
292
288
  ], [NAME], [
293
289
 
294
290
  // WebView
295
- /((?:fban\/fbios|fb_iab\/fb4a)(?!.+fbav)|;fbav\/([\w\.]+);)/i // Facebook App for iOS & Android
296
- ], [[NAME, FACEBOOK], VERSION], [
297
- /(Klarna)\/([\w\.]+)/i, // Klarna Shopping Browser for iOS & Android
298
- /(kakao(?:talk|story))[\/ ]([\w\.]+)/i, // Kakao App
299
- /(naver)\(.*?(\d+\.[\w\.]+).*\)/i, // Naver InApp
300
- /safari (line)\/([\w\.]+)/i, // Line App for iOS
291
+ /;fbav\/([\w\.]+);/i // Facebook App for iOS & Android with version
292
+ ], [VERSION, [NAME, 'Facebook']], [
293
+ /FBAN\/FBIOS|FB_IAB\/FB4A/i // Facebook App for iOS & Android without version
294
+ ], [[NAME, 'Facebook']], [
295
+ /safari\s(line)\/([\w\.]+)/i, // Line App for iOS
301
296
  /\b(line)\/([\w\.]+)\/iab/i, // Line App for Android
302
- /(alipay)client\/([\w\.]+)/i, // Alipay
303
- /(chromium|instagram|snapchat)[\/ ]([-\w\.]+)/i // Chromium/Instagram/Snapchat
297
+ /(chromium|instagram)[\/\s]([\w\.-]+)/i // Chromium/Instagram
304
298
  ], [NAME, VERSION], [
305
- /\bgsa\/([\w\.]+) .*safari\//i // Google Search Appliance on iOS
299
+ /\bgsa\/([\w\.]+)\s.*safari\//i // Google Search Appliance on iOS
306
300
  ], [VERSION, [NAME, 'GSA']], [
307
- /musical_ly(?:.+app_?version\/|_)([\w\.]+)/i // TikTok
308
- ], [VERSION, [NAME, 'TikTok']], [
309
301
 
310
- /headlesschrome(?:\/([\w\.]+)| )/i // Chrome Headless
311
- ], [VERSION, [NAME, CHROME+' Headless']], [
302
+ /headlesschrome(?:\/([\w\.]+)|\s)/i // Chrome Headless
303
+ ], [VERSION, [NAME, 'Chrome Headless']], [
312
304
 
313
- / wv\).+(chrome)\/([\w\.]+)/i // Chrome WebView
314
- ], [[NAME, CHROME+' WebView'], VERSION], [
305
+ /\swv\).+(chrome)\/([\w\.]+)/i // Chrome WebView
306
+ ], [[NAME, 'Chrome WebView'], VERSION], [
315
307
 
316
- /droid.+ version\/([\w\.]+)\b.+(?:mobile safari|safari)/i // Android Browser
317
- ], [VERSION, [NAME, 'Android '+BROWSER]], [
308
+ /droid.+\sversion\/([\w\.]+)\b.+(?:mobile\ssafari|safari)/i // Android Browser
309
+ ], [VERSION, [NAME, 'Android Browser']], [
318
310
 
319
- /(chrome|omniweb|arora|[tizenoka]{5} ?browser)\/v?([\w\.]+)/i // Chrome/OmniWeb/Arora/Tizen/Nokia
311
+ /(chrome|omniweb|arora|[tizenoka]{5}\s?browser)\/v?([\w\.]+)/i // Chrome/OmniWeb/Arora/Tizen/Nokia
320
312
  ], [NAME, VERSION], [
321
313
 
322
- /version\/([\w\.\,]+) .*mobile\/\w+ (safari)/i // Mobile Safari
314
+ /version\/([\w\.]+)\s.*mobile\/\w+\s(safari)/i // Mobile Safari
323
315
  ], [VERSION, [NAME, 'Mobile Safari']], [
324
- /version\/([\w(\.|\,)]+) .*(mobile ?safari|safari)/i // Safari & Safari Mobile
316
+ /version\/([\w\.]+)\s.*(mobile\s?safari|safari)/i // Safari & Safari Mobile
325
317
  ], [VERSION, NAME], [
326
- /webkit.+?(mobile ?safari|safari)(\/[\w\.]+)/i // Safari < 3.0
327
- ], [NAME, [VERSION, strMapper, oldSafariMap]], [
318
+ /webkit.+?(mobile\s?safari|safari)(\/[\w\.]+)/i // Safari < 3.0
319
+ ], [NAME, [VERSION, mapper.str, maps.browser.oldSafari.version]], [
328
320
 
329
321
  /(webkit|khtml)\/([\w\.]+)/i
330
322
  ], [NAME, VERSION], [
331
323
 
332
324
  // Gecko based
333
- /(navigator|netscape\d?)\/([-\w\.]+)/i // Netscape
325
+ /(navigator|netscape)\/([\w\.-]+)/i // Netscape
334
326
  ], [[NAME, 'Netscape'], VERSION], [
335
- /mobile vr; rv:([\w\.]+)\).+firefox/i // Firefox Reality
336
- ], [VERSION, [NAME, FIREFOX+' Reality']], [
327
+ /ile\svr;\srv:([\w\.]+)\).+firefox/i // Firefox Reality
328
+ ], [VERSION, [NAME, 'Firefox Reality']], [
337
329
  /ekiohf.+(flow)\/([\w\.]+)/i, // Flow
338
330
  /(swiftfox)/i, // Swiftfox
339
- /(icedragon|iceweasel|camino|chimera|fennec|maemo browser|minimo|conkeror|klar)[\/ ]?([\w\.\+]+)/i,
340
- // IceDragon/Iceweasel/Camino/Chimera/Fennec/Maemo/Minimo/Conkeror/Klar
341
- /(seamonkey|k-meleon|icecat|iceape|firebird|phoenix|palemoon|basilisk|waterfox)\/([-\w\.]+)$/i,
331
+ /(icedragon|iceweasel|camino|chimera|fennec|maemo\sbrowser|minimo|conkeror)[\/\s]?([\w\.\+]+)/i,
332
+ // IceDragon/Iceweasel/Camino/Chimera/Fennec/Maemo/Minimo/Conkeror
333
+ /(firefox|seamonkey|k-meleon|icecat|iceape|firebird|phoenix|palemoon|basilisk|waterfox)\/([\w\.-]+)$/i,
342
334
  // Firefox/SeaMonkey/K-Meleon/IceCat/IceApe/Firebird/Phoenix
343
- /(firefox)\/([\w\.]+)/i, // Other Firefox-based
344
- /(mozilla)\/([\w\.]+) .+rv\:.+gecko\/\d+/i, // Mozilla
335
+ /(firefox)\/([\w\.]+)\s[\w\s\-]+\/[\w\.]+$/i, // Other Firefox-based
336
+ /(mozilla)\/([\w\.]+)\s.+rv\:.+gecko\/\d+/i, // Mozilla
345
337
 
346
338
  // Other
347
- /(polaris|lynx|dillo|icab|doris|amaya|w3m|netsurf|sleipnir|obigo|mosaic|(?:go|ice|up)[\. ]?browser)[-\/ ]?v?([\w\.]+)/i,
348
- // Polaris/Lynx/Dillo/iCab/Doris/Amaya/w3m/NetSurf/Sleipnir/Obigo/Mosaic/Go/ICE/UP.Browser
349
- /(links) \(([\w\.]+)/i, // Links
350
- /panasonic;(viera)/i // Panasonic Viera
351
- ], [NAME, VERSION], [
352
-
353
- /(cobalt)\/([\w\.]+)/i // Cobalt
354
- ], [NAME, [VERSION, /master.|lts./, ""]]
339
+ /(polaris|lynx|dillo|icab|doris|amaya|w3m|netsurf|sleipnir)[\/\s]?([\w\.]+)/i,
340
+ // Polaris/Lynx/Dillo/iCab/Doris/Amaya/w3m/NetSurf/Sleipnir
341
+ /(links)\s\(([\w\.]+)/i, // Links
342
+ /(gobrowser)\/?([\w\.]*)/i, // GoBrowser
343
+ /(ice\s?browser)\/v?([\w\._]+)/i, // ICE Browser
344
+ /(mosaic)[\/\s]([\w\.]+)/i // Mosaic
345
+ ], [NAME, VERSION]
355
346
  ],
356
347
 
357
348
  cpu : [[
358
349
 
359
- /(?:(amd|x(?:(?:86|64)[-_])?|wow|win)64)[;\)]/i // AMD64 (x64)
350
+ /(?:(amd|x(?:(?:86|64)[_-])?|wow|win)64)[;\)]/i // AMD64 (x64)
360
351
  ], [[ARCHITECTURE, 'amd64']], [
361
352
 
362
353
  /(ia32(?=;))/i // IA32 (quicktime)
363
- ], [[ARCHITECTURE, lowerize]], [
354
+ ], [[ARCHITECTURE, util.lowerize]], [
364
355
 
365
356
  /((?:i[346]|x)86)[;\)]/i // IA32 (x86)
366
357
  ], [[ARCHITECTURE, 'ia32']], [
367
358
 
368
- /\b(aarch64|arm(v?8e?l?|_?64))\b/i // ARM64
359
+ /\b(aarch64|armv?8e?l?)\b/i // ARM64
369
360
  ], [[ARCHITECTURE, 'arm64']], [
370
361
 
371
362
  /\b(arm(?:v[67])?ht?n?[fl]p?)\b/i // ARMHF
372
363
  ], [[ARCHITECTURE, 'armhf']], [
373
364
 
374
365
  // PocketPC mistakenly identified as PowerPC
375
- /windows (ce|mobile); ppc;/i
366
+ /windows\s(ce|mobile);\sppc;/i
376
367
  ], [[ARCHITECTURE, 'arm']], [
377
368
 
378
- /((?:ppc|powerpc)(?:64)?)(?: mac|;|\))/i // PowerPC
379
- ], [[ARCHITECTURE, /ower/, EMPTY, lowerize]], [
369
+ /((?:ppc|powerpc)(?:64)?)(?:\smac|;|\))/i // PowerPC
370
+ ], [[ARCHITECTURE, /ower/, '', util.lowerize]], [
380
371
 
381
372
  /(sun4\w)[;\)]/i // SPARC
382
373
  ], [[ARCHITECTURE, 'sparc']], [
383
374
 
384
- /((?:avr32|ia64(?=;))|68k(?=\))|\barm(?=v(?:[1-7]|[5-7]1)l?|;|eabi)|(?=atmel )avr|(?:irix|mips|sparc)(?:64)?\b|pa-risc)/i
375
+ /((?:avr32|ia64(?=;))|68k(?=\))|\barm(?:64|(?=v(?:[1-7]|[5-7]1)l?|;|eabi))|(?=atmel\s)avr|(?:irix|mips|sparc)(?:64)?\b|pa-risc)/i
385
376
  // IA64, 68K, ARM/64, AVR/32, IRIX/64, MIPS/64, SPARC/64, PA-RISC
386
- ], [[ARCHITECTURE, lowerize]]
377
+ ], [[ARCHITECTURE, util.lowerize]]
387
378
  ],
388
379
 
389
380
  device : [[
390
381
 
391
382
  //////////////////////////
392
383
  // MOBILES & TABLETS
384
+ // Ordered by popularity
393
385
  /////////////////////////
394
386
 
395
387
  // Samsung
396
- /\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
397
- ], [MODEL, [VENDOR, SAMSUNG], [TYPE, TABLET]], [
398
- /\b((?:s[cgp]h|gt|sm)-\w+|sc[g-]?[\d]+a?|galaxy nexus)/i,
399
- /samsung[- ]([-\w]+)/i,
388
+ /\b(sch-i[89]0\d|shw-m380s|sm-[pt]\w{2,4}|gt-[pn]\d{2,4}|sgh-t8[56]9|nexus\s10)/i
389
+ ], [MODEL, [VENDOR, 'Samsung'], [TYPE, TABLET]], [
390
+ /\b((?:s[cgp]h|gt|sm)-\w+|galaxy\snexus)/i,
391
+ /\ssamsung[\s-]([\w-]+)/i,
400
392
  /sec-(sgh\w+)/i
401
- ], [MODEL, [VENDOR, SAMSUNG], [TYPE, MOBILE]], [
393
+ ], [MODEL, [VENDOR, 'Samsung'], [TYPE, MOBILE]], [
402
394
 
403
395
  // Apple
404
- /(?:\/|\()(ip(?:hone|od)[\w, ]*)(?:\/|;)/i // iPod/iPhone
405
- ], [MODEL, [VENDOR, APPLE], [TYPE, MOBILE]], [
406
- /\((ipad);[-\w\),; ]+apple/i, // iPad
407
- /applecoremedia\/[\w\.]+ \((ipad)/i,
396
+ /\((ip(?:hone|od)[\s\w]*);/i // iPod/iPhone
397
+ ], [MODEL, [VENDOR, 'Apple'], [TYPE, MOBILE]], [
398
+ /\((ipad);[\w\s\),;-]+apple/i, // iPad
399
+ /applecoremedia\/[\w\.]+\s\((ipad)/i,
408
400
  /\b(ipad)\d\d?,\d\d?[;\]].+ios/i
409
- ], [MODEL, [VENDOR, APPLE], [TYPE, TABLET]], [
410
- /(macintosh);/i
411
- ], [MODEL, [VENDOR, APPLE]], [
412
-
413
- // Sharp
414
- /\b(sh-?[altvz]?\d\d[a-ekm]?)/i
415
- ], [MODEL, [VENDOR, SHARP], [TYPE, MOBILE]], [
401
+ ], [MODEL, [VENDOR, 'Apple'], [TYPE, TABLET]], [
416
402
 
417
403
  // Huawei
418
- /\b((?:ag[rs][23]?|bah2?|sht?|btv)-a?[lw]\d{2})\b(?!.+d\/s)/i
419
- ], [MODEL, [VENDOR, HUAWEI], [TYPE, TABLET]], [
420
- /(?:huawei|honor)([-\w ]+)[;\)]/i,
421
- /\b(nexus 6p|\w{2,4}e?-[atu]?[ln][\dx][012359c][adn]?)\b(?!.+d\/s)/i
422
- ], [MODEL, [VENDOR, HUAWEI], [TYPE, MOBILE]], [
404
+ /\b((?:agr|ags[23]|bah2?|sht?)-a?[lw]\d{2})/i,
405
+ ], [MODEL, [VENDOR, 'Huawei'], [TYPE, TABLET]], [
406
+ /d\/huawei([\w\s-]+)[;\)]/i,
407
+ /\b(nexus\s6p|vog-[at]?l\d\d|ane-[at]?l[x\d]\d|eml-a?l\d\da?|lya-[at]?l\d[\dc]|clt-a?l\d\di?|ele-l\d\d)/i,
408
+ /\b(\w{2,4}-[atu][ln][01259][019])[;\)\s]/i
409
+ ], [MODEL, [VENDOR, 'Huawei'], [TYPE, MOBILE]], [
423
410
 
424
411
  // Xiaomi
425
- /\b(poco[\w ]+|m2\d{3}j\d\d[a-z]{2})(?: bui|\))/i, // Xiaomi POCO
426
- /\b; (\w+) build\/hm\1/i, // Xiaomi Hongmi 'numeric' models
427
- /\b(hm[-_ ]?note?[_ ]?(?:\d\w)?) bui/i, // Xiaomi Hongmi
428
- /\b(redmi[\-_ ]?(?:note|k)?[\w_ ]+)(?: bui|\))/i, // Xiaomi Redmi
429
- /oid[^\)]+; (m?[12][0-389][01]\w{3,6}[c-y])( bui|; wv|\))/i, // Xiaomi Redmi 'numeric' models
430
- /\b(mi[-_ ]?(?:a\d|one|one[_ ]plus|note lte|max|cc)?[_ ]?(?:\d?\w?)[_ ]?(?:plus|se|lite)?)(?: bui|\))/i // Xiaomi Mi
431
- ], [[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, MOBILE]], [
432
- /oid[^\)]+; (2\d{4}(283|rpbf)[cgl])( bui|\))/i, // Redmi Pad
433
- /\b(mi[-_ ]?(?:pad)(?:[\w_ ]+))(?: bui|\))/i // Mi Pad tablets
434
- ],[[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, TABLET]], [
412
+ /\b(poco[\s\w]+)(?:\sbuild|\))/i, // Xiaomi POCO
413
+ /\b;\s(\w+)\sbuild\/hm\1/i, // Xiaomi Hongmi 'numeric' models
414
+ /\b(hm[\s\-_]?note?[\s_]?(?:\d\w)?)\sbuild/i, // Xiaomi Hongmi
415
+ /\b(redmi[\s\-_]?(?:note|k)?[\w\s_]+)(?:\sbuild|\))/i, // Xiaomi Redmi
416
+ /\b(mi[\s\-_]?(?:a\d|one|one[\s_]plus|note lte)?[\s_]?(?:\d?\w?)[\s_]?(?:plus)?)\sbuild/i // Xiaomi Mi
417
+ ], [[MODEL, /_/g, ' '], [VENDOR, 'Xiaomi'], [TYPE, MOBILE]], [
418
+ /\b(mi[\s\-_]?(?:pad)(?:[\w\s_]+))(?:\sbuild|\))/i // Mi Pad tablets
419
+ ],[[MODEL, /_/g, ' '], [VENDOR, 'Xiaomi'], [TYPE, TABLET]], [
435
420
 
436
421
  // OPPO
437
- /; (\w+) bui.+ oppo/i,
438
- /\b(cph[12]\d{3}|p(?:af|c[al]|d\w|e[ar])[mt]\d0|x9007|a101op)\b/i
422
+ /;\s(\w+)\sbuild.+\soppo/i,
423
+ /\s(cph[12]\d{3}|p(?:af|c[al]|d\w|e[ar])[mt]\d0|x9007)\b/i
439
424
  ], [MODEL, [VENDOR, 'OPPO'], [TYPE, MOBILE]], [
440
425
 
441
426
  // Vivo
442
- /vivo (\w+)(?: bui|\))/i,
443
- /\b(v[12]\d{3}\w?[at])(?: bui|;)/i
427
+ /\svivo\s(\w+)(?:\sbuild|\))/i,
428
+ /\s(v[12]\d{3}\w?[at])(?:\sbuild|;)/i
444
429
  ], [MODEL, [VENDOR, 'Vivo'], [TYPE, MOBILE]], [
445
430
 
446
431
  // Realme
447
- /\b(rmx[1-3]\d{3})(?: bui|;|\))/i
432
+ /\s(rmx[12]\d{3})(?:\sbuild|;)/i
448
433
  ], [MODEL, [VENDOR, 'Realme'], [TYPE, MOBILE]], [
449
434
 
450
435
  // Motorola
451
- /\b(milestone|droid(?:[2-4x]| (?:bionic|x2|pro|razr))?:?( 4g)?)\b[\w ]+build\//i,
452
- /\bmot(?:orola)?[- ](\w*)/i,
453
- /((?:moto[\w\(\) ]+|xt\d{3,4}|nexus 6)(?= bui|\)))/i
454
- ], [MODEL, [VENDOR, MOTOROLA], [TYPE, MOBILE]], [
455
- /\b(mz60\d|xoom[2 ]{0,2}) build\//i
456
- ], [MODEL, [VENDOR, MOTOROLA], [TYPE, TABLET]], [
436
+ /\s(milestone|droid(?:[2-4x]|\s(?:bionic|x2|pro|razr))?:?(\s4g)?)\b[\w\s]+build\//i,
437
+ /\smot(?:orola)?[\s-](\w*)/i,
438
+ /((?:moto[\s\w\(\)]+|xt\d{3,4}|nexus\s6)(?=\sbuild|\)))/i
439
+ ], [MODEL, [VENDOR, 'Motorola'], [TYPE, MOBILE]], [
440
+ /\s(mz60\d|xoom[\s2]{0,2})\sbuild\//i
441
+ ], [MODEL, [VENDOR, 'Motorola'], [TYPE, TABLET]], [
457
442
 
458
443
  // LG
459
- /((?=lg)?[vl]k\-?\d{3}) bui| 3\.[-\w; ]{10}lg?-([06cv9]{3,4})/i
460
- ], [MODEL, [VENDOR, LG], [TYPE, TABLET]], [
461
- /(lm(?:-?f100[nv]?|-[\w\.]+)(?= bui|\))|nexus [45])/i,
462
- /\blg[-e;\/ ]+((?!browser|netcast|android tv)\w+)/i,
463
- /\blg-?([\d\w]+) bui/i
464
- ], [MODEL, [VENDOR, LG], [TYPE, MOBILE]], [
444
+ /((?=lg)?[vl]k\-?\d{3})\sbuild|\s3\.[\s\w;-]{10}lg?-([06cv9]{3,4})/i
445
+ ], [MODEL, [VENDOR, 'LG'], [TYPE, TABLET]], [
446
+ /(lm-?f100[nv]?|nexus\s[45])/i,
447
+ /lg[e;\s\/-]+((?!browser|netcast)\w+)/i,
448
+ /\blg(\-?[\d\w]+)\sbuild/i
449
+ ], [MODEL, [VENDOR, 'LG'], [TYPE, MOBILE]], [
465
450
 
466
451
  // Lenovo
467
- /(ideatab[-\w ]+)/i,
468
- /lenovo ?(s[56]000[-\w]+|tab(?:[\w ]+)|yt[-\d\w]{6}|tb[-\d\w]{6})/i
452
+ /(ideatab[\w\-\s]+)/i,
453
+ /lenovo\s?(s(?:5000|6000)(?:[\w-]+)|tab(?:[\s\w]+)|yt[\d\w-]{6}|tb[\d\w-]{6})/i // Lenovo tablets
469
454
  ], [MODEL, [VENDOR, 'Lenovo'], [TYPE, TABLET]], [
470
455
 
471
456
  // Nokia
472
- /(?:maemo|nokia).*(n900|lumia \d+)/i,
473
- /nokia[-_ ]?([-\w\.]*)/i
457
+ /(?:maemo|nokia).*(n900|lumia\s\d+)/i,
458
+ /nokia[\s_-]?([\w\.-]*)/i
474
459
  ], [[MODEL, /_/g, ' '], [VENDOR, 'Nokia'], [TYPE, MOBILE]], [
475
460
 
476
461
  // Google
477
- /(pixel c)\b/i // Google Pixel C
478
- ], [MODEL, [VENDOR, GOOGLE], [TYPE, TABLET]], [
479
- /droid.+; (pixel[\daxl ]{0,6})(?: bui|\))/i // Google Pixel
480
- ], [MODEL, [VENDOR, GOOGLE], [TYPE, MOBILE]], [
462
+ /droid.+;\s(pixel\sc)[\s)]/i // Google Pixel C
463
+ ], [MODEL, [VENDOR, 'Google'], [TYPE, TABLET]], [
464
+ /droid.+;\s(pixel[\s\daxl]{0,6})(?:\sbuild|\))/i // Google Pixel
465
+ ], [MODEL, [VENDOR, 'Google'], [TYPE, MOBILE]], [
481
466
 
482
467
  // Sony
483
- /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
484
- ], [MODEL, [VENDOR, SONY], [TYPE, MOBILE]], [
485
- /sony tablet [ps]/i,
486
- /\b(?:sony)?sgp\w+(?: bui|\))/i
487
- ], [[MODEL, 'Xperia Tablet'], [VENDOR, SONY], [TYPE, TABLET]], [
468
+ /droid.+\s([c-g]\d{4}|so[-l]\w+|xq-a\w[4-7][12])(?=\sbuild\/|\).+chrome\/(?![1-6]{0,1}\d\.))/i
469
+ ], [MODEL, [VENDOR, 'Sony'], [TYPE, MOBILE]], [
470
+ /sony\stablet\s[ps]\sbuild\//i,
471
+ /(?:sony)?sgp\w+(?:\sbuild\/|\))/i
472
+ ], [[MODEL, 'Xperia Tablet'], [VENDOR, 'Sony'], [TYPE, TABLET]], [
488
473
 
489
474
  // OnePlus
490
- / (kb2005|in20[12]5|be20[12][59])\b/i,
491
- /(?:one)?(?:plus)? (a\d0\d\d)(?: b|\))/i
475
+ /\s(kb2005|in20[12]5|be20[12][59])\b/i,
476
+ /\ba000(1)\sbuild/i, // OnePlus
477
+ /\boneplus\s(a\d{4})[\s)]/i
492
478
  ], [MODEL, [VENDOR, 'OnePlus'], [TYPE, MOBILE]], [
493
479
 
494
480
  // Amazon
495
481
  /(alexa)webm/i,
496
- /(kf[a-z]{2}wi|aeo[c-r]{2})( bui|\))/i, // Kindle Fire without Silk / Echo Show
497
- /(kf[a-z]+)( bui|\)).+silk\//i // Kindle Fire HD
498
- ], [MODEL, [VENDOR, AMAZON], [TYPE, TABLET]], [
499
- /((?:sd|kf)[0349hijorstuw]+)( bui|\)).+silk\//i // Fire Phone
500
- ], [[MODEL, /(.+)/g, 'Fire Phone $1'], [VENDOR, AMAZON], [TYPE, MOBILE]], [
482
+ /(kf[a-z]{2}wi)(\sbuild\/|\))/i, // Kindle Fire without Silk
483
+ /(kf[a-z]+)(\sbuild\/|\)).+silk\//i // Kindle Fire HD
484
+ ], [MODEL, [VENDOR, 'Amazon'], [TYPE, TABLET]], [
485
+ /(sd|kf)[0349hijorstuw]+(\sbuild\/|\)).+silk\//i // Fire Phone
486
+ ], [[MODEL, 'Fire Phone'], [VENDOR, 'Amazon'], [TYPE, MOBILE]], [
501
487
 
502
488
  // BlackBerry
503
- /(playbook);[-\w\),; ]+(rim)/i // BlackBerry PlayBook
489
+ /\((playbook);[\w\s\),;-]+(rim)/i // BlackBerry PlayBook
504
490
  ], [MODEL, VENDOR, [TYPE, TABLET]], [
505
- /\b((?:bb[a-f]|st[hv])100-\d)/i,
506
- /\(bb10; (\w+)/i // BlackBerry 10
507
- ], [MODEL, [VENDOR, BLACKBERRY], [TYPE, MOBILE]], [
491
+ /((?:bb[a-f]|st[hv])100-\d)/i,
492
+ /\(bb10;\s(\w+)/i // BlackBerry 10
493
+ ], [MODEL, [VENDOR, 'BlackBerry'], [TYPE, MOBILE]], [
508
494
 
509
495
  // Asus
510
- /(?:\b|asus_)(transfo[prime ]{4,10} \w+|eeepc|slider \w+|nexus 7|padfone|p00[cj])/i
511
- ], [MODEL, [VENDOR, ASUS], [TYPE, TABLET]], [
512
- / (z[bes]6[027][012][km][ls]|zenfone \d\w?)\b/i
513
- ], [MODEL, [VENDOR, ASUS], [TYPE, MOBILE]], [
496
+ /(?:\b|asus_)(transfo[prime\s]{4,10}\s\w+|eeepc|slider\s\w+|nexus\s7|padfone|p00[cj])/i
497
+ ], [MODEL, [VENDOR, 'ASUS'], [TYPE, TABLET]], [
498
+ /\s(z[es]6[027][01][km][ls]|zenfone\s\d\w?)\b/i
499
+ ], [MODEL, [VENDOR, 'ASUS'], [TYPE, MOBILE]], [
514
500
 
515
501
  // HTC
516
- /(nexus 9)/i // HTC Nexus 9
502
+ /(nexus\s9)/i // HTC Nexus 9
517
503
  ], [MODEL, [VENDOR, 'HTC'], [TYPE, TABLET]], [
518
- /(htc)[-;_ ]{1,2}([\w ]+(?=\)| bui)|\w+)/i, // HTC
504
+ /(htc)[;_\s-]{1,2}([\w\s]+(?=\)|\sbuild)|\w+)/i, // HTC
519
505
 
520
506
  // ZTE
521
- /(zte)[- ]([\w ]+?)(?: bui|\/|\))/i,
522
- /(alcatel|geeksphone|nexian|panasonic(?!(?:;|\.))|sony(?!-bra))[-_ ]?([-\w]*)/i // Alcatel/GeeksPhone/Nexian/Panasonic/Sony
507
+ /(zte)-(\w*)/i,
508
+ /(alcatel|geeksphone|nexian|panasonic|(?=;\s)sony)[_\s-]?([\w-]*)/i // Alcatel/GeeksPhone/Nexian/Panasonic/Sony
523
509
  ], [VENDOR, [MODEL, /_/g, ' '], [TYPE, MOBILE]], [
524
510
 
525
511
  // Acer
526
- /droid.+; ([ab][1-7]-?[0178a]\d\d?)/i
512
+ /droid[x\d\.\s;]+\s([ab][1-7]\-?[0178a]\d\d?)/i
527
513
  ], [MODEL, [VENDOR, 'Acer'], [TYPE, TABLET]], [
528
514
 
529
515
  // Meizu
530
- /droid.+; (m[1-5] note) bui/i,
531
- /\bmz-([-\w]{2,})/i
516
+ /droid.+;\s(m[1-5]\snote)\sbuild/i,
517
+ /\bmz-([\w-]{2,})/i
532
518
  ], [MODEL, [VENDOR, 'Meizu'], [TYPE, MOBILE]], [
533
-
534
- // Ulefone
535
- /; ((?:power )?armor(?:[\w ]{0,8}))(?: bui|\))/i
536
- ], [MODEL, [VENDOR, 'Ulefone'], [TYPE, MOBILE]], [
537
519
 
538
520
  // MIXED
539
- /(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus|dell|meizu|motorola|polytron|infinix|tecno)[-_ ]?([-\w]*)/i,
521
+ /(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus|dell|meizu|motorola|polytron)[\s_-]?([\w-]*)/i,
540
522
  // BlackBerry/BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron
541
- /(hp) ([\w ]+\w)/i, // HP iPAQ
523
+ /(hp)\s([\w\s]+\w)/i, // HP iPAQ
542
524
  /(asus)-?(\w+)/i, // Asus
543
- /(microsoft); (lumia[\w ]+)/i, // Microsoft Lumia
544
- /(lenovo)[-_ ]?([-\w]+)/i, // Lenovo
545
- /(jolla)/i, // Jolla
546
- /(oppo) ?([\w ]+) bui/i // OPPO
525
+ /(microsoft);\s(lumia[\s\w]+)/i, // Microsoft Lumia
526
+ /(lenovo)[_\s-]?([\w-]+)/i, // Lenovo
527
+ /linux;.+(jolla);/i, // Jolla
528
+ /droid.+;\s(oppo)\s?([\w\s]+)\sbuild/i // OPPO
547
529
  ], [VENDOR, MODEL, [TYPE, MOBILE]], [
548
530
 
549
- /(kobo)\s(ereader|touch)/i, // Kobo
550
- /(archos) (gamepad2?)/i, // Archos
531
+ /(archos)\s(gamepad2?)/i, // Archos
551
532
  /(hp).+(touchpad(?!.+tablet)|tablet)/i, // HP TouchPad
552
533
  /(kindle)\/([\w\.]+)/i, // Kindle
553
- /(nook)[\w ]+build\/(\w+)/i, // Nook
554
- /(dell) (strea[kpr\d ]*[\dko])/i, // Dell Streak
555
- /(le[- ]+pan)[- ]+(\w{1,9}) bui/i, // Le Pan Tablets
556
- /(trinity)[- ]*(t\d{3}) bui/i, // Trinity Tablets
557
- /(gigaset)[- ]+(q\w{1,9}) bui/i, // Gigaset Tablets
558
- /(vodafone) ([\w ]+)(?:\)| bui)/i // Vodafone
534
+ /\s(nook)[\w\s]+build\/(\w+)/i, // Nook
535
+ /(dell)\s(strea[kpr\s\d]*[\dko])/i, // Dell Streak
536
+ /[;\/]\s?(le[\s\-]+pan)[\s\-]+(\w{1,9})\sbuild/i, // Le Pan Tablets
537
+ /[;\/]\s?(trinity)[\-\s]*(t\d{3})\sbuild/i, // Trinity Tablets
538
+ /\b(gigaset)[\s\-]+(q\w{1,9})\sbuild/i, // Gigaset Tablets
539
+ /\b(vodafone)\s([\w\s]+)(?:\)|\sbuild)/i // Vodafone
559
540
  ], [VENDOR, MODEL, [TYPE, TABLET]], [
560
541
 
561
- /(surface duo)/i // Surface Duo
562
- ], [MODEL, [VENDOR, MICROSOFT], [TYPE, TABLET]], [
563
- /droid [\d\.]+; (fp\du?)(?: b|\))/i // Fairphone
542
+ /\s(surface\sduo)\s/i // Surface Duo
543
+ ], [MODEL, [VENDOR, 'Microsoft'], [TYPE, TABLET]], [
544
+ /droid\s[\d\.]+;\s(fp\du?)\sbuild/i
564
545
  ], [MODEL, [VENDOR, 'Fairphone'], [TYPE, MOBILE]], [
565
- /(u304aa)/i // AT&T
546
+ /\s(u304aa)\sbuild/i // AT&T
566
547
  ], [MODEL, [VENDOR, 'AT&T'], [TYPE, MOBILE]], [
567
- /\bsie-(\w*)/i // Siemens
548
+ /sie-(\w*)/i // Siemens
568
549
  ], [MODEL, [VENDOR, 'Siemens'], [TYPE, MOBILE]], [
569
- /\b(rct\w+) b/i // RCA Tablets
550
+ /[;\/]\s?(rct\w+)\sbuild/i // RCA Tablets
570
551
  ], [MODEL, [VENDOR, 'RCA'], [TYPE, TABLET]], [
571
- /\b(venue[\d ]{2,7}) b/i // Dell Venue Tablets
552
+ /[;\/\s](venue[\d\s]{2,7})\sbuild/i // Dell Venue Tablets
572
553
  ], [MODEL, [VENDOR, 'Dell'], [TYPE, TABLET]], [
573
- /\b(q(?:mv|ta)\w+) b/i // Verizon Tablet
554
+ /[;\/]\s?(q(?:mv|ta)\w+)\sbuild/i // Verizon Tablet
574
555
  ], [MODEL, [VENDOR, 'Verizon'], [TYPE, TABLET]], [
575
- /\b(?:barnes[& ]+noble |bn[rt])([\w\+ ]*) b/i // Barnes & Noble Tablet
556
+ /[;\/]\s(?:barnes[&\s]+noble\s|bn[rt])([\w\s\+]*)\sbuild/i // Barnes & Noble Tablet
576
557
  ], [MODEL, [VENDOR, 'Barnes & Noble'], [TYPE, TABLET]], [
577
- /\b(tm\d{3}\w+) b/i
558
+ /[;\/]\s(tm\d{3}\w+)\sbuild/i
578
559
  ], [MODEL, [VENDOR, 'NuVision'], [TYPE, TABLET]], [
579
- /\b(k88) b/i // ZTE K Series Tablet
560
+ /;\s(k88)\sbuild/i // ZTE K Series Tablet
580
561
  ], [MODEL, [VENDOR, 'ZTE'], [TYPE, TABLET]], [
581
- /\b(nx\d{3}j) b/i // ZTE Nubia
562
+ /;\s(nx\d{3}j)\sbuild/i // ZTE Nubia
582
563
  ], [MODEL, [VENDOR, 'ZTE'], [TYPE, MOBILE]], [
583
- /\b(gen\d{3}) b.+49h/i // Swiss GEN Mobile
564
+ /[;\/]\s?(gen\d{3})\sbuild.*49h/i // Swiss GEN Mobile
584
565
  ], [MODEL, [VENDOR, 'Swiss'], [TYPE, MOBILE]], [
585
- /\b(zur\d{3}) b/i // Swiss ZUR Tablet
566
+ /[;\/]\s?(zur\d{3})\sbuild/i // Swiss ZUR Tablet
586
567
  ], [MODEL, [VENDOR, 'Swiss'], [TYPE, TABLET]], [
587
- /\b((zeki)?tb.*\b) b/i // Zeki Tablets
568
+ /[;\/]\s?((zeki)?tb.*\b)\sbuild/i // Zeki Tablets
588
569
  ], [MODEL, [VENDOR, 'Zeki'], [TYPE, TABLET]], [
589
- /\b([yr]\d{2}) b/i,
590
- /\b(dragon[- ]+touch |dt)(\w{5}) b/i // Dragon Touch Tablet
570
+ /[;\/]\s([yr]\d{2})\sbuild/i,
571
+ /[;\/]\s(dragon[\-\s]+touch\s|dt)(\w{5})\sbuild/i // Dragon Touch Tablet
591
572
  ], [[VENDOR, 'Dragon Touch'], MODEL, [TYPE, TABLET]], [
592
- /\b(ns-?\w{0,9}) b/i // Insignia Tablets
573
+ /[;\/]\s?(ns-?\w{0,9})\sbuild/i // Insignia Tablets
593
574
  ], [MODEL, [VENDOR, 'Insignia'], [TYPE, TABLET]], [
594
- /\b((nxa|next)-?\w{0,9}) b/i // NextBook Tablets
575
+ /[;\/]\s?((nxa|Next)-?\w{0,9})\sbuild/i // NextBook Tablets
595
576
  ], [MODEL, [VENDOR, 'NextBook'], [TYPE, TABLET]], [
596
- /\b(xtreme\_)?(v(1[045]|2[015]|[3469]0|7[05])) b/i // Voice Xtreme Phones
597
- ], [[VENDOR, 'Voice'], MODEL, [TYPE, MOBILE]], [
598
- /\b(lvtel\-)?(v1[12]) b/i // LvTel Phones
577
+ /[;\/]\s?(xtreme\_)?(v(1[045]|2[015]|[3469]0|7[05]))\sbuild/i
578
+ ], [[VENDOR, 'Voice'], MODEL, [TYPE, MOBILE]], [ // Voice Xtreme Phones
579
+ /[;\/]\s?(lvtel\-)?(v1[12])\sbuild/i // LvTel Phones
599
580
  ], [[VENDOR, 'LvTel'], MODEL, [TYPE, MOBILE]], [
600
- /\b(ph-1) /i // Essential PH-1
601
- ], [MODEL, [VENDOR, 'Essential'], [TYPE, MOBILE]], [
602
- /\b(v(100md|700na|7011|917g).*\b) b/i // Envizen Tablets
581
+ /;\s(ph-1)\s/i
582
+ ], [MODEL, [VENDOR, 'Essential'], [TYPE, MOBILE]], [ // Essential PH-1
583
+ /[;\/]\s?(v(100md|700na|7011|917g).*\b)\sbuild/i // Envizen Tablets
603
584
  ], [MODEL, [VENDOR, 'Envizen'], [TYPE, TABLET]], [
604
- /\b(trio[-\w\. ]+) b/i // MachSpeed Tablets
585
+ /[;\/]\s?(trio[\s\w\-\.]+)\sbuild/i // MachSpeed Tablets
605
586
  ], [MODEL, [VENDOR, 'MachSpeed'], [TYPE, TABLET]], [
606
- /\btu_(1491) b/i // Rotor Tablets
587
+ /[;\/]\s?tu_(1491)\sbuild/i // Rotor Tablets
607
588
  ], [MODEL, [VENDOR, 'Rotor'], [TYPE, TABLET]], [
608
- /(shield[\w ]+) b/i // Nvidia Shield Tablets
589
+ /(shield[\w\s]+)\sbuild/i // Nvidia Shield Tablets
609
590
  ], [MODEL, [VENDOR, 'Nvidia'], [TYPE, TABLET]], [
610
- /(sprint) (\w+)/i // Sprint Phones
591
+ /(sprint)\s(\w+)/i // Sprint Phones
611
592
  ], [VENDOR, MODEL, [TYPE, MOBILE]], [
612
593
  /(kin\.[onetw]{3})/i // Microsoft Kin
613
- ], [[MODEL, /\./g, ' '], [VENDOR, MICROSOFT], [TYPE, MOBILE]], [
614
- /droid.+; (cc6666?|et5[16]|mc[239][23]x?|vc8[03]x?)\)/i // Zebra
615
- ], [MODEL, [VENDOR, ZEBRA], [TYPE, TABLET]], [
616
- /droid.+; (ec30|ps20|tc[2-8]\d[kx])\)/i
617
- ], [MODEL, [VENDOR, ZEBRA], [TYPE, MOBILE]], [
594
+ ], [[MODEL, /\./g, ' '], [VENDOR, 'Microsoft'], [TYPE, MOBILE]], [
595
+ /droid\s[\d\.]+;\s(cc6666?|et5[16]|mc[239][23]x?|vc8[03]x?)\)/i // Zebra
596
+ ], [MODEL, [VENDOR, 'Zebra'], [TYPE, TABLET]], [
597
+ /droid\s[\d\.]+;\s(ec30|ps20|tc[2-8]\d[kx])\)/i
598
+ ], [MODEL, [VENDOR, 'Zebra'], [TYPE, MOBILE]], [
599
+
600
+ ///////////////////
601
+ // CONSOLES
602
+ ///////////////////
603
+
604
+ /\s(ouya)\s/i, // Ouya
605
+ /(nintendo)\s([wids3utch]+)/i // Nintendo
606
+ ], [VENDOR, MODEL, [TYPE, CONSOLE]], [
607
+ /droid.+;\s(shield)\sbuild/i // Nvidia
608
+ ], [MODEL, [VENDOR, 'Nvidia'], [TYPE, CONSOLE]], [
609
+ /(playstation\s[345portablevi]+)/i // Playstation
610
+ ], [MODEL, [VENDOR, 'Sony'], [TYPE, CONSOLE]], [
611
+ /[\s\(;](xbox(?:\sone)?(?!;\sxbox))[\s\);]/i // Microsoft Xbox
612
+ ], [MODEL, [VENDOR, 'Microsoft'], [TYPE, CONSOLE]], [
618
613
 
619
614
  ///////////////////
620
615
  // SMARTTVS
@@ -623,88 +618,61 @@
623
618
  /smart-tv.+(samsung)/i // Samsung
624
619
  ], [VENDOR, [TYPE, SMARTTV]], [
625
620
  /hbbtv.+maple;(\d+)/i
626
- ], [[MODEL, /^/, 'SmartTV'], [VENDOR, SAMSUNG], [TYPE, SMARTTV]], [
627
- /(nux; netcast.+smarttv|lg (netcast\.tv-201\d|android tv))/i // LG SmartTV
628
- ], [[VENDOR, LG], [TYPE, SMARTTV]], [
629
- /(apple) ?tv/i // Apple TV
630
- ], [VENDOR, [MODEL, APPLE+' TV'], [TYPE, SMARTTV]], [
621
+ ], [[MODEL, /^/, 'SmartTV'], [VENDOR, 'Samsung'], [TYPE, SMARTTV]], [
622
+ /(?:linux;\snetcast.+smarttv|lg\snetcast\.tv-201\d)/i, // LG SmartTV
623
+ ], [[VENDOR, 'LG'], [TYPE, SMARTTV]], [
624
+ /(apple)\s?tv/i // Apple TV
625
+ ], [VENDOR, [MODEL, 'Apple TV'], [TYPE, SMARTTV]], [
631
626
  /crkey/i // Google Chromecast
632
- ], [[MODEL, CHROME+'cast'], [VENDOR, GOOGLE], [TYPE, SMARTTV]], [
633
- /droid.+aft(\w+)( bui|\))/i // Fire TV
634
- ], [MODEL, [VENDOR, AMAZON], [TYPE, SMARTTV]], [
635
- /\(dtv[\);].+(aquos)/i,
636
- /(aquos-tv[\w ]+)\)/i // Sharp
637
- ], [MODEL, [VENDOR, SHARP], [TYPE, SMARTTV]],[
638
- /(bravia[\w ]+)( bui|\))/i // Sony
639
- ], [MODEL, [VENDOR, SONY], [TYPE, SMARTTV]], [
640
- /(mitv-\w{5}) bui/i // Xiaomi
641
- ], [MODEL, [VENDOR, XIAOMI], [TYPE, SMARTTV]], [
642
- /Hbbtv.*(technisat) (.*);/i // TechniSAT
643
- ], [VENDOR, MODEL, [TYPE, SMARTTV]], [
644
- /\b(roku)[\dx]*[\)\/]((?:dvp-)?[\d\.]*)/i, // Roku
645
- /hbbtv\/\d+\.\d+\.\d+ +\([\w\+ ]*; *([\w\d][^;]*);([^;]*)/i // HbbTV devices
646
- ], [[VENDOR, trim], [MODEL, trim], [TYPE, SMARTTV]], [
647
- /\b(android tv|smart[- ]?tv|opera tv|tv; rv:)\b/i // SmartTV from Unidentified Vendors
627
+ ], [[MODEL, 'Chromecast'], [VENDOR, 'Google'], [TYPE, SMARTTV]], [
628
+ /droid.+aft([\w])(\sbuild\/|\))/i // Fire TV
629
+ ], [MODEL, [VENDOR, 'Amazon'], [TYPE, SMARTTV]], [
630
+ /\(dtv[\);].+(aquos)/i // Sharp
631
+ ], [MODEL, [VENDOR, 'Sharp'], [TYPE, SMARTTV]], [
632
+ /hbbtv\/\d+\.\d+\.\d+\s+\([\w\s]*;\s*(\w[^;]*);([^;]*)/i // HbbTV devices
633
+ ], [[VENDOR, util.trim], [MODEL, util.trim], [TYPE, SMARTTV]], [
634
+ /[\s\/\(](android\s|smart[-\s]?|opera\s)tv[;\)\s]/i // SmartTV from Unidentified Vendors
648
635
  ], [[TYPE, SMARTTV]], [
649
636
 
650
- ///////////////////
651
- // CONSOLES
652
- ///////////////////
653
-
654
- /(ouya)/i, // Ouya
655
- /(nintendo) ([wids3utch]+)/i // Nintendo
656
- ], [VENDOR, MODEL, [TYPE, CONSOLE]], [
657
- /droid.+; (shield) bui/i // Nvidia
658
- ], [MODEL, [VENDOR, 'Nvidia'], [TYPE, CONSOLE]], [
659
- /(playstation [345portablevi]+)/i // Playstation
660
- ], [MODEL, [VENDOR, SONY], [TYPE, CONSOLE]], [
661
- /\b(xbox(?: one)?(?!; xbox))[\); ]/i // Microsoft Xbox
662
- ], [MODEL, [VENDOR, MICROSOFT], [TYPE, CONSOLE]], [
663
-
664
637
  ///////////////////
665
638
  // WEARABLES
666
639
  ///////////////////
667
640
 
668
- /((pebble))app/i // Pebble
641
+ /((pebble))app\/[\d\.]+\s/i // Pebble
669
642
  ], [VENDOR, MODEL, [TYPE, WEARABLE]], [
670
- /(watch)(?: ?os[,\/]|\d,\d\/)[\d\.]+/i // Apple Watch
671
- ], [MODEL, [VENDOR, APPLE], [TYPE, WEARABLE]], [
672
- /droid.+; (glass) \d/i // Google Glass
673
- ], [MODEL, [VENDOR, GOOGLE], [TYPE, WEARABLE]], [
674
- /droid.+; (wt63?0{2,3})\)/i
675
- ], [MODEL, [VENDOR, ZEBRA], [TYPE, WEARABLE]], [
676
- /(quest( 2| pro)?)/i // Oculus Quest
677
- ], [MODEL, [VENDOR, FACEBOOK], [TYPE, WEARABLE]], [
643
+ /droid.+;\s(glass)\s\d/i // Google Glass
644
+ ], [MODEL, [VENDOR, 'Google'], [TYPE, WEARABLE]], [
645
+ /droid\s[\d\.]+;\s(wt63?0{2,3})\)/i
646
+ ], [MODEL, [VENDOR, 'Zebra'], [TYPE, WEARABLE]], [
678
647
 
679
648
  ///////////////////
680
649
  // EMBEDDED
681
650
  ///////////////////
682
651
 
683
- /(tesla)(?: qtcarbrowser|\/[-\w\.]+)/i // Tesla
652
+ /(tesla)(?:\sqtcarbrowser|\/20[12]\d\.[\w\.-]+)/i // Tesla
684
653
  ], [VENDOR, [TYPE, EMBEDDED]], [
685
- /(aeobc)\b/i // Echo Dot
686
- ], [MODEL, [VENDOR, AMAZON], [TYPE, EMBEDDED]], [
687
654
 
688
655
  ////////////////////
689
656
  // MIXED (GENERIC)
690
657
  ///////////////////
691
658
 
692
- /droid .+?; ([^;]+?)(?: bui|; wv\)|\) applew).+? mobile safari/i // Android Phones from Unidentified Vendors
659
+ /droid .+?; ([^;]+?)(?: build|\) applewebkit).+? mobile safari/i // Android Phones from Unidentified Vendors
693
660
  ], [MODEL, [TYPE, MOBILE]], [
694
- /droid .+?; ([^;]+?)(?: bui|\) applew).+?(?! mobile) safari/i // Android Tablets from Unidentified Vendors
661
+ /droid .+?;\s([^;]+?)(?: build|\) applewebkit).+?(?! mobile) safari/i // Android Tablets from Unidentified Vendors
695
662
  ], [MODEL, [TYPE, TABLET]], [
696
- /\b((tablet|tab)[;\/]|focus\/\d(?!.+mobile))/i // Unidentifiable Tablet
697
- ], [[TYPE, TABLET]], [
698
- /(phone|mobile(?:[;\/]| [ \w\/\.]*safari)|pda(?=.+windows ce))/i // Unidentifiable Mobile
699
- ], [[TYPE, MOBILE]], [
700
- /(android[-\w\. ]{0,9});.+buil/i // Generic Android Device
701
- ], [MODEL, [VENDOR, 'Generic']]
663
+ /\s(tablet|tab)[;\/]/i, // Unidentifiable Tablet
664
+ /\s(mobile)(?:[;\/]|\ssafari)/i // Unidentifiable Mobile
665
+ ], [[TYPE, util.lowerize]], [
666
+ /(android[\w\.\s\-]{0,9});.+build/i // Generic Android Device
667
+ ], [MODEL, [VENDOR, 'Generic']], [
668
+ /(phone)/i
669
+ ], [[TYPE, MOBILE]]
702
670
  ],
703
671
 
704
672
  engine : [[
705
673
 
706
- /windows.+ edge\/([\w\.]+)/i // EdgeHTML
707
- ], [VERSION, [NAME, EDGE+'HTML']], [
674
+ /windows.+\sedge\/([\w\.]+)/i // EdgeHTML
675
+ ], [VERSION, [NAME, 'EdgeHTML']], [
708
676
 
709
677
  /webkit\/537\.36.+chrome\/(?!27)([\w\.]+)/i // Blink
710
678
  ], [VERSION, [NAME, 'Blink']], [
@@ -712,9 +680,8 @@
712
680
  /(presto)\/([\w\.]+)/i, // Presto
713
681
  /(webkit|trident|netfront|netsurf|amaya|lynx|w3m|goanna)\/([\w\.]+)/i, // WebKit/Trident/NetFront/NetSurf/Amaya/Lynx/w3m/Goanna
714
682
  /ekioh(flow)\/([\w\.]+)/i, // Flow
715
- /(khtml|tasman|links)[\/ ]\(?([\w\.]+)/i, // KHTML/Tasman/Links
716
- /(icab)[\/ ]([23]\.[\d\.]+)/i, // iCab
717
- /\b(libweb)/i
683
+ /(khtml|tasman|links)[\/\s]\(?([\w\.]+)/i, // KHTML/Tasman/Links
684
+ /(icab)[\/\s]([23]\.[\d\.]+)/i // iCab
718
685
  ], [NAME, VERSION], [
719
686
 
720
687
  /rv\:([\w\.]{1,9})\b.+(gecko)/i // Gecko
@@ -724,87 +691,81 @@
724
691
  os : [[
725
692
 
726
693
  // Windows
727
- /microsoft (windows) (vista|xp)/i // Windows (iTunes)
694
+ /microsoft\s(windows)\s(vista|xp)/i // Windows (iTunes)
728
695
  ], [NAME, VERSION], [
729
- /(windows (?:phone(?: os)?|mobile))[\/ ]?([\d\.\w ]*)/i // Windows Phone
730
- ], [NAME, [VERSION, strMapper, windowsVersionMap]], [
731
- /windows nt 6\.2; (arm)/i, // Windows RT
732
- /windows[\/ ]?([ntce\d\. ]+\w)(?!.+xbox)/i,
733
- /(?:win(?=3|9|n)|win 9x )([nt\d\.]+)/i
734
- ], [[VERSION, strMapper, windowsVersionMap], [NAME, 'Windows']], [
696
+ /(windows)\snt\s6\.2;\s(arm)/i, // Windows RT
697
+ /(windows\sphone(?:\sos)*)[\s\/]?([\d\.\s\w]*)/i, // Windows Phone
698
+ /(windows\smobile|windows)[\s\/]?([ntce\d\.\s]+\w)(?!.+xbox)/i
699
+ ], [NAME, [VERSION, mapper.str, maps.os.windows.version]], [
700
+ /(win(?=3|9|n)|win\s9x\s)([nt\d\.]+)/i
701
+ ], [[NAME, 'Windows'], [VERSION, mapper.str, maps.os.windows.version]], [
735
702
 
736
703
  // iOS/macOS
737
- /ip[honead]{2,4}\b(?:.*os ([\w]+) like mac|; opera)/i, // iOS
738
- /(?:ios;fbsv\/|iphone.+ios[\/ ])([\d\.]+)/i,
704
+ /ip[honead]{2,4}\b(?:.*os\s([\w]+)\slike\smac|;\sopera)/i, // iOS
739
705
  /cfnetwork\/.+darwin/i
740
706
  ], [[VERSION, /_/g, '.'], [NAME, 'iOS']], [
741
- /(mac os x) ?([\w\. ]*)/i,
742
- /(macintosh|mac_powerpc\b)(?!.+haiku)/i // Mac OS
743
- ], [[NAME, MAC_OS], [VERSION, /_/g, '.']], [
744
-
745
- // Mobile OSes
746
- /droid ([\w\.]+)\b.+(android[- ]x86|harmonyos)/i // Android-x86/HarmonyOS
747
- ], [VERSION, NAME], [ // Android/WebOS/QNX/Bada/RIM/Maemo/MeeGo/Sailfish OS
748
- /(android|webos|qnx|bada|rim tablet os|maemo|meego|sailfish)[-\/ ]?([\w\.]*)/i,
707
+ /(mac\sos\sx)\s?([\w\s\.]*)/i,
708
+ /(macintosh|mac(?=_powerpc)\s)(?!.+haiku)/i // Mac OS
709
+ ], [[NAME, 'Mac OS'], [VERSION, /_/g, '.']], [
710
+
711
+ // Mobile OSes // Android/WebOS/Palm/QNX/Bada/RIM/MeeGo/Contiki/Sailfish OS
712
+ /(android|webos|palm\sos|qnx|bada|rim\stablet\sos|meego|sailfish|contiki)[\/\s-]?([\w\.]*)/i,
749
713
  /(blackberry)\w*\/([\w\.]*)/i, // Blackberry
750
- /(tizen|kaios)[\/ ]([\w\.]+)/i, // Tizen/KaiOS
714
+ /(tizen|kaios)[\/\s]([\w\.]+)/i, // Tizen/KaiOS
751
715
  /\((series40);/i // Series 40
752
716
  ], [NAME, VERSION], [
753
717
  /\(bb(10);/i // BlackBerry 10
754
- ], [VERSION, [NAME, BLACKBERRY]], [
755
- /(?:symbian ?os|symbos|s60(?=;)|series60)[-\/ ]?([\w\.]*)/i // Symbian
718
+ ], [VERSION, [NAME, 'BlackBerry']], [
719
+ /(?:symbian\s?os|symbos|s60(?=;)|series60)[\/\s-]?([\w\.]*)/i // Symbian
756
720
  ], [VERSION, [NAME, 'Symbian']], [
757
- /mozilla\/[\d\.]+ \((?:mobile|tablet|tv|mobile; [\w ]+); rv:.+ gecko\/([\w\.]+)/i // Firefox OS
758
- ], [VERSION, [NAME, FIREFOX+' OS']], [
721
+ /mozilla.+\(mobile;.+gecko.+firefox/i // Firefox OS
722
+ ], [[NAME, 'Firefox OS']], [
759
723
  /web0s;.+rt(tv)/i,
760
724
  /\b(?:hp)?wos(?:browser)?\/([\w\.]+)/i // WebOS
761
725
  ], [VERSION, [NAME, 'webOS']], [
762
- /watch(?: ?os[,\/]|\d,\d\/)([\d\.]+)/i // watchOS
763
- ], [VERSION, [NAME, 'watchOS']], [
764
726
 
765
727
  // Google Chromecast
766
728
  /crkey\/([\d\.]+)/i // Google Chromecast
767
- ], [VERSION, [NAME, CHROME+'cast']], [
768
- /(cros) [\w]+(?:\)| ([\w\.]+)\b)/i // Chromium OS
769
- ], [[NAME, CHROMIUM_OS], VERSION],[
770
-
771
- // Smart TVs
772
- /panasonic;(viera)/i, // Panasonic Viera
773
- /(netrange)mmh/i, // Netrange
774
- /(nettv)\/(\d+\.[\w\.]+)/i, // NetTV
729
+ ], [VERSION, [NAME, 'Chromecast']], [
730
+ /(cros)\s[\w]+\s([\w\.]+\w)/i // Chromium OS
731
+ ], [[NAME, 'Chromium OS'], VERSION],[
775
732
 
776
733
  // Console
777
- /(nintendo|playstation) ([wids345portablevuch]+)/i, // Nintendo/Playstation
778
- /(xbox); +xbox ([^\);]+)/i, // Microsoft Xbox (360, One, X, S, Series X, Series S)
734
+ /(nintendo|playstation)\s([wids345portablevuch]+)/i, // Nintendo/Playstation
735
+ /(xbox);\s+xbox\s([^\);]+)/i, // Microsoft Xbox (360, One, X, S, Series X, Series S)
736
+
737
+ // GNU/Linux based
738
+ /(mint)[\/\s\(\)]?(\w*)/i, // Mint
739
+ /(mageia|vectorlinux)[;\s]/i, // Mageia/VectorLinux
740
+ /(joli|[kxln]?ubuntu|debian|suse|opensuse|gentoo|arch(?=\slinux)|slackware|fedora|mandriva|centos|pclinuxos|redhat|zenwalk|linpus|raspbian)(?:\sgnu\/linux)?(?:\slinux)?[\/\s-]?(?!chrom|package)([\w\.-]*)/i,
741
+ // Joli/Ubuntu/Debian/SUSE/Gentoo/Arch/Slackware
742
+ // Fedora/Mandriva/CentOS/PCLinuxOS/RedHat/Zenwalk/Linpus
743
+ /(hurd|linux)\s?([\w\.]*)/i, // Hurd/Linux
744
+ /(gnu)\s?([\w\.]*)/i, // GNU
745
+
746
+ // BSD based
747
+ /\s([frentopc-]{0,4}bsd|dragonfly)\s?(?!amd|[ix346]{1,2}86)([\w\.]*)/i, // FreeBSD/NetBSD/OpenBSD/PC-BSD/DragonFly
748
+ /(haiku)\s(\w+)/i // Haiku
749
+ ], [NAME, VERSION], [
779
750
 
780
751
  // Other
781
- /\b(joli|palm)\b ?(?:os)?\/?([\w\.]*)/i, // Joli/Palm
782
- /(mint)[\/\(\) ]?(\w*)/i, // Mint
783
- /(mageia|vectorlinux)[; ]/i, // Mageia/VectorLinux
784
- /([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,
785
- // Ubuntu/Debian/SUSE/Gentoo/Arch/Slackware/Fedora/Mandriva/CentOS/PCLinuxOS/RedHat/Zenwalk/Linpus/Raspbian/Plan9/Minix/RISCOS/Contiki/Deepin/Manjaro/elementary/Sabayon/Linspire
786
- /(hurd|linux) ?([\w\.]*)/i, // Hurd/Linux
787
- /(gnu) ?([\w\.]*)/i, // GNU
788
- /\b([-frentopcghs]{0,5}bsd|dragonfly)[\/ ]?(?!amd|[ix346]{1,2}86)([\w\.]*)/i, // FreeBSD/NetBSD/OpenBSD/PC-BSD/GhostBSD/DragonFly
789
- /(haiku) (\w+)/i // Haiku
790
- ], [NAME, VERSION], [
791
- /(sunos) ?([\w\.\d]*)/i // Solaris
752
+ /(sunos)\s?([\w\.\d]*)/i // Solaris
792
753
  ], [[NAME, 'Solaris'], VERSION], [
793
- /((?:open)?solaris)[-\/ ]?([\w\.]*)/i, // Solaris
794
- /(aix) ((\d)(?=\.|\)| )[\w\.])*/i, // AIX
795
- /\b(beos|os\/2|amigaos|morphos|openvms|fuchsia|hp-ux|serenityos)/i, // BeOS/OS2/AmigaOS/MorphOS/OpenVMS/Fuchsia/HP-UX/SerenityOS
796
- /(unix) ?([\w\.]*)/i // UNIX
754
+ /((?:open)?solaris)[\/\s-]?([\w\.]*)/i, // Solaris
755
+ /(aix)\s((\d)(?=\.|\)|\s)[\w\.])*/i, // AIX
756
+ /(plan\s9|minix|beos|os\/2|amigaos|morphos|risc\sos|openvms|fuchsia)/i, // Plan9/Minix/BeOS/OS2/AmigaOS/MorphOS/RISCOS/OpenVMS/Fuchsia
757
+ /(unix)\s?([\w\.]*)/i // UNIX
797
758
  ], [NAME, VERSION]
798
759
  ]
799
760
  };
800
761
 
762
+
801
763
  /////////////////
802
764
  // Constructor
803
765
  ////////////////
804
-
805
766
  var UAParser = function (ua, extensions) {
806
767
 
807
- if (typeof ua === OBJ_TYPE) {
768
+ if (typeof ua === 'object') {
808
769
  extensions = ua;
809
770
  ua = undefined;
810
771
  }
@@ -813,63 +774,33 @@
813
774
  return new UAParser(ua, extensions).getResult();
814
775
  }
815
776
 
816
- var _navigator = (typeof window !== UNDEF_TYPE && window.navigator) ? window.navigator : undefined;
817
- var _ua = ua || ((_navigator && _navigator.userAgent) ? _navigator.userAgent : EMPTY);
818
- var _uach = (_navigator && _navigator.userAgentData) ? _navigator.userAgentData : undefined;
819
- var _rgxmap = extensions ? extend(regexes, extensions) : regexes;
820
- var _isSelfNav = _navigator && _navigator.userAgent == _ua;
777
+ var _ua = ua || ((typeof window !== 'undefined' && window.navigator && window.navigator.userAgent) ? window.navigator.userAgent : EMPTY);
778
+ var _rgxmap = extensions ? util.extend(regexes, extensions) : regexes;
821
779
 
822
780
  this.getBrowser = function () {
823
- var _browser = {};
824
- _browser[NAME] = undefined;
825
- _browser[VERSION] = undefined;
826
- rgxMapper.call(_browser, _ua, _rgxmap.browser);
827
- _browser[MAJOR] = majorize(_browser[VERSION]);
828
- // Brave-specific detection
829
- if (_isSelfNav && _navigator && _navigator.brave && typeof _navigator.brave.isBrave == FUNC_TYPE) {
830
- _browser[NAME] = 'Brave';
831
- }
781
+ var _browser = { name: undefined, version: undefined };
782
+ mapper.rgx.call(_browser, _ua, _rgxmap.browser);
783
+ _browser.major = util.major(_browser.version); // deprecated
832
784
  return _browser;
833
785
  };
834
786
  this.getCPU = function () {
835
- var _cpu = {};
836
- _cpu[ARCHITECTURE] = undefined;
837
- rgxMapper.call(_cpu, _ua, _rgxmap.cpu);
787
+ var _cpu = { architecture: undefined };
788
+ mapper.rgx.call(_cpu, _ua, _rgxmap.cpu);
838
789
  return _cpu;
839
790
  };
840
791
  this.getDevice = function () {
841
- var _device = {};
842
- _device[VENDOR] = undefined;
843
- _device[MODEL] = undefined;
844
- _device[TYPE] = undefined;
845
- rgxMapper.call(_device, _ua, _rgxmap.device);
846
- if (_isSelfNav && !_device[TYPE] && _uach && _uach.mobile) {
847
- _device[TYPE] = MOBILE;
848
- }
849
- // iPadOS-specific detection: identified as Mac, but has some iOS-only properties
850
- if (_isSelfNav && _device[MODEL] == 'Macintosh' && _navigator && typeof _navigator.standalone !== UNDEF_TYPE && _navigator.maxTouchPoints && _navigator.maxTouchPoints > 2) {
851
- _device[MODEL] = 'iPad';
852
- _device[TYPE] = TABLET;
853
- }
792
+ var _device = { vendor: undefined, model: undefined, type: undefined };
793
+ mapper.rgx.call(_device, _ua, _rgxmap.device);
854
794
  return _device;
855
795
  };
856
796
  this.getEngine = function () {
857
- var _engine = {};
858
- _engine[NAME] = undefined;
859
- _engine[VERSION] = undefined;
860
- rgxMapper.call(_engine, _ua, _rgxmap.engine);
797
+ var _engine = { name: undefined, version: undefined };
798
+ mapper.rgx.call(_engine, _ua, _rgxmap.engine);
861
799
  return _engine;
862
800
  };
863
801
  this.getOS = function () {
864
- var _os = {};
865
- _os[NAME] = undefined;
866
- _os[VERSION] = undefined;
867
- rgxMapper.call(_os, _ua, _rgxmap.os);
868
- if (_isSelfNav && !_os[NAME] && _uach && _uach.platform != 'Unknown') {
869
- _os[NAME] = _uach.platform
870
- .replace(/chrome os/i, CHROMIUM_OS)
871
- .replace(/macos/i, MAC_OS); // backward compatibility
872
- }
802
+ var _os = { name: undefined, version: undefined };
803
+ mapper.rgx.call(_os, _ua, _rgxmap.os);
873
804
  return _os;
874
805
  };
875
806
  this.getResult = function () {
@@ -886,7 +817,7 @@
886
817
  return _ua;
887
818
  };
888
819
  this.setUA = function (ua) {
889
- _ua = (typeof ua === STR_TYPE && ua.length > UA_MAX_LENGTH) ? trim(ua, UA_MAX_LENGTH) : ua;
820
+ _ua = (typeof ua === STR_TYPE && ua.length > UA_MAX_LENGTH) ? util.trim(ua, UA_MAX_LENGTH) : ua;
890
821
  return this;
891
822
  };
892
823
  this.setUA(_ua);
@@ -894,15 +825,39 @@
894
825
  };
895
826
 
896
827
  UAParser.VERSION = LIBVERSION;
897
- UAParser.BROWSER = enumerize([NAME, VERSION, MAJOR]);
898
- UAParser.CPU = enumerize([ARCHITECTURE]);
899
- UAParser.DEVICE = enumerize([MODEL, VENDOR, TYPE, CONSOLE, MOBILE, SMARTTV, TABLET, WEARABLE, EMBEDDED]);
900
- UAParser.ENGINE = UAParser.OS = enumerize([NAME, VERSION]);
828
+ UAParser.BROWSER = {
829
+ NAME : NAME,
830
+ MAJOR : MAJOR, // deprecated
831
+ VERSION : VERSION
832
+ };
833
+ UAParser.CPU = {
834
+ ARCHITECTURE : ARCHITECTURE
835
+ };
836
+ UAParser.DEVICE = {
837
+ MODEL : MODEL,
838
+ VENDOR : VENDOR,
839
+ TYPE : TYPE,
840
+ CONSOLE : CONSOLE,
841
+ MOBILE : MOBILE,
842
+ SMARTTV : SMARTTV,
843
+ TABLET : TABLET,
844
+ WEARABLE: WEARABLE,
845
+ EMBEDDED: EMBEDDED
846
+ };
847
+ UAParser.ENGINE = {
848
+ NAME : NAME,
849
+ VERSION : VERSION
850
+ };
851
+ UAParser.OS = {
852
+ NAME : NAME,
853
+ VERSION : VERSION
854
+ };
901
855
 
902
856
  ///////////
903
857
  // Export
904
858
  //////////
905
859
 
860
+
906
861
  // check js environment
907
862
  if (typeof(exports) !== UNDEF_TYPE) {
908
863
  // nodejs env
@@ -912,11 +867,11 @@
912
867
  exports.UAParser = UAParser;
913
868
  } else {
914
869
  // requirejs env (optional)
915
- if (typeof(define) === FUNC_TYPE && define.amd) {
870
+ if (typeof(define) === 'function' && define.amd) {
916
871
  define(function () {
917
872
  return UAParser;
918
873
  });
919
- } else if (typeof window !== UNDEF_TYPE) {
874
+ } else if (typeof window !== 'undefined') {
920
875
  // browser env
921
876
  window.UAParser = UAParser;
922
877
  }
@@ -927,15 +882,15 @@
927
882
  // In AMD env the global scope should be kept clean, but jQuery is an exception.
928
883
  // jQuery always exports to global scope, unless jQuery.noConflict(true) is used,
929
884
  // and we should catch that.
930
- var $ = typeof window !== UNDEF_TYPE && (window.jQuery || window.Zepto);
885
+ var $ = typeof window !== 'undefined' && (window.jQuery || window.Zepto);
931
886
  if ($ && !$.ua) {
932
887
  var parser = new UAParser();
933
888
  $.ua = parser.getResult();
934
889
  $.ua.get = function () {
935
890
  return parser.getUA();
936
891
  };
937
- $.ua.set = function (ua) {
938
- parser.setUA(ua);
892
+ $.ua.set = function (uastring) {
893
+ parser.setUA(uastring);
939
894
  var result = parser.getResult();
940
895
  for (var prop in result) {
941
896
  $.ua[prop] = result[prop];