ua-parser-js 0.7.28 → 0.7.30

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

Potentially problematic release.


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

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