ua-parser-js 0.7.30 → 0.8.0

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

Potentially problematic release.


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

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