ua-parser-js 0.7.21 → 0.7.30

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.

Potentially problematic release.


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

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