ua-parser-js 0.7.17 → 1.0.2

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