ua-parser-js 0.7.28 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
package/src/ua-parser.js CHANGED
@@ -1,11 +1,12 @@
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
- */
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.28',
20
+ var LIBVERSION = '1.0.1',
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',
@@ -38,14 +39,31 @@
38
39
  EMBEDDED = 'embedded',
39
40
  UA_MAX_LENGTH = 255;
40
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';
41
61
 
42
62
  ///////////
43
63
  // Helper
44
64
  //////////
45
65
 
46
-
47
- var util = {
48
- extend : function (regexes, extensions) {
66
+ var extend = function (regexes, extensions) {
49
67
  var mergedRegexes = {};
50
68
  for (var i in regexes) {
51
69
  if (extensions[i] && extensions[i].length % 2 === 0) {
@@ -56,30 +74,34 @@
56
74
  }
57
75
  return mergedRegexes;
58
76
  },
59
- has : function (str1, str2) {
60
- return typeof str1 === STR_TYPE ? str2.toLowerCase().indexOf(str1.toLowerCase()) !== -1 : false;
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;
61
86
  },
62
- lowerize : function (str) {
87
+ lowerize = function (str) {
63
88
  return str.toLowerCase();
64
89
  },
65
- major : function (version) {
66
- 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;
67
92
  },
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
- }
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
+ }
72
98
  };
73
99
 
74
-
75
100
  ///////////////
76
101
  // Map helper
77
102
  //////////////
78
103
 
79
-
80
- var mapper = {
81
-
82
- rgx : function (ua, arrays) {
104
+ var rgxMapper = function (ua, arrays) {
83
105
 
84
106
  var i = 0, j, k, p, q, matches, match;
85
107
 
@@ -131,84 +153,56 @@
131
153
  }
132
154
  },
133
155
 
134
- str : function (str, map) {
156
+ strMapper = function (str, map) {
135
157
 
136
158
  for (var i in map) {
137
- // check if array
159
+ // check if current value is array
138
160
  if (typeof map[i] === OBJ_TYPE && map[i].length > 0) {
139
161
  for (var j = 0; j < map[i].length; j++) {
140
- if (util.has(map[i][j], str)) {
162
+ if (has(map[i][j], str)) {
141
163
  return (i === UNKNOWN) ? undefined : i;
142
164
  }
143
165
  }
144
- } else if (util.has(map[i], str)) {
166
+ } else if (has(map[i], str)) {
145
167
  return (i === UNKNOWN) ? undefined : i;
146
168
  }
147
169
  }
148
170
  return str;
149
- }
150
171
  };
151
172
 
152
-
153
173
  ///////////////
154
174
  // String map
155
175
  //////////////
156
176
 
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
- }
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
+ '?' : '/'
185
187
  },
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
- }
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'
204
200
  };
205
201
 
206
-
207
202
  //////////////
208
203
  // Regex map
209
204
  /////////////
210
205
 
211
-
212
206
  var regexes = {
213
207
 
214
208
  browser : [[
@@ -217,164 +211,155 @@
217
211
  ], [VERSION, [NAME, 'Chrome']], [
218
212
  /edg(?:e|ios|a)?\/([\w\.]+)/i // Microsoft Edge
219
213
  ], [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']], [
223
214
 
224
215
  // Presto based
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
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
- /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']], [
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]], [
233
224
 
234
225
  // Mixed
235
226
  /(kindle)\/([\w\.]+)/i, // Kindle
236
- /(lunascape|maxthon|netfront|jasmine|blazer)[\/\s]?([\w\.]*)/i, // Lunascape/Maxthon/Netfront/Jasmine/Blazer
227
+ /(lunascape|maxthon|netfront|jasmine|blazer)[\/ ]?([\w\.]*)/i, // Lunascape/Maxthon/Netfront/Jasmine/Blazer
237
228
  // Trident based
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
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
246
236
  /(weibo)__([\d\.]+)/i // Weibo
247
237
  ], [NAME, VERSION], [
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
238
+ /(?:\buc? ?browser|(?:juc.+)ucweb)[\/ ]?([\w\.]+)/i // UCBrowser
239
+ ], [VERSION, [NAME, 'UC'+BROWSER]], [
240
+ /\bqbcore\/([\w\.]+)/i // WeChat Desktop for Windows Built-in Browser
251
241
  ], [VERSION, [NAME, 'WeChat(Win) Desktop']], [
252
242
  /micromessenger\/([\w\.]+)/i // WeChat
253
243
  ], [VERSION, [NAME, 'WeChat']], [
254
244
  /konqueror\/([\w\.]+)/i // Konqueror
255
245
  ], [VERSION, [NAME, 'Konqueror']], [
256
- /trident.+rv[:\s]([\w\.]{1,9})\b.+like\sgecko/i // IE11
246
+ /trident.+rv[: ]([\w\.]{1,9})\b.+like gecko/i // IE11
257
247
  ], [VERSION, [NAME, 'IE']], [
258
248
  /yabrowser\/([\w\.]+)/i // Yandex
259
249
  ], [VERSION, [NAME, 'Yandex']], [
260
250
  /(avast|avg)\/([\w\.]+)/i // Avast/AVG Secure 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
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
267
257
  ], [VERSION, [NAME, 'Coc Coc']], [
268
258
  /dolfin\/([\w\.]+)/i // Dolphin
269
259
  ], [VERSION, [NAME, 'Dolphin']], [
270
260
  /coast\/([\w\.]+)/i // Opera Coast
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']], [
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]], [
278
268
  /(oculus|samsung|sailfish)browser\/([\w\.]+)/i
279
- ], [[NAME, /(.+)/, '$1 Browser'], VERSION], [ // Oculus/Samsung/Sailfish Browser
269
+ ], [[NAME, /(.+)/, '$1 '+BROWSER], VERSION], [ // Oculus/Samsung/Sailfish Browser
280
270
  /(comodo_dragon)\/([\w\.]+)/i // Comodo Dragon
281
271
  ], [[NAME, /_/g, ' '], VERSION], [
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
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
285
275
  ], [NAME, VERSION], [
286
- /(MetaSr)[\/\s]?([\w\.]+)/i, // SouGouBrowser
287
- /(LBBROWSER)/i // LieBao Browser
276
+ /(metasr)[\/ ]?([\w\.]+)/i, // SouGouBrowser
277
+ /(lbbrowser)/i // LieBao Browser
288
278
  ], [NAME], [
289
279
 
290
280
  // WebView
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
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
296
284
  /\b(line)\/([\w\.]+)\/iab/i, // Line App for Android
297
- /(chromium|instagram)[\/\s]([\w\.-]+)/i // Chromium/Instagram
285
+ /(chromium|instagram)[\/ ]([-\w\.]+)/i // Chromium/Instagram
298
286
  ], [NAME, VERSION], [
299
- /\bgsa\/([\w\.]+)\s.*safari\//i // Google Search Appliance on iOS
287
+ /\bgsa\/([\w\.]+) .*safari\//i // Google Search Appliance on iOS
300
288
  ], [VERSION, [NAME, 'GSA']], [
301
289
 
302
- /headlesschrome(?:\/([\w\.]+)|\s)/i // Chrome Headless
303
- ], [VERSION, [NAME, 'Chrome Headless']], [
290
+ /headlesschrome(?:\/([\w\.]+)| )/i // Chrome Headless
291
+ ], [VERSION, [NAME, CHROME+' Headless']], [
304
292
 
305
- /\swv\).+(chrome)\/([\w\.]+)/i // Chrome WebView
306
- ], [[NAME, 'Chrome WebView'], VERSION], [
293
+ / wv\).+(chrome)\/([\w\.]+)/i // Chrome WebView
294
+ ], [[NAME, CHROME+' WebView'], VERSION], [
307
295
 
308
- /droid.+\sversion\/([\w\.]+)\b.+(?:mobile\ssafari|safari)/i // Android Browser
309
- ], [VERSION, [NAME, 'Android Browser']], [
296
+ /droid.+ version\/([\w\.]+)\b.+(?:mobile safari|safari)/i // Android Browser
297
+ ], [VERSION, [NAME, 'Android '+BROWSER]], [
310
298
 
311
- /(chrome|omniweb|arora|[tizenoka]{5}\s?browser)\/v?([\w\.]+)/i // Chrome/OmniWeb/Arora/Tizen/Nokia
299
+ /(chrome|omniweb|arora|[tizenoka]{5} ?browser)\/v?([\w\.]+)/i // Chrome/OmniWeb/Arora/Tizen/Nokia
312
300
  ], [NAME, VERSION], [
313
301
 
314
- /version\/([\w\.]+)\s.*mobile\/\w+\s(safari)/i // Mobile Safari
302
+ /version\/([\w\.]+) .*mobile\/\w+ (safari)/i // Mobile Safari
315
303
  ], [VERSION, [NAME, 'Mobile Safari']], [
316
- /version\/([\w\.]+)\s.*(mobile\s?safari|safari)/i // Safari & Safari Mobile
304
+ /version\/([\w\.]+) .*(mobile ?safari|safari)/i // Safari & Safari Mobile
317
305
  ], [VERSION, NAME], [
318
- /webkit.+?(mobile\s?safari|safari)(\/[\w\.]+)/i // Safari < 3.0
319
- ], [NAME, [VERSION, mapper.str, maps.browser.oldSafari.version]], [
306
+ /webkit.+?(mobile ?safari|safari)(\/[\w\.]+)/i // Safari < 3.0
307
+ ], [NAME, [VERSION, strMapper, oldSafariMap]], [
320
308
 
321
309
  /(webkit|khtml)\/([\w\.]+)/i
322
310
  ], [NAME, VERSION], [
323
311
 
324
312
  // Gecko based
325
- /(navigator|netscape)\/([\w\.-]+)/i // Netscape
313
+ /(navigator|netscape\d?)\/([-\w\.]+)/i // Netscape
326
314
  ], [[NAME, 'Netscape'], VERSION], [
327
- /ile\svr;\srv:([\w\.]+)\).+firefox/i // Firefox Reality
328
- ], [VERSION, [NAME, 'Firefox Reality']], [
315
+ /mobile vr; rv:([\w\.]+)\).+firefox/i // Firefox Reality
316
+ ], [VERSION, [NAME, FIREFOX+' Reality']], [
329
317
  /ekiohf.+(flow)\/([\w\.]+)/i, // Flow
330
318
  /(swiftfox)/i, // Swiftfox
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,
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,
334
322
  // Firefox/SeaMonkey/K-Meleon/IceCat/IceApe/Firebird/Phoenix
335
- /(firefox)\/([\w\.]+)\s[\w\s\-]+\/[\w\.]+$/i, // Other Firefox-based
336
- /(mozilla)\/([\w\.]+)\s.+rv\:.+gecko\/\d+/i, // Mozilla
323
+ /(firefox)\/([\w\.]+)/i, // Other Firefox-based
324
+ /(mozilla)\/([\w\.]+) .+rv\:.+gecko\/\d+/i, // Mozilla
337
325
 
338
326
  // Other
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
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
345
330
  ], [NAME, VERSION]
346
331
  ],
347
332
 
348
333
  cpu : [[
349
334
 
350
- /(?:(amd|x(?:(?:86|64)[_-])?|wow|win)64)[;\)]/i // AMD64 (x64)
335
+ /(?:(amd|x(?:(?:86|64)[-_])?|wow|win)64)[;\)]/i // AMD64 (x64)
351
336
  ], [[ARCHITECTURE, 'amd64']], [
352
337
 
353
338
  /(ia32(?=;))/i // IA32 (quicktime)
354
- ], [[ARCHITECTURE, util.lowerize]], [
339
+ ], [[ARCHITECTURE, lowerize]], [
355
340
 
356
341
  /((?:i[346]|x)86)[;\)]/i // IA32 (x86)
357
342
  ], [[ARCHITECTURE, 'ia32']], [
358
343
 
359
- /\b(aarch64|armv?8e?l?)\b/i // ARM64
344
+ /\b(aarch64|arm(v?8e?l?|_?64))\b/i // ARM64
360
345
  ], [[ARCHITECTURE, 'arm64']], [
361
346
 
362
347
  /\b(arm(?:v[67])?ht?n?[fl]p?)\b/i // ARMHF
363
348
  ], [[ARCHITECTURE, 'armhf']], [
364
349
 
365
350
  // PocketPC mistakenly identified as PowerPC
366
- /windows\s(ce|mobile);\sppc;/i
351
+ /windows (ce|mobile); ppc;/i
367
352
  ], [[ARCHITECTURE, 'arm']], [
368
353
 
369
- /((?:ppc|powerpc)(?:64)?)(?:\smac|;|\))/i // PowerPC
370
- ], [[ARCHITECTURE, /ower/, '', util.lowerize]], [
354
+ /((?:ppc|powerpc)(?:64)?)(?: mac|;|\))/i // PowerPC
355
+ ], [[ARCHITECTURE, /ower/, EMPTY, lowerize]], [
371
356
 
372
357
  /(sun4\w)[;\)]/i // SPARC
373
358
  ], [[ARCHITECTURE, 'sparc']], [
374
359
 
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
360
+ /((?:avr32|ia64(?=;))|68k(?=\))|\barm(?=v(?:[1-7]|[5-7]1)l?|;|eabi)|(?=atmel )avr|(?:irix|mips|sparc)(?:64)?\b|pa-risc)/i
376
361
  // IA64, 68K, ARM/64, AVR/32, IRIX/64, MIPS/64, SPARC/64, PA-RISC
377
- ], [[ARCHITECTURE, util.lowerize]]
362
+ ], [[ARCHITECTURE, lowerize]]
378
363
  ],
379
364
 
380
365
  device : [[
@@ -385,231 +370,233 @@
385
370
  /////////////////////////
386
371
 
387
372
  // Samsung
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,
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,
392
377
  /sec-(sgh\w+)/i
393
- ], [MODEL, [VENDOR, 'Samsung'], [TYPE, MOBILE]], [
378
+ ], [MODEL, [VENDOR, SAMSUNG], [TYPE, MOBILE]], [
394
379
 
395
380
  // Apple
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,
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,
400
385
  /\b(ipad)\d\d?,\d\d?[;\]].+ios/i
401
- ], [MODEL, [VENDOR, 'Apple'], [TYPE, TABLET]], [
386
+ ], [MODEL, [VENDOR, APPLE], [TYPE, TABLET]], [
402
387
 
403
388
  // Huawei
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]], [
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]], [
410
394
 
411
395
  // Xiaomi
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]], [
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]], [
420
404
 
421
405
  // OPPO
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
406
+ /; (\w+) bui.+ oppo/i,
407
+ /\b(cph[12]\d{3}|p(?:af|c[al]|d\w|e[ar])[mt]\d0|x9007)\b/i
424
408
  ], [MODEL, [VENDOR, 'OPPO'], [TYPE, MOBILE]], [
425
409
 
426
410
  // Vivo
427
- /\svivo\s(\w+)(?:\sbuild|\))/i,
428
- /\s(v[12]\d{3}\w?[at])(?:\sbuild|;)/i
411
+ /vivo (\w+)(?: bui|\))/i,
412
+ /\b(v[12]\d{3}\w?[at])(?: bui|;)/i
429
413
  ], [MODEL, [VENDOR, 'Vivo'], [TYPE, MOBILE]], [
430
414
 
431
415
  // Realme
432
- /\s(rmx[12]\d{3})(?:\sbuild|;)/i
416
+ /\b(rmx[12]\d{3})(?: bui|;|\))/i
433
417
  ], [MODEL, [VENDOR, 'Realme'], [TYPE, MOBILE]], [
434
418
 
435
419
  // Motorola
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]], [
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]], [
442
426
 
443
427
  // LG
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]], [
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]], [
450
434
 
451
435
  // Lenovo
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
436
+ /(ideatab[-\w ]+)/i,
437
+ /lenovo ?(s[56]000[-\w]+|tab(?:[\w ]+)|yt[-\d\w]{6}|tb[-\d\w]{6})/i
454
438
  ], [MODEL, [VENDOR, 'Lenovo'], [TYPE, TABLET]], [
455
439
 
456
440
  // Nokia
457
- /(?:maemo|nokia).*(n900|lumia\s\d+)/i,
458
- /nokia[\s_-]?([\w\.-]*)/i
441
+ /(?:maemo|nokia).*(n900|lumia \d+)/i,
442
+ /nokia[-_ ]?([-\w\.]*)/i
459
443
  ], [[MODEL, /_/g, ' '], [VENDOR, 'Nokia'], [TYPE, MOBILE]], [
460
444
 
461
445
  // Google
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]], [
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]], [
466
450
 
467
451
  // Sony
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]], [
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]], [
473
457
 
474
458
  // OnePlus
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
459
+ / (kb2005|in20[12]5|be20[12][59])\b/i,
460
+ /(?:one)?(?:plus)? (a\d0\d\d)(?: b|\))/i
478
461
  ], [MODEL, [VENDOR, 'OnePlus'], [TYPE, MOBILE]], [
479
462
 
480
463
  // Amazon
481
464
  /(alexa)webm/i,
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]], [
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]], [
487
470
 
488
471
  // BlackBerry
489
- /\((playbook);[\w\s\),;-]+(rim)/i // BlackBerry PlayBook
472
+ /(playbook);[-\w\),; ]+(rim)/i // BlackBerry PlayBook
490
473
  ], [MODEL, VENDOR, [TYPE, TABLET]], [
491
- /((?:bb[a-f]|st[hv])100-\d)/i,
492
- /\(bb10;\s(\w+)/i // BlackBerry 10
493
- ], [MODEL, [VENDOR, 'BlackBerry'], [TYPE, MOBILE]], [
474
+ /\b((?:bb[a-f]|st[hv])100-\d)/i,
475
+ /\(bb10; (\w+)/i // BlackBerry 10
476
+ ], [MODEL, [VENDOR, BLACKBERRY], [TYPE, MOBILE]], [
494
477
 
495
478
  // Asus
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]], [
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]], [
500
483
 
501
484
  // HTC
502
- /(nexus\s9)/i // HTC Nexus 9
485
+ /(nexus 9)/i // HTC Nexus 9
503
486
  ], [MODEL, [VENDOR, 'HTC'], [TYPE, TABLET]], [
504
- /(htc)[;_\s-]{1,2}([\w\s]+(?=\)|\sbuild)|\w+)/i, // HTC
487
+ /(htc)[-;_ ]{1,2}([\w ]+(?=\)| bui)|\w+)/i, // HTC
505
488
 
506
489
  // ZTE
507
- /(zte)-(\w*)/i,
508
- /(alcatel|geeksphone|nexian|panasonic|(?=;\s)sony)[_\s-]?([\w-]*)/i // Alcatel/GeeksPhone/Nexian/Panasonic/Sony
490
+ /(zte)[- ]([\w ]+?)(?: bui|\/|\))/i,
491
+ /(alcatel|geeksphone|nexian|panasonic|sony)[-_ ]?([-\w]*)/i // Alcatel/GeeksPhone/Nexian/Panasonic/Sony
509
492
  ], [VENDOR, [MODEL, /_/g, ' '], [TYPE, MOBILE]], [
510
493
 
511
494
  // Acer
512
- /droid[x\d\.\s;]+\s([ab][1-7]\-?[0178a]\d\d?)/i
495
+ /droid.+; ([ab][1-7]-?[0178a]\d\d?)/i
513
496
  ], [MODEL, [VENDOR, 'Acer'], [TYPE, TABLET]], [
514
497
 
515
498
  // Meizu
516
- /droid.+;\s(m[1-5]\snote)\sbuild/i,
517
- /\bmz-([\w-]{2,})/i
499
+ /droid.+; (m[1-5] note) bui/i,
500
+ /\bmz-([-\w]{2,})/i
518
501
  ], [MODEL, [VENDOR, 'Meizu'], [TYPE, MOBILE]], [
519
502
 
503
+ // Sharp
504
+ /\b(sh-?[altvz]?\d\d[a-ekm]?)/i
505
+ ], [MODEL, [VENDOR, 'Sharp'], [TYPE, MOBILE]], [
506
+
520
507
  // MIXED
521
- /(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus|dell|meizu|motorola|polytron)[\s_-]?([\w-]*)/i,
508
+ /(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus|dell|meizu|motorola|polytron)[-_ ]?([-\w]*)/i,
522
509
  // BlackBerry/BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron
523
- /(hp)\s([\w\s]+\w)/i, // HP iPAQ
510
+ /(hp) ([\w ]+\w)/i, // HP iPAQ
524
511
  /(asus)-?(\w+)/i, // Asus
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
512
+ /(microsoft); (lumia[\w ]+)/i, // Microsoft Lumia
513
+ /(lenovo)[-_ ]?([-\w]+)/i, // Lenovo
514
+ /(jolla)/i, // Jolla
515
+ /(oppo) ?([\w ]+) bui/i // OPPO
529
516
  ], [VENDOR, MODEL, [TYPE, MOBILE]], [
530
517
 
531
- /(archos)\s(gamepad2?)/i, // Archos
518
+ /(archos) (gamepad2?)/i, // Archos
532
519
  /(hp).+(touchpad(?!.+tablet)|tablet)/i, // HP TouchPad
533
520
  /(kindle)\/([\w\.]+)/i, // Kindle
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
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
540
527
  ], [VENDOR, MODEL, [TYPE, TABLET]], [
541
528
 
542
- /\s(surface\sduo)\s/i // Surface Duo
543
- ], [MODEL, [VENDOR, 'Microsoft'], [TYPE, TABLET]], [
544
- /droid\s[\d\.]+;\s(fp\du?)\sbuild/i
529
+ /(surface duo)/i // Surface Duo
530
+ ], [MODEL, [VENDOR, MICROSOFT], [TYPE, TABLET]], [
531
+ /droid [\d\.]+; (fp\du?)(?: b|\))/i // Fairphone
545
532
  ], [MODEL, [VENDOR, 'Fairphone'], [TYPE, MOBILE]], [
546
- /\s(u304aa)\sbuild/i // AT&T
533
+ /(u304aa)/i // AT&T
547
534
  ], [MODEL, [VENDOR, 'AT&T'], [TYPE, MOBILE]], [
548
- /sie-(\w*)/i // Siemens
535
+ /\bsie-(\w*)/i // Siemens
549
536
  ], [MODEL, [VENDOR, 'Siemens'], [TYPE, MOBILE]], [
550
- /[;\/]\s?(rct\w+)\sbuild/i // RCA Tablets
537
+ /\b(rct\w+) b/i // RCA Tablets
551
538
  ], [MODEL, [VENDOR, 'RCA'], [TYPE, TABLET]], [
552
- /[;\/\s](venue[\d\s]{2,7})\sbuild/i // Dell Venue Tablets
539
+ /\b(venue[\d ]{2,7}) b/i // Dell Venue Tablets
553
540
  ], [MODEL, [VENDOR, 'Dell'], [TYPE, TABLET]], [
554
- /[;\/]\s?(q(?:mv|ta)\w+)\sbuild/i // Verizon Tablet
541
+ /\b(q(?:mv|ta)\w+) b/i // Verizon Tablet
555
542
  ], [MODEL, [VENDOR, 'Verizon'], [TYPE, TABLET]], [
556
- /[;\/]\s(?:barnes[&\s]+noble\s|bn[rt])([\w\s\+]*)\sbuild/i // Barnes & Noble Tablet
543
+ /\b(?:barnes[& ]+noble |bn[rt])([\w\+ ]*) b/i // Barnes & Noble Tablet
557
544
  ], [MODEL, [VENDOR, 'Barnes & Noble'], [TYPE, TABLET]], [
558
- /[;\/]\s(tm\d{3}\w+)\sbuild/i
545
+ /\b(tm\d{3}\w+) b/i
559
546
  ], [MODEL, [VENDOR, 'NuVision'], [TYPE, TABLET]], [
560
- /;\s(k88)\sbuild/i // ZTE K Series Tablet
547
+ /\b(k88) b/i // ZTE K Series Tablet
561
548
  ], [MODEL, [VENDOR, 'ZTE'], [TYPE, TABLET]], [
562
- /;\s(nx\d{3}j)\sbuild/i // ZTE Nubia
549
+ /\b(nx\d{3}j) b/i // ZTE Nubia
563
550
  ], [MODEL, [VENDOR, 'ZTE'], [TYPE, MOBILE]], [
564
- /[;\/]\s?(gen\d{3})\sbuild.*49h/i // Swiss GEN Mobile
551
+ /\b(gen\d{3}) b.+49h/i // Swiss GEN Mobile
565
552
  ], [MODEL, [VENDOR, 'Swiss'], [TYPE, MOBILE]], [
566
- /[;\/]\s?(zur\d{3})\sbuild/i // Swiss ZUR Tablet
553
+ /\b(zur\d{3}) b/i // Swiss ZUR Tablet
567
554
  ], [MODEL, [VENDOR, 'Swiss'], [TYPE, TABLET]], [
568
- /[;\/]\s?((zeki)?tb.*\b)\sbuild/i // Zeki Tablets
555
+ /\b((zeki)?tb.*\b) b/i // Zeki Tablets
569
556
  ], [MODEL, [VENDOR, 'Zeki'], [TYPE, TABLET]], [
570
- /[;\/]\s([yr]\d{2})\sbuild/i,
571
- /[;\/]\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
572
559
  ], [[VENDOR, 'Dragon Touch'], MODEL, [TYPE, TABLET]], [
573
- /[;\/]\s?(ns-?\w{0,9})\sbuild/i // Insignia Tablets
560
+ /\b(ns-?\w{0,9}) b/i // Insignia Tablets
574
561
  ], [MODEL, [VENDOR, 'Insignia'], [TYPE, TABLET]], [
575
- /[;\/]\s?((nxa|Next)-?\w{0,9})\sbuild/i // NextBook Tablets
562
+ /\b((nxa|next)-?\w{0,9}) b/i // NextBook Tablets
576
563
  ], [MODEL, [VENDOR, 'NextBook'], [TYPE, TABLET]], [
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
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
580
567
  ], [[VENDOR, 'LvTel'], MODEL, [TYPE, MOBILE]], [
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
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
584
571
  ], [MODEL, [VENDOR, 'Envizen'], [TYPE, TABLET]], [
585
- /[;\/]\s?(trio[\s\w\-\.]+)\sbuild/i // MachSpeed Tablets
572
+ /\b(trio[-\w\. ]+) b/i // MachSpeed Tablets
586
573
  ], [MODEL, [VENDOR, 'MachSpeed'], [TYPE, TABLET]], [
587
- /[;\/]\s?tu_(1491)\sbuild/i // Rotor Tablets
574
+ /\btu_(1491) b/i // Rotor Tablets
588
575
  ], [MODEL, [VENDOR, 'Rotor'], [TYPE, TABLET]], [
589
- /(shield[\w\s]+)\sbuild/i // Nvidia Shield Tablets
576
+ /(shield[\w ]+) b/i // Nvidia Shield Tablets
590
577
  ], [MODEL, [VENDOR, 'Nvidia'], [TYPE, TABLET]], [
591
- /(sprint)\s(\w+)/i // Sprint Phones
578
+ /(sprint) (\w+)/i // Sprint Phones
592
579
  ], [VENDOR, MODEL, [TYPE, MOBILE]], [
593
580
  /(kin\.[onetw]{3})/i // Microsoft Kin
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]], [
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]], [
599
586
 
600
587
  ///////////////////
601
588
  // CONSOLES
602
589
  ///////////////////
603
590
 
604
- /\s(ouya)\s/i, // Ouya
605
- /(nintendo)\s([wids3utch]+)/i // Nintendo
591
+ /(ouya)/i, // Ouya
592
+ /(nintendo) ([wids3utch]+)/i // Nintendo
606
593
  ], [VENDOR, MODEL, [TYPE, CONSOLE]], [
607
- /droid.+;\s(shield)\sbuild/i // Nvidia
594
+ /droid.+; (shield) bui/i // Nvidia
608
595
  ], [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]], [
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]], [
613
600
 
614
601
  ///////////////////
615
602
  // SMARTTVS
@@ -618,61 +605,63 @@
618
605
  /smart-tv.+(samsung)/i // Samsung
619
606
  ], [VENDOR, [TYPE, SMARTTV]], [
620
607
  /hbbtv.+maple;(\d+)/i
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]], [
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]], [
626
613
  /crkey/i // Google Chromecast
627
- ], [[MODEL, 'Chromecast'], [VENDOR, 'Google'], [TYPE, SMARTTV]], [
628
- /droid.+aft([\w])(\sbuild\/|\))/i // Fire TV
629
- ], [MODEL, [VENDOR, 'Amazon'], [TYPE, SMARTTV]], [
614
+ ], [[MODEL, CHROME+'cast'], [VENDOR, GOOGLE], [TYPE, SMARTTV]], [
615
+ /droid.+aft(\w)( bui|\))/i // Fire TV
616
+ ], [MODEL, [VENDOR, AMAZON], [TYPE, SMARTTV]], [
630
617
  /\(dtv[\);].+(aquos)/i // Sharp
631
618
  ], [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
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
635
623
  ], [[TYPE, SMARTTV]], [
636
624
 
637
625
  ///////////////////
638
626
  // WEARABLES
639
627
  ///////////////////
640
628
 
641
- /((pebble))app\/[\d\.]+\s/i // Pebble
629
+ /((pebble))app/i // Pebble
642
630
  ], [VENDOR, MODEL, [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]], [
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]], [
647
637
 
648
638
  ///////////////////
649
639
  // EMBEDDED
650
640
  ///////////////////
651
641
 
652
- /(tesla)(?:\sqtcarbrowser|\/20[12]\d\.[\w\.-]+)/i // Tesla
642
+ /(tesla)(?: qtcarbrowser|\/[-\w\.]+)/i // Tesla
653
643
  ], [VENDOR, [TYPE, EMBEDDED]], [
654
644
 
655
645
  ////////////////////
656
646
  // MIXED (GENERIC)
657
647
  ///////////////////
658
648
 
659
- /droid .+?; ([^;]+?)(?: build|\) applewebkit).+? mobile safari/i // Android Phones from Unidentified Vendors
649
+ /droid .+?; ([^;]+?)(?: bui|\) applew).+? mobile safari/i // Android Phones from Unidentified Vendors
660
650
  ], [MODEL, [TYPE, MOBILE]], [
661
- /droid .+?;\s([^;]+?)(?: build|\) applewebkit).+?(?! mobile) safari/i // Android Tablets from Unidentified Vendors
651
+ /droid .+?; ([^;]+?)(?: bui|\) applew).+?(?! mobile) safari/i // Android Tablets from Unidentified Vendors
662
652
  ], [MODEL, [TYPE, TABLET]], [
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]]
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
658
+ ], [MODEL, [VENDOR, 'Generic']]
670
659
  ],
671
660
 
672
661
  engine : [[
673
662
 
674
- /windows.+\sedge\/([\w\.]+)/i // EdgeHTML
675
- ], [VERSION, [NAME, 'EdgeHTML']], [
663
+ /windows.+ edge\/([\w\.]+)/i // EdgeHTML
664
+ ], [VERSION, [NAME, EDGE+'HTML']], [
676
665
 
677
666
  /webkit\/537\.36.+chrome\/(?!27)([\w\.]+)/i // Blink
678
667
  ], [VERSION, [NAME, 'Blink']], [
@@ -680,8 +669,8 @@
680
669
  /(presto)\/([\w\.]+)/i, // Presto
681
670
  /(webkit|trident|netfront|netsurf|amaya|lynx|w3m|goanna)\/([\w\.]+)/i, // WebKit/Trident/NetFront/NetSurf/Amaya/Lynx/w3m/Goanna
682
671
  /ekioh(flow)\/([\w\.]+)/i, // Flow
683
- /(khtml|tasman|links)[\/\s]\(?([\w\.]+)/i, // KHTML/Tasman/Links
684
- /(icab)[\/\s]([23]\.[\d\.]+)/i // iCab
672
+ /(khtml|tasman|links)[\/ ]\(?([\w\.]+)/i, // KHTML/Tasman/Links
673
+ /(icab)[\/ ]([23]\.[\d\.]+)/i // iCab
685
674
  ], [NAME, VERSION], [
686
675
 
687
676
  /rv\:([\w\.]{1,9})\b.+(gecko)/i // Gecko
@@ -691,81 +680,79 @@
691
680
  os : [[
692
681
 
693
682
  // Windows
694
- /microsoft\s(windows)\s(vista|xp)/i // Windows (iTunes)
683
+ /microsoft (windows) (vista|xp)/i // Windows (iTunes)
695
684
  ], [NAME, VERSION], [
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]], [
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]], [
702
691
 
703
692
  // iOS/macOS
704
- /ip[honead]{2,4}\b(?:.*os\s([\w]+)\slike\smac|;\sopera)/i, // iOS
693
+ /ip[honead]{2,4}\b(?:.*os ([\w]+) like mac|; opera)/i, // iOS
705
694
  /cfnetwork\/.+darwin/i
706
695
  ], [[VERSION, /_/g, '.'], [NAME, 'iOS']], [
707
- /(mac\sos\sx)\s?([\w\s\.]*)/i,
708
- /(macintosh|mac(?=_powerpc)\s)(?!.+haiku)/i // Mac OS
696
+ /(mac os x) ?([\w\. ]*)/i,
697
+ /(macintosh|mac_powerpc\b)(?!.+haiku)/i // Mac OS
709
698
  ], [[NAME, 'Mac OS'], [VERSION, /_/g, '.']], [
710
699
 
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,
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,
713
704
  /(blackberry)\w*\/([\w\.]*)/i, // Blackberry
714
- /(tizen|kaios)[\/\s]([\w\.]+)/i, // Tizen/KaiOS
705
+ /(tizen|kaios)[\/ ]([\w\.]+)/i, // Tizen/KaiOS
715
706
  /\((series40);/i // Series 40
716
707
  ], [NAME, VERSION], [
717
708
  /\(bb(10);/i // BlackBerry 10
718
- ], [VERSION, [NAME, 'BlackBerry']], [
719
- /(?:symbian\s?os|symbos|s60(?=;)|series60)[\/\s-]?([\w\.]*)/i // Symbian
709
+ ], [VERSION, [NAME, BLACKBERRY]], [
710
+ /(?:symbian ?os|symbos|s60(?=;)|series60)[-\/ ]?([\w\.]*)/i // Symbian
720
711
  ], [VERSION, [NAME, 'Symbian']], [
721
- /mozilla.+\(mobile;.+gecko.+firefox/i // Firefox OS
722
- ], [[NAME, 'Firefox OS']], [
712
+ /mozilla\/[\d\.]+ \((?:mobile|tablet|tv|mobile; [\w ]+); rv:.+ gecko\/([\w\.]+)/i // Firefox OS
713
+ ], [VERSION, [NAME, FIREFOX+' OS']], [
723
714
  /web0s;.+rt(tv)/i,
724
715
  /\b(?:hp)?wos(?:browser)?\/([\w\.]+)/i // WebOS
725
716
  ], [VERSION, [NAME, 'webOS']], [
726
717
 
727
718
  // Google Chromecast
728
719
  /crkey\/([\d\.]+)/i // Google Chromecast
729
- ], [VERSION, [NAME, 'Chromecast']], [
730
- /(cros)\s[\w]+\s([\w\.]+\w)/i // Chromium OS
720
+ ], [VERSION, [NAME, CHROME+'cast']], [
721
+ /(cros) [\w]+ ([\w\.]+\w)/i // Chromium OS
731
722
  ], [[NAME, 'Chromium OS'], VERSION],[
732
723
 
733
724
  // Console
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], [
725
+ /(nintendo|playstation) ([wids345portablevuch]+)/i, // Nintendo/Playstation
726
+ /(xbox); +xbox ([^\);]+)/i, // Microsoft Xbox (360, One, X, S, Series X, Series S)
750
727
 
751
728
  // Other
752
- /(sunos)\s?([\w\.\d]*)/i // Solaris
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
753
740
  ], [[NAME, 'Solaris'], VERSION], [
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
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
758
745
  ], [NAME, VERSION]
759
746
  ]
760
747
  };
761
748
 
762
-
763
749
  /////////////////
764
750
  // Constructor
765
751
  ////////////////
752
+
766
753
  var UAParser = function (ua, extensions) {
767
754
 
768
- if (typeof ua === 'object') {
755
+ if (typeof ua === OBJ_TYPE) {
769
756
  extensions = ua;
770
757
  ua = undefined;
771
758
  }
@@ -774,33 +761,43 @@
774
761
  return new UAParser(ua, extensions).getResult();
775
762
  }
776
763
 
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;
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;
779
766
 
780
767
  this.getBrowser = function () {
781
- var _browser = { name: undefined, version: undefined };
782
- mapper.rgx.call(_browser, _ua, _rgxmap.browser);
783
- _browser.major = util.major(_browser.version); // deprecated
768
+ var _browser = {};
769
+ _browser[NAME] = undefined;
770
+ _browser[VERSION] = undefined;
771
+ rgxMapper.call(_browser, _ua, _rgxmap.browser);
772
+ _browser.major = majorize(_browser.version);
784
773
  return _browser;
785
774
  };
786
775
  this.getCPU = function () {
787
- var _cpu = { architecture: undefined };
788
- mapper.rgx.call(_cpu, _ua, _rgxmap.cpu);
776
+ var _cpu = {};
777
+ _cpu[ARCHITECTURE] = undefined;
778
+ rgxMapper.call(_cpu, _ua, _rgxmap.cpu);
789
779
  return _cpu;
790
780
  };
791
781
  this.getDevice = function () {
792
- var _device = { vendor: undefined, model: undefined, type: undefined };
793
- mapper.rgx.call(_device, _ua, _rgxmap.device);
782
+ var _device = {};
783
+ _device[VENDOR] = undefined;
784
+ _device[MODEL] = undefined;
785
+ _device[TYPE] = undefined;
786
+ rgxMapper.call(_device, _ua, _rgxmap.device);
794
787
  return _device;
795
788
  };
796
789
  this.getEngine = function () {
797
- var _engine = { name: undefined, version: undefined };
798
- mapper.rgx.call(_engine, _ua, _rgxmap.engine);
790
+ var _engine = {};
791
+ _engine[NAME] = undefined;
792
+ _engine[VERSION] = undefined;
793
+ rgxMapper.call(_engine, _ua, _rgxmap.engine);
799
794
  return _engine;
800
795
  };
801
796
  this.getOS = function () {
802
- var _os = { name: undefined, version: undefined };
803
- mapper.rgx.call(_os, _ua, _rgxmap.os);
797
+ var _os = {};
798
+ _os[NAME] = undefined;
799
+ _os[VERSION] = undefined;
800
+ rgxMapper.call(_os, _ua, _rgxmap.os);
804
801
  return _os;
805
802
  };
806
803
  this.getResult = function () {
@@ -817,7 +814,7 @@
817
814
  return _ua;
818
815
  };
819
816
  this.setUA = function (ua) {
820
- _ua = (typeof ua === STR_TYPE && ua.length > UA_MAX_LENGTH) ? util.trim(ua, UA_MAX_LENGTH) : ua;
817
+ _ua = (typeof ua === STR_TYPE && ua.length > UA_MAX_LENGTH) ? trim(ua, UA_MAX_LENGTH) : ua;
821
818
  return this;
822
819
  };
823
820
  this.setUA(_ua);
@@ -825,39 +822,15 @@
825
822
  };
826
823
 
827
824
  UAParser.VERSION = LIBVERSION;
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
- };
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]);
855
829
 
856
830
  ///////////
857
831
  // Export
858
832
  //////////
859
833
 
860
-
861
834
  // check js environment
862
835
  if (typeof(exports) !== UNDEF_TYPE) {
863
836
  // nodejs env
@@ -867,11 +840,11 @@
867
840
  exports.UAParser = UAParser;
868
841
  } else {
869
842
  // requirejs env (optional)
870
- if (typeof(define) === 'function' && define.amd) {
843
+ if (typeof(define) === FUNC_TYPE && define.amd) {
871
844
  define(function () {
872
845
  return UAParser;
873
846
  });
874
- } else if (typeof window !== 'undefined') {
847
+ } else if (typeof window !== UNDEF_TYPE) {
875
848
  // browser env
876
849
  window.UAParser = UAParser;
877
850
  }
@@ -882,15 +855,15 @@
882
855
  // In AMD env the global scope should be kept clean, but jQuery is an exception.
883
856
  // jQuery always exports to global scope, unless jQuery.noConflict(true) is used,
884
857
  // and we should catch that.
885
- var $ = typeof window !== 'undefined' && (window.jQuery || window.Zepto);
858
+ var $ = typeof window !== UNDEF_TYPE && (window.jQuery || window.Zepto);
886
859
  if ($ && !$.ua) {
887
860
  var parser = new UAParser();
888
861
  $.ua = parser.getResult();
889
862
  $.ua.get = function () {
890
863
  return parser.getUA();
891
864
  };
892
- $.ua.set = function (uastring) {
893
- parser.setUA(uastring);
865
+ $.ua.set = function (ua) {
866
+ parser.setUA(ua);
894
867
  var result = parser.getResult();
895
868
  for (var prop in result) {
896
869
  $.ua[prop] = result[prop];