ua-parser-js 0.7.30 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

package/src/ua-parser.js CHANGED
@@ -1,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];