@naturalcycles/js-lib 15.84.1 → 15.86.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/decorators/index.d.ts +2 -2
- package/dist/decorators/index.js +2 -2
- package/dist/decorators/{memoFn.d.ts → memoized.d.ts} +1 -3
- package/dist/decorators/{memoFn.js → memoized.js} +1 -3
- package/dist/decorators/{memoFnAsync.d.ts → memoizedAsync.d.ts} +1 -4
- package/dist/decorators/{memoFnAsync.js → memoizedAsync.js} +1 -4
- package/dist/ua/ua.d.ts +113 -0
- package/dist/ua/ua.js +1297 -0
- package/package.json +3 -2
- package/src/decorators/index.ts +2 -2
- package/src/decorators/{memoFn.ts → memoized.ts} +1 -3
- package/src/decorators/{memoFnAsync.ts → memoizedAsync.ts} +1 -4
- package/src/ua/ua.ts +1473 -0
package/dist/ua/ua.js
ADDED
|
@@ -0,0 +1,1297 @@
|
|
|
1
|
+
// Vendored & modernized from https://github.com/mcollina/my-ua-parser (v2.0.4, commit 0ff5baa),
|
|
2
|
+
// which is an MIT fork of https://github.com/faisalman/ua-parser-js
|
|
3
|
+
// Copyright © 2024 Matteo Collina <hello@matteocollina.com>
|
|
4
|
+
// Copyright © 2012-2025 Faisal Salman <f@faisalman.com>
|
|
5
|
+
// MIT license.
|
|
6
|
+
//
|
|
7
|
+
// Regex data refreshed from ua-parser-js v1.0.41 (`1.0.x` branch, 2025-08-19), which stayed
|
|
8
|
+
// MIT-licensed. Nothing is taken from ua-parser-js v2.x, which is AGPL-3.0-licensed.
|
|
9
|
+
//
|
|
10
|
+
// Detects Browser, Engine, OS, CPU and Device type/model from a User-Agent string.
|
|
11
|
+
// Supports browser & Node.js environments.
|
|
12
|
+
/// <reference lib="dom" preserve="true" />
|
|
13
|
+
/**
|
|
14
|
+
* Parses the given User-Agent string into browser, engine, os, device and cpu information.
|
|
15
|
+
*
|
|
16
|
+
* When `ua` is not provided and running in a browser - `navigator.userAgent` is used
|
|
17
|
+
* (with client-hints-based refinements, e.g. Brave and iPadOS detection).
|
|
18
|
+
*/
|
|
19
|
+
export function parseUserAgent(userAgent, extensions) {
|
|
20
|
+
return new UAParser(userAgent, extensions).getResult();
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* User-Agent parser.
|
|
24
|
+
*
|
|
25
|
+
* Compared to `parseUserAgent()`, the class allows parsing only the needed parts
|
|
26
|
+
* (e.g `getBrowser()` alone is much cheaper than `getResult()`),
|
|
27
|
+
* and reusing the compiled extensions across multiple `setUA()` calls.
|
|
28
|
+
*/
|
|
29
|
+
export class UAParser {
|
|
30
|
+
constructor(ua, extensions) {
|
|
31
|
+
if (typeof ua === 'object' && ua !== null) {
|
|
32
|
+
extensions = ua;
|
|
33
|
+
ua = undefined;
|
|
34
|
+
}
|
|
35
|
+
this.nav = typeof globalThis.window !== 'undefined' ? globalThis.navigator : undefined;
|
|
36
|
+
this.rgxMap = extensions ? extend(regexes, extensions) : regexes;
|
|
37
|
+
const initialUa = ua || this.nav?.userAgent || '';
|
|
38
|
+
// Whether we're parsing the environment's own UA - only then the
|
|
39
|
+
// navigator-based refinements (Brave, client hints, iPadOS) apply
|
|
40
|
+
this.isSelfNav = !!this.nav && this.nav.userAgent === initialUa;
|
|
41
|
+
this.setUA(initialUa);
|
|
42
|
+
}
|
|
43
|
+
ua = '';
|
|
44
|
+
nav;
|
|
45
|
+
rgxMap;
|
|
46
|
+
isSelfNav;
|
|
47
|
+
getBrowser() {
|
|
48
|
+
const browser = { name: undefined, version: undefined, major: undefined };
|
|
49
|
+
rgxMapper(browser, this.ua, this.rgxMap.browser);
|
|
50
|
+
browser.major = majorize(browser.version);
|
|
51
|
+
// Brave-specific detection
|
|
52
|
+
if (this.isSelfNav && typeof this.nav?.brave?.isBrave === 'function') {
|
|
53
|
+
browser.name = 'Brave';
|
|
54
|
+
}
|
|
55
|
+
return browser;
|
|
56
|
+
}
|
|
57
|
+
getCPU() {
|
|
58
|
+
const cpu = { architecture: undefined };
|
|
59
|
+
rgxMapper(cpu, this.ua, this.rgxMap.cpu);
|
|
60
|
+
return cpu;
|
|
61
|
+
}
|
|
62
|
+
getDevice() {
|
|
63
|
+
const device = { vendor: undefined, model: undefined, type: undefined };
|
|
64
|
+
rgxMapper(device, this.ua, this.rgxMap.device);
|
|
65
|
+
if (this.isSelfNav && !device.type && this.nav?.userAgentData?.mobile) {
|
|
66
|
+
device.type = MOBILE;
|
|
67
|
+
}
|
|
68
|
+
// iPadOS-specific detection: identified as Mac, but has some iOS-only properties
|
|
69
|
+
if (this.isSelfNav &&
|
|
70
|
+
device.model === 'Macintosh' &&
|
|
71
|
+
typeof this.nav?.standalone !== 'undefined' &&
|
|
72
|
+
this.nav.maxTouchPoints > 2) {
|
|
73
|
+
device.model = 'iPad';
|
|
74
|
+
device.type = TABLET;
|
|
75
|
+
}
|
|
76
|
+
return device;
|
|
77
|
+
}
|
|
78
|
+
getEngine() {
|
|
79
|
+
const engine = { name: undefined, version: undefined };
|
|
80
|
+
rgxMapper(engine, this.ua, this.rgxMap.engine);
|
|
81
|
+
return engine;
|
|
82
|
+
}
|
|
83
|
+
getOS() {
|
|
84
|
+
const os = { name: undefined, version: undefined };
|
|
85
|
+
rgxMapper(os, this.ua, this.rgxMap.os);
|
|
86
|
+
const platform = this.nav?.userAgentData?.platform;
|
|
87
|
+
if (this.isSelfNav && !os.name && platform && platform !== 'Unknown') {
|
|
88
|
+
os.name = platform.replace(/chrome os/i, CHROMIUM_OS).replace(/macos/i, MAC_OS); // backward compatibility
|
|
89
|
+
}
|
|
90
|
+
return os;
|
|
91
|
+
}
|
|
92
|
+
getResult() {
|
|
93
|
+
return {
|
|
94
|
+
ua: this.getUA(),
|
|
95
|
+
browser: this.getBrowser(),
|
|
96
|
+
engine: this.getEngine(),
|
|
97
|
+
os: this.getOS(),
|
|
98
|
+
device: this.getDevice(),
|
|
99
|
+
cpu: this.getCPU(),
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
getUA() {
|
|
103
|
+
return this.ua;
|
|
104
|
+
}
|
|
105
|
+
setUA(ua) {
|
|
106
|
+
ua ||= '';
|
|
107
|
+
this.ua = ua.length > UA_MAX_LENGTH ? ua.replace(/^\s\s*/, '').slice(0, UA_MAX_LENGTH) : ua;
|
|
108
|
+
return this;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
///////////
|
|
112
|
+
// Helpers
|
|
113
|
+
//////////
|
|
114
|
+
function extend(defaults, extensions) {
|
|
115
|
+
return {
|
|
116
|
+
browser: mergeMapEntries(defaults.browser, extensions.browser),
|
|
117
|
+
cpu: mergeMapEntries(defaults.cpu, extensions.cpu),
|
|
118
|
+
device: mergeMapEntries(defaults.device, extensions.device),
|
|
119
|
+
engine: mergeMapEntries(defaults.engine, extensions.engine),
|
|
120
|
+
os: mergeMapEntries(defaults.os, extensions.os),
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
function mergeMapEntries(defaults, extension) {
|
|
124
|
+
// extension must be a valid alternating [regexes, actions, ...] sequence, otherwise ignored
|
|
125
|
+
return extension?.length && extension.length % 2 === 0 ? extension.concat(defaults) : defaults;
|
|
126
|
+
}
|
|
127
|
+
function rgxMapper(target, ua, arrays) {
|
|
128
|
+
const t = target;
|
|
129
|
+
let matches = null;
|
|
130
|
+
// loop through all regexes maps
|
|
131
|
+
for (let i = 0; i < arrays.length && !matches; i += 2) {
|
|
132
|
+
const regexList = arrays[i]; // even sequence (0,2,4,..)
|
|
133
|
+
const actions = arrays[i + 1]; // odd sequence (1,3,5,..)
|
|
134
|
+
let k = 0;
|
|
135
|
+
// try matching uastring with regexes
|
|
136
|
+
for (let j = 0; j < regexList.length && !matches; j++) {
|
|
137
|
+
const regex = regexList[j];
|
|
138
|
+
if (!regex)
|
|
139
|
+
break;
|
|
140
|
+
matches = regex.exec(ua);
|
|
141
|
+
if (matches) {
|
|
142
|
+
for (const q of actions) {
|
|
143
|
+
const match = matches[++k];
|
|
144
|
+
if (typeof q === 'string') {
|
|
145
|
+
// assign the raw match
|
|
146
|
+
t[q] = match || undefined;
|
|
147
|
+
}
|
|
148
|
+
else if (q.length === 2) {
|
|
149
|
+
if (typeof q[1] === 'function') {
|
|
150
|
+
// assign modified match
|
|
151
|
+
t[q[0]] = match === undefined ? undefined : q[1](match);
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
// assign given value, ignore regex match
|
|
155
|
+
t[q[0]] = q[1];
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
else if (q.length === 3) {
|
|
159
|
+
if (typeof q[1] === 'function') {
|
|
160
|
+
// call function (usually string mapper)
|
|
161
|
+
// typeof check on q[1] doesn't discriminate the tuple union, hence the cast
|
|
162
|
+
const [prop, fn, map] = q;
|
|
163
|
+
t[prop] = match ? fn(match, map) : undefined;
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
// sanitize match using given regex
|
|
167
|
+
const [prop, rgx, replacement] = q;
|
|
168
|
+
t[prop] = match ? match.replace(rgx, replacement) : undefined;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
else if (q.length === 4) {
|
|
172
|
+
t[q[0]] = match ? q[3](match.replace(q[1], q[2])) : undefined;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
function strMapper(str, map) {
|
|
180
|
+
for (const key of Object.keys(map)) {
|
|
181
|
+
const value = map[key];
|
|
182
|
+
// check if current value is array
|
|
183
|
+
if (Array.isArray(value)) {
|
|
184
|
+
for (const v of value) {
|
|
185
|
+
if (has(v, str)) {
|
|
186
|
+
return key === UNKNOWN ? undefined : key;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
else if (has(value, str)) {
|
|
191
|
+
return key === UNKNOWN ? undefined : key;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
// '*' is a catch-all fallback value (always a string in the built-in maps)
|
|
195
|
+
const fallback = map['*'];
|
|
196
|
+
return typeof fallback === 'string' ? fallback : str;
|
|
197
|
+
}
|
|
198
|
+
function majorize(version) {
|
|
199
|
+
return typeof version === 'string' ? version.replaceAll(/[^\d\.]/g, '').split('.')[0] : undefined;
|
|
200
|
+
}
|
|
201
|
+
function has(str1, str2) {
|
|
202
|
+
return lowerize(str2).includes(lowerize(str1));
|
|
203
|
+
}
|
|
204
|
+
function lowerize(str) {
|
|
205
|
+
return str.toLowerCase();
|
|
206
|
+
}
|
|
207
|
+
function trimStr(str) {
|
|
208
|
+
return str.replace(/^\s\s*/, '');
|
|
209
|
+
}
|
|
210
|
+
//////////////
|
|
211
|
+
// Constants
|
|
212
|
+
/////////////
|
|
213
|
+
const UNKNOWN = '?';
|
|
214
|
+
const UA_MAX_LENGTH = 500;
|
|
215
|
+
const MODEL = 'model';
|
|
216
|
+
const NAME = 'name';
|
|
217
|
+
const TYPE = 'type';
|
|
218
|
+
const VENDOR = 'vendor';
|
|
219
|
+
const VERSION = 'version';
|
|
220
|
+
const ARCHITECTURE = 'architecture';
|
|
221
|
+
const CONSOLE = 'console';
|
|
222
|
+
const MOBILE = 'mobile';
|
|
223
|
+
const TABLET = 'tablet';
|
|
224
|
+
const SMARTTV = 'smarttv';
|
|
225
|
+
const WEARABLE = 'wearable';
|
|
226
|
+
const EMBEDDED = 'embedded';
|
|
227
|
+
const AMAZON = 'Amazon';
|
|
228
|
+
const APPLE = 'Apple';
|
|
229
|
+
const ASUS = 'ASUS';
|
|
230
|
+
const BLACKBERRY = 'BlackBerry';
|
|
231
|
+
const BROWSER = 'Browser';
|
|
232
|
+
const SUFFIX_BROWSER = ' Browser';
|
|
233
|
+
const CHROME = 'Chrome';
|
|
234
|
+
const EDGE = 'Edge';
|
|
235
|
+
const FIREFOX = 'Firefox';
|
|
236
|
+
const GOOGLE = 'Google';
|
|
237
|
+
const HONOR = 'Honor';
|
|
238
|
+
const HUAWEI = 'Huawei';
|
|
239
|
+
const LENOVO = 'Lenovo';
|
|
240
|
+
const LG = 'LG';
|
|
241
|
+
const MICROSOFT = 'Microsoft';
|
|
242
|
+
const MOTOROLA = 'Motorola';
|
|
243
|
+
const NVIDIA = 'Nvidia';
|
|
244
|
+
const ONEPLUS = 'OnePlus';
|
|
245
|
+
const OPERA = 'Opera';
|
|
246
|
+
const OPPO = 'OPPO';
|
|
247
|
+
const SAMSUNG = 'Samsung';
|
|
248
|
+
const SHARP = 'Sharp';
|
|
249
|
+
const SONY = 'Sony';
|
|
250
|
+
const XIAOMI = 'Xiaomi';
|
|
251
|
+
const ZEBRA = 'Zebra';
|
|
252
|
+
const FACEBOOK = 'Facebook';
|
|
253
|
+
const CHROMIUM_OS = 'Chromium OS';
|
|
254
|
+
const MAC_OS = 'Mac OS';
|
|
255
|
+
///////////////
|
|
256
|
+
// String maps
|
|
257
|
+
//////////////
|
|
258
|
+
// Safari < 3.0
|
|
259
|
+
const oldSafariMap = {
|
|
260
|
+
'1.0': '/8',
|
|
261
|
+
'1.2': '/1',
|
|
262
|
+
'1.3': '/3',
|
|
263
|
+
'2.0': '/412',
|
|
264
|
+
'2.0.2': '/416',
|
|
265
|
+
'2.0.3': '/417',
|
|
266
|
+
'2.0.4': '/419',
|
|
267
|
+
'?': '/',
|
|
268
|
+
};
|
|
269
|
+
const windowsVersionMap = {
|
|
270
|
+
ME: '4.90',
|
|
271
|
+
'NT 3.11': 'NT3.51',
|
|
272
|
+
'NT 4.0': 'NT4.0',
|
|
273
|
+
2000: 'NT 5.0',
|
|
274
|
+
XP: ['NT 5.1', 'NT 5.2'],
|
|
275
|
+
Vista: 'NT 6.0',
|
|
276
|
+
7: 'NT 6.1',
|
|
277
|
+
8: 'NT 6.2',
|
|
278
|
+
8.1: 'NT 6.3',
|
|
279
|
+
10: ['NT 6.4', 'NT 10.0'],
|
|
280
|
+
RT: 'ARM',
|
|
281
|
+
};
|
|
282
|
+
//////////////
|
|
283
|
+
// Regex map
|
|
284
|
+
/////////////
|
|
285
|
+
// The regexes below are preserved verbatim from upstream ua-parser-js 1.0.41 (MIT) -
|
|
286
|
+
// do not "fix" escapes or simplify them, to keep them diffable against upstream.
|
|
287
|
+
const regexes = {
|
|
288
|
+
browser: [
|
|
289
|
+
[
|
|
290
|
+
/\b(?:crmo|crios)\/([\w\.]+)/i, // Chrome for Android/iOS
|
|
291
|
+
],
|
|
292
|
+
[VERSION, [NAME, 'Chrome']],
|
|
293
|
+
[
|
|
294
|
+
/edg(?:e|ios|a)?\/([\w\.]+)/i, // Microsoft Edge
|
|
295
|
+
],
|
|
296
|
+
[VERSION, [NAME, 'Edge']],
|
|
297
|
+
[
|
|
298
|
+
// Presto based
|
|
299
|
+
/(opera mini)\/([-\w\.]+)/i, // Opera Mini
|
|
300
|
+
/(opera [mobiletab]{3,6})\b.+version\/([-\w\.]+)/i, // Opera Mobi/Tablet
|
|
301
|
+
/(opera)(?:.+version\/|[\/ ]+)([\w\.]+)/i, // Opera
|
|
302
|
+
],
|
|
303
|
+
[NAME, VERSION],
|
|
304
|
+
[
|
|
305
|
+
/opios[\/ ]+([\w\.]+)/i, // Opera mini on iphone >= 8.0
|
|
306
|
+
],
|
|
307
|
+
[VERSION, [NAME, OPERA + ' Mini']],
|
|
308
|
+
[
|
|
309
|
+
/\bop(?:rg)?x\/([\w\.]+)/i, // Opera GX
|
|
310
|
+
],
|
|
311
|
+
[VERSION, [NAME, OPERA + ' GX']],
|
|
312
|
+
[
|
|
313
|
+
/\bopr\/([\w\.]+)/i, // Opera Webkit
|
|
314
|
+
],
|
|
315
|
+
[VERSION, [NAME, OPERA]],
|
|
316
|
+
[
|
|
317
|
+
// Mixed
|
|
318
|
+
/\bb[ai]*d(?:uhd|[ub]*[aekoprswx]{5,6})[\/ ]?([\w\.]+)/i, // Baidu
|
|
319
|
+
],
|
|
320
|
+
[VERSION, [NAME, 'Baidu']],
|
|
321
|
+
[
|
|
322
|
+
/\b(?:mxbrowser|mxios|myie2)\/?([-\w\.]*)\b/i, // Maxthon
|
|
323
|
+
],
|
|
324
|
+
[VERSION, [NAME, 'Maxthon']],
|
|
325
|
+
[
|
|
326
|
+
/(kindle)\/([\w\.]+)/i, // Kindle
|
|
327
|
+
/(lunascape|maxthon|netfront|jasmine|blazer|sleipnir)[\/ ]?([\w\.]*)/i,
|
|
328
|
+
// Lunascape/Maxthon/Netfront/Jasmine/Blazer/Sleipnir
|
|
329
|
+
// Trident based
|
|
330
|
+
/(avant|iemobile|slim(?:browser|boat|jet))[\/ ]?([\d\.]*)/i, // Avant/IEMobile/SlimBrowser/SlimBoat/Slimjet
|
|
331
|
+
/(?:ms|\()(ie) ([\w\.]+)/i, // Internet Explorer
|
|
332
|
+
// Blink/Webkit/KHTML based // Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS/Bowser/QupZilla/Falkon
|
|
333
|
+
/(flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi|iridium|phantomjs|bowser|qupzilla|falkon|rekonq|puffin|brave|whale(?!.+naver)|qqbrowserlite|duckduckgo|klar|helio|(?=comodo_)?dragon)\/([-\w\.]+)/i,
|
|
334
|
+
// Rekonq/Puffin/Brave/Whale/QQBrowserLite/QQ//Vivaldi/DuckDuckGo/Klar/Helio/Dragon
|
|
335
|
+
/(heytap|ovi|115)browser\/([\d\.]+)/i, // HeyTap/Ovi/115
|
|
336
|
+
/(weibo)__([\d\.]+)/i, // Weibo
|
|
337
|
+
],
|
|
338
|
+
[NAME, VERSION],
|
|
339
|
+
[
|
|
340
|
+
/quark(?:pc)?\/([-\w\.]+)/i, // Quark
|
|
341
|
+
],
|
|
342
|
+
[VERSION, [NAME, 'Quark']],
|
|
343
|
+
[
|
|
344
|
+
/\bddg\/([\w\.]+)/i, // DuckDuckGo
|
|
345
|
+
],
|
|
346
|
+
[VERSION, [NAME, 'DuckDuckGo']],
|
|
347
|
+
[
|
|
348
|
+
/(?:\buc? ?browser|(?:juc.+)ucweb)[\/ ]?([\w\.]+)/i, // UCBrowser
|
|
349
|
+
],
|
|
350
|
+
[VERSION, [NAME, 'UC' + BROWSER]],
|
|
351
|
+
[
|
|
352
|
+
/microm.+\bqbcore\/([\w\.]+)/i, // WeChat Desktop for Windows Built-in Browser
|
|
353
|
+
/\bqbcore\/([\w\.]+).+microm/i,
|
|
354
|
+
/micromessenger\/([\w\.]+)/i, // WeChat
|
|
355
|
+
],
|
|
356
|
+
[VERSION, [NAME, 'WeChat']],
|
|
357
|
+
[
|
|
358
|
+
/konqueror\/([\w\.]+)/i, // Konqueror
|
|
359
|
+
],
|
|
360
|
+
[VERSION, [NAME, 'Konqueror']],
|
|
361
|
+
[
|
|
362
|
+
/trident.+rv[: ]([\w\.]{1,9})\b.+like gecko/i, // IE11
|
|
363
|
+
],
|
|
364
|
+
[VERSION, [NAME, 'IE']],
|
|
365
|
+
[
|
|
366
|
+
/ya(?:search)?browser\/([\w\.]+)/i, // Yandex
|
|
367
|
+
],
|
|
368
|
+
[VERSION, [NAME, 'Yandex']],
|
|
369
|
+
[
|
|
370
|
+
/slbrowser\/([\w\.]+)/i, // Smart Lenovo Browser
|
|
371
|
+
],
|
|
372
|
+
[VERSION, [NAME, 'Smart Lenovo ' + BROWSER]],
|
|
373
|
+
[
|
|
374
|
+
/(avast|avg)\/([\w\.]+)/i, // Avast/AVG Secure Browser
|
|
375
|
+
],
|
|
376
|
+
[[NAME, /(.+)/, '$1 Secure ' + BROWSER], VERSION],
|
|
377
|
+
[
|
|
378
|
+
/\bfocus\/([\w\.]+)/i, // Firefox Focus
|
|
379
|
+
],
|
|
380
|
+
[VERSION, [NAME, FIREFOX + ' Focus']],
|
|
381
|
+
[
|
|
382
|
+
/\bopt\/([\w\.]+)/i, // Opera Touch
|
|
383
|
+
],
|
|
384
|
+
[VERSION, [NAME, OPERA + ' Touch']],
|
|
385
|
+
[
|
|
386
|
+
/coc_coc\w+\/([\w\.]+)/i, // Coc Coc Browser
|
|
387
|
+
],
|
|
388
|
+
[VERSION, [NAME, 'Coc Coc']],
|
|
389
|
+
[
|
|
390
|
+
/dolfin\/([\w\.]+)/i, // Dolphin
|
|
391
|
+
],
|
|
392
|
+
[VERSION, [NAME, 'Dolphin']],
|
|
393
|
+
[
|
|
394
|
+
/coast\/([\w\.]+)/i, // Opera Coast
|
|
395
|
+
],
|
|
396
|
+
[VERSION, [NAME, OPERA + ' Coast']],
|
|
397
|
+
[
|
|
398
|
+
/miuibrowser\/([\w\.]+)/i, // MIUI Browser
|
|
399
|
+
],
|
|
400
|
+
[VERSION, [NAME, 'MIUI' + SUFFIX_BROWSER]],
|
|
401
|
+
[
|
|
402
|
+
/fxios\/([\w\.-]+)/i, // Firefox for iOS
|
|
403
|
+
],
|
|
404
|
+
[VERSION, [NAME, FIREFOX]],
|
|
405
|
+
[
|
|
406
|
+
/\bqihoobrowser\/?([\w\.]*)/i, // 360
|
|
407
|
+
],
|
|
408
|
+
[VERSION, [NAME, '360']],
|
|
409
|
+
[
|
|
410
|
+
/\b(qq)\/([\w\.]+)/i, // QQ
|
|
411
|
+
],
|
|
412
|
+
[[NAME, /(.+)/, '$1Browser'], VERSION],
|
|
413
|
+
[/(oculus|sailfish|huawei|vivo|pico)browser\/([\w\.]+)/i],
|
|
414
|
+
[[NAME, /(.+)/, '$1' + SUFFIX_BROWSER], VERSION], // Oculus/Sailfish/HuaweiBrowser/VivoBrowser/PicoBrowser
|
|
415
|
+
[
|
|
416
|
+
/samsungbrowser\/([\w\.]+)/i, // Samsung Internet
|
|
417
|
+
],
|
|
418
|
+
[VERSION, [NAME, SAMSUNG + ' Internet']],
|
|
419
|
+
[
|
|
420
|
+
/metasr[\/ ]?([\d\.]+)/i, // Sogou Explorer
|
|
421
|
+
],
|
|
422
|
+
[VERSION, [NAME, 'Sogou Explorer']],
|
|
423
|
+
[
|
|
424
|
+
/(sogou)mo\w+\/([\d\.]+)/i, // Sogou Mobile
|
|
425
|
+
],
|
|
426
|
+
[[NAME, 'Sogou Mobile'], VERSION],
|
|
427
|
+
[
|
|
428
|
+
/(electron)\/([\w\.]+) safari/i, // Electron-based App
|
|
429
|
+
/(tesla)(?: qtcarbrowser|\/(20\d\d\.[-\w\.]+))/i, // Tesla
|
|
430
|
+
/m?(qqbrowser|2345(?=browser|chrome|explorer))\w*[\/ ]?v?([\w\.]+)/i, // QQ/2345
|
|
431
|
+
],
|
|
432
|
+
[NAME, VERSION],
|
|
433
|
+
[
|
|
434
|
+
/(lbbrowser|rekonq)/i, // LieBao Browser/Rekonq
|
|
435
|
+
/\[(linkedin)app\]/i, // LinkedIn App for iOS & Android
|
|
436
|
+
],
|
|
437
|
+
[NAME],
|
|
438
|
+
[
|
|
439
|
+
/ome\/([\w\.]+) \w* ?(iron) saf/i, // Iron
|
|
440
|
+
/ome\/([\w\.]+).+qihu (360)[es]e/i, // 360
|
|
441
|
+
],
|
|
442
|
+
[VERSION, NAME],
|
|
443
|
+
[
|
|
444
|
+
// WebView
|
|
445
|
+
/((?:fban\/fbios|fb_iab\/fb4a)(?!.+fbav)|;fbav\/([\w\.]+);)/i, // Facebook App for iOS & Android
|
|
446
|
+
],
|
|
447
|
+
[[NAME, FACEBOOK], VERSION],
|
|
448
|
+
[
|
|
449
|
+
/(Klarna)\/([\w\.]+)/i, // Klarna Shopping Browser for iOS & Android
|
|
450
|
+
/(kakao(?:talk|story))[\/ ]([\w\.]+)/i, // Kakao App
|
|
451
|
+
/(naver)\(.*?(\d+\.[\w\.]+).*\)/i, // Naver InApp
|
|
452
|
+
/(daum)apps[\/ ]([\w\.]+)/i, // Daum App
|
|
453
|
+
/safari (line)\/([\w\.]+)/i, // Line App for iOS
|
|
454
|
+
/\b(line)\/([\w\.]+)\/iab/i, // Line App for Android
|
|
455
|
+
/(alipay)client\/([\w\.]+)/i, // Alipay
|
|
456
|
+
/(twitter)(?:and| f.+e\/([\w\.]+))/i, // Twitter
|
|
457
|
+
/(chromium|instagram|snapchat)[\/ ]([-\w\.]+)/i, // Chromium/Instagram/Snapchat
|
|
458
|
+
],
|
|
459
|
+
[NAME, VERSION],
|
|
460
|
+
[
|
|
461
|
+
/\bgsa\/([\w\.]+) .*safari\//i, // Google Search Appliance on iOS
|
|
462
|
+
],
|
|
463
|
+
[VERSION, [NAME, 'GSA']],
|
|
464
|
+
[
|
|
465
|
+
/musical_ly(?:.+app_?version\/|_)([\w\.]+)/i, // TikTok
|
|
466
|
+
],
|
|
467
|
+
[VERSION, [NAME, 'TikTok']],
|
|
468
|
+
[
|
|
469
|
+
/headlesschrome(?:\/([\w\.]+)| )/i, // Chrome Headless
|
|
470
|
+
],
|
|
471
|
+
[VERSION, [NAME, CHROME + ' Headless']],
|
|
472
|
+
[
|
|
473
|
+
/ wv\).+(chrome)\/([\w\.]+)/i, // Chrome WebView
|
|
474
|
+
],
|
|
475
|
+
[[NAME, CHROME + ' WebView'], VERSION],
|
|
476
|
+
[
|
|
477
|
+
/droid.+ version\/([\w\.]+)\b.+(?:mobile safari|safari)/i, // Android Browser
|
|
478
|
+
],
|
|
479
|
+
[VERSION, [NAME, 'Android ' + BROWSER]],
|
|
480
|
+
[
|
|
481
|
+
/(chrome|omniweb|arora|[tizenoka]{5} ?browser)\/v?([\w\.]+)/i, // Chrome/OmniWeb/Arora/Tizen/Nokia
|
|
482
|
+
],
|
|
483
|
+
[NAME, VERSION],
|
|
484
|
+
[
|
|
485
|
+
/version\/([\w\.\,]+) .*mobile\/\w+ (safari)/i, // Mobile Safari
|
|
486
|
+
],
|
|
487
|
+
[VERSION, [NAME, 'Mobile Safari']],
|
|
488
|
+
[
|
|
489
|
+
/version\/([\w(\.|\,)]+) .*(mobile ?safari|safari)/i, // Safari & Safari Mobile
|
|
490
|
+
],
|
|
491
|
+
[VERSION, NAME],
|
|
492
|
+
[
|
|
493
|
+
/webkit.+?(mobile ?safari|safari)(\/[\w\.]+)/i, // Safari < 3.0
|
|
494
|
+
],
|
|
495
|
+
[NAME, [VERSION, strMapper, oldSafariMap]],
|
|
496
|
+
[/(webkit|khtml)\/([\w\.]+)/i],
|
|
497
|
+
[NAME, VERSION],
|
|
498
|
+
[
|
|
499
|
+
// Gecko based
|
|
500
|
+
/(navigator|netscape\d?)\/([-\w\.]+)/i, // Netscape
|
|
501
|
+
],
|
|
502
|
+
[[NAME, 'Netscape'], VERSION],
|
|
503
|
+
[
|
|
504
|
+
/(wolvic|librewolf)\/([\w\.]+)/i, // Wolvic/LibreWolf
|
|
505
|
+
],
|
|
506
|
+
[NAME, VERSION],
|
|
507
|
+
[
|
|
508
|
+
/mobile vr; rv:([\w\.]+)\).+firefox/i, // Firefox Reality
|
|
509
|
+
],
|
|
510
|
+
[VERSION, [NAME, FIREFOX + ' Reality']],
|
|
511
|
+
[
|
|
512
|
+
/ekiohf.+(flow)\/([\w\.]+)/i, // Flow
|
|
513
|
+
/(swiftfox)/i, // Swiftfox
|
|
514
|
+
/(icedragon|iceweasel|camino|chimera|fennec|maemo browser|minimo|conkeror)[\/ ]?([\w\.\+]+)/i,
|
|
515
|
+
// IceDragon/Iceweasel/Camino/Chimera/Fennec/Maemo/Minimo/Conkeror
|
|
516
|
+
/(seamonkey|k-meleon|icecat|iceape|firebird|phoenix|palemoon|basilisk|waterfox)\/([-\w\.]+)$/i,
|
|
517
|
+
// Firefox/SeaMonkey/K-Meleon/IceCat/IceApe/Firebird/Phoenix
|
|
518
|
+
/(firefox)\/([\w\.]+)/i, // Other Firefox-based
|
|
519
|
+
/(mozilla)\/([\w\.]+) .+rv\:.+gecko\/\d+/i, // Mozilla
|
|
520
|
+
],
|
|
521
|
+
[NAME, VERSION],
|
|
522
|
+
[
|
|
523
|
+
// Other
|
|
524
|
+
/(amaya|dillo|doris|icab|ladybird|lynx|mosaic|netsurf|obigo|polaris|w3m|(?:go|ice|up)[\. ]?browser)[-\/ ]?v?([\w\.]+)/i,
|
|
525
|
+
// Polaris/Lynx/Dillo/iCab/Doris/Amaya/w3m/NetSurf/Obigo/Mosaic/Go/ICE/UP.Browser/Ladybird
|
|
526
|
+
/\b(links) \(([\w\.]+)/i, // Links
|
|
527
|
+
],
|
|
528
|
+
[NAME, [VERSION, /_/g, '.']],
|
|
529
|
+
[
|
|
530
|
+
/(cobalt)\/([\w\.]+)/i, // Cobalt
|
|
531
|
+
],
|
|
532
|
+
[NAME, [VERSION, /master.|lts./, '']],
|
|
533
|
+
],
|
|
534
|
+
cpu: [
|
|
535
|
+
[
|
|
536
|
+
/\b((amd|x|x86[-_]?|wow|win)64)\b/i, // AMD64 (x64)
|
|
537
|
+
],
|
|
538
|
+
[[ARCHITECTURE, 'amd64']],
|
|
539
|
+
[
|
|
540
|
+
/(ia32(?=;))/i, // IA32 (quicktime)
|
|
541
|
+
/\b((i[346]|x)86)(pc)?\b/i, // IA32 (x86)
|
|
542
|
+
],
|
|
543
|
+
[[ARCHITECTURE, 'ia32']],
|
|
544
|
+
[
|
|
545
|
+
/\b(aarch64|arm(v?[89]e?l?|_?64))\b/i, // ARM64
|
|
546
|
+
],
|
|
547
|
+
[[ARCHITECTURE, 'arm64']],
|
|
548
|
+
[
|
|
549
|
+
/\b(arm(v[67])?ht?n?[fl]p?)\b/i, // ARMHF
|
|
550
|
+
],
|
|
551
|
+
[[ARCHITECTURE, 'armhf']],
|
|
552
|
+
[
|
|
553
|
+
// PocketPC mistakenly identified as PowerPC
|
|
554
|
+
/( (ce|mobile); ppc;|\/[\w\.]+arm\b)/i,
|
|
555
|
+
],
|
|
556
|
+
[[ARCHITECTURE, 'arm']],
|
|
557
|
+
[
|
|
558
|
+
/((ppc|powerpc)(64)?)( mac|;|\))/i, // PowerPC
|
|
559
|
+
],
|
|
560
|
+
[[ARCHITECTURE, /ower/, '', lowerize]],
|
|
561
|
+
[
|
|
562
|
+
/ sun4\w[;\)]/i, // SPARC
|
|
563
|
+
],
|
|
564
|
+
[[ARCHITECTURE, 'sparc']],
|
|
565
|
+
[
|
|
566
|
+
/\b(avr32|ia64(?=;)|68k(?=\))|\barm(?=v([1-7]|[5-7]1)l?|;|eabi)|(irix|mips|sparc)(64)?\b|pa-risc)/i,
|
|
567
|
+
// IA64, 68K, ARM/64, AVR/32, IRIX/64, MIPS/64, SPARC/64, PA-RISC
|
|
568
|
+
],
|
|
569
|
+
[[ARCHITECTURE, lowerize]],
|
|
570
|
+
],
|
|
571
|
+
device: [
|
|
572
|
+
[
|
|
573
|
+
//////////////////////////
|
|
574
|
+
// MOBILES & TABLETS
|
|
575
|
+
/////////////////////////
|
|
576
|
+
// Samsung
|
|
577
|
+
/\b(sch-i[89]0\d|shw-m380s|sm-[ptx]\w{2,4}|gt-[pn]\d{2,4}|sgh-t8[56]9|nexus 10)/i,
|
|
578
|
+
],
|
|
579
|
+
[MODEL, [VENDOR, SAMSUNG], [TYPE, TABLET]],
|
|
580
|
+
[
|
|
581
|
+
/\b((?:s[cgp]h|gt|sm)-(?![lr])\w+|sc[g-]?[\d]+a?|galaxy nexus)/i,
|
|
582
|
+
/samsung[- ]((?!sm-[lr])[-\w]+)/i,
|
|
583
|
+
/sec-(sgh\w+)/i,
|
|
584
|
+
],
|
|
585
|
+
[MODEL, [VENDOR, SAMSUNG], [TYPE, MOBILE]],
|
|
586
|
+
[
|
|
587
|
+
// Apple
|
|
588
|
+
/(?:\/|\()(ip(?:hone|od)[\w, ]*)(?:\/|;)/i, // iPod/iPhone
|
|
589
|
+
],
|
|
590
|
+
[MODEL, [VENDOR, APPLE], [TYPE, MOBILE]],
|
|
591
|
+
[
|
|
592
|
+
/\((ipad);[-\w\),; ]+apple/i, // iPad
|
|
593
|
+
/applecoremedia\/[\w\.]+ \((ipad)/i,
|
|
594
|
+
/\b(ipad)\d\d?,\d\d?[;\]].+ios/i,
|
|
595
|
+
],
|
|
596
|
+
[MODEL, [VENDOR, APPLE], [TYPE, TABLET]],
|
|
597
|
+
[/(macintosh);/i],
|
|
598
|
+
[MODEL, [VENDOR, APPLE]],
|
|
599
|
+
[
|
|
600
|
+
// Sharp
|
|
601
|
+
/\b(sh-?[altvz]?\d\d[a-ekm]?)/i,
|
|
602
|
+
],
|
|
603
|
+
[MODEL, [VENDOR, SHARP], [TYPE, MOBILE]],
|
|
604
|
+
[
|
|
605
|
+
// Honor
|
|
606
|
+
/\b((?:brt|eln|hey2?|gdi|jdn)-a?[lnw]09|(?:ag[rm]3?|jdn2|kob2)-a?[lw]0[09]hn)(?: bui|\)|;)/i,
|
|
607
|
+
],
|
|
608
|
+
[MODEL, [VENDOR, HONOR], [TYPE, TABLET]],
|
|
609
|
+
[/honor([-\w ]+)[;\)]/i],
|
|
610
|
+
[MODEL, [VENDOR, HONOR], [TYPE, MOBILE]],
|
|
611
|
+
[
|
|
612
|
+
// Huawei
|
|
613
|
+
/\b((?:ag[rs][2356]?k?|bah[234]?|bg[2o]|bt[kv]|cmr|cpn|db[ry]2?|jdn2|got|kob2?k?|mon|pce|scm|sht?|[tw]gr|vrd)-[ad]?[lw][0125][09]b?|605hw|bg2-u03|(?:gem|fdr|m2|ple|t1)-[7a]0[1-4][lu]|t1-a2[13][lw]|mediapad[\w\. ]*(?= bui|\)))\b(?!.+d\/s)/i,
|
|
614
|
+
],
|
|
615
|
+
[MODEL, [VENDOR, HUAWEI], [TYPE, TABLET]],
|
|
616
|
+
[
|
|
617
|
+
/(?:huawei)([-\w ]+)[;\)]/i,
|
|
618
|
+
/\b(nexus 6p|\w{2,4}e?-[atu]?[ln][\dx][012359c][adn]?)\b(?!.+d\/s)/i,
|
|
619
|
+
],
|
|
620
|
+
[MODEL, [VENDOR, HUAWEI], [TYPE, MOBILE]],
|
|
621
|
+
[
|
|
622
|
+
// Xiaomi
|
|
623
|
+
/oid[^\)]+; (2[\dbc]{4}(182|283|rp\w{2})[cgl]|m2105k81a?c)(?: bui|\))/i,
|
|
624
|
+
/\b((?:red)?mi[-_ ]?pad[\w- ]*)(?: bui|\))/i, // Mi Pad tablets
|
|
625
|
+
],
|
|
626
|
+
[
|
|
627
|
+
[MODEL, /_/g, ' '],
|
|
628
|
+
[VENDOR, XIAOMI],
|
|
629
|
+
[TYPE, TABLET],
|
|
630
|
+
],
|
|
631
|
+
[
|
|
632
|
+
/\b(poco[\w ]+|m2\d{3}j\d\d[a-z]{2})(?: bui|\))/i, // Xiaomi POCO
|
|
633
|
+
/\b; (\w+) build\/hm\1/i, // Xiaomi Hongmi 'numeric' models
|
|
634
|
+
/\b(hm[-_ ]?note?[_ ]?(?:\d\w)?) bui/i, // Xiaomi Hongmi
|
|
635
|
+
/\b(redmi[\-_ ]?(?:note|k)?[\w_ ]+)(?: bui|\))/i, // Xiaomi Redmi
|
|
636
|
+
/oid[^\)]+; (m?[12][0-389][01]\w{3,6}[c-y])( bui|; wv|\))/i, // Xiaomi Redmi 'numeric' models
|
|
637
|
+
/\b(mi[-_ ]?(?:a\d|one|one[_ ]plus|note lte|max|cc)?[_ ]?(?:\d?\w?)[_ ]?(?:plus|se|lite|pro)?)(?: bui|\))/i, // Xiaomi Mi
|
|
638
|
+
/ ([\w ]+) miui\/v?\d/i,
|
|
639
|
+
],
|
|
640
|
+
[
|
|
641
|
+
[MODEL, /_/g, ' '],
|
|
642
|
+
[VENDOR, XIAOMI],
|
|
643
|
+
[TYPE, MOBILE],
|
|
644
|
+
],
|
|
645
|
+
[
|
|
646
|
+
// OPPO
|
|
647
|
+
/; (\w+) bui.+ oppo/i,
|
|
648
|
+
/\b(cph[12]\d{3}|p(?:af|c[al]|d\w|e[ar])[mt]\d0|x9007|a101op)\b/i,
|
|
649
|
+
],
|
|
650
|
+
[MODEL, [VENDOR, OPPO], [TYPE, MOBILE]],
|
|
651
|
+
[/\b(opd2(\d{3}a?))(?: bui|\))/i],
|
|
652
|
+
[MODEL, [VENDOR, strMapper, { OnePlus: ['304', '403', '203'], '*': OPPO }], [TYPE, TABLET]],
|
|
653
|
+
[
|
|
654
|
+
// Vivo
|
|
655
|
+
/vivo (\w+)(?: bui|\))/i,
|
|
656
|
+
/\b(v[12]\d{3}\w?[at])(?: bui|;)/i,
|
|
657
|
+
],
|
|
658
|
+
[MODEL, [VENDOR, 'Vivo'], [TYPE, MOBILE]],
|
|
659
|
+
[
|
|
660
|
+
// Realme
|
|
661
|
+
/\b(rmx[1-3]\d{3})(?: bui|;|\))/i,
|
|
662
|
+
],
|
|
663
|
+
[MODEL, [VENDOR, 'Realme'], [TYPE, MOBILE]],
|
|
664
|
+
[
|
|
665
|
+
// Motorola
|
|
666
|
+
/\b(milestone|droid(?:[2-4x]| (?:bionic|x2|pro|razr))?:?( 4g)?)\b[\w ]+build\//i,
|
|
667
|
+
/\bmot(?:orola)?[- ](\w*)/i,
|
|
668
|
+
/((?:moto(?! 360)[\w\(\) ]+|xt\d{3,4}|nexus 6)(?= bui|\)))/i,
|
|
669
|
+
],
|
|
670
|
+
[MODEL, [VENDOR, MOTOROLA], [TYPE, MOBILE]],
|
|
671
|
+
[/\b(mz60\d|xoom[2 ]{0,2}) build\//i],
|
|
672
|
+
[MODEL, [VENDOR, MOTOROLA], [TYPE, TABLET]],
|
|
673
|
+
[
|
|
674
|
+
// LG
|
|
675
|
+
/((?=lg)?[vl]k\-?\d{3}) bui| 3\.[-\w; ]{10}lg?-([06cv9]{3,4})/i,
|
|
676
|
+
],
|
|
677
|
+
[MODEL, [VENDOR, LG], [TYPE, TABLET]],
|
|
678
|
+
[
|
|
679
|
+
/(lm(?:-?f100[nv]?|-[\w\.]+)(?= bui|\))|nexus [45])/i,
|
|
680
|
+
/\blg[-e;\/ ]+((?!browser|netcast|android tv|watch)\w+)/i,
|
|
681
|
+
/\blg-?([\d\w]+) bui/i,
|
|
682
|
+
],
|
|
683
|
+
[MODEL, [VENDOR, LG], [TYPE, MOBILE]],
|
|
684
|
+
[
|
|
685
|
+
// Lenovo
|
|
686
|
+
/(ideatab[-\w ]+|602lv|d-42a|a101lv|a2109a|a3500-hv|s[56]000|pb-6505[my]|tb-?x?\d{3,4}(?:f[cu]|xu|[av])|yt\d?-[jx]?\d+[lfmx])( bui|;|\)|\/)/i,
|
|
687
|
+
/lenovo ?(b[68]0[08]0-?[hf]?|tab(?:[\w- ]+?)|tb[\w-]{6,7})( bui|;|\)|\/)/i,
|
|
688
|
+
],
|
|
689
|
+
[MODEL, [VENDOR, LENOVO], [TYPE, TABLET]],
|
|
690
|
+
[
|
|
691
|
+
// Nokia
|
|
692
|
+
/(nokia) (t[12][01])/i,
|
|
693
|
+
],
|
|
694
|
+
[VENDOR, MODEL, [TYPE, TABLET]],
|
|
695
|
+
[/(?:maemo|nokia).*(n900|lumia \d+|rm-\d+)/i, /nokia[-_ ]?(([-\w\. ]*))/i],
|
|
696
|
+
[
|
|
697
|
+
[MODEL, /_/g, ' '],
|
|
698
|
+
[TYPE, MOBILE],
|
|
699
|
+
[VENDOR, 'Nokia'],
|
|
700
|
+
],
|
|
701
|
+
[
|
|
702
|
+
// Google
|
|
703
|
+
/(pixel (c|tablet))\b/i, // Google Pixel C/Tablet
|
|
704
|
+
],
|
|
705
|
+
[MODEL, [VENDOR, GOOGLE], [TYPE, TABLET]],
|
|
706
|
+
[
|
|
707
|
+
/droid.+; (pixel[\daxl ]{0,6})(?: bui|\))/i, // Google Pixel
|
|
708
|
+
],
|
|
709
|
+
[MODEL, [VENDOR, GOOGLE], [TYPE, MOBILE]],
|
|
710
|
+
[
|
|
711
|
+
// Sony
|
|
712
|
+
/droid.+; (a?\d[0-2]{2}so|[c-g]\d{4}|so[-gl]\w+|xq-a\w[4-7][12])(?= bui|\).+chrome\/(?![1-6]{0,1}\d\.))/i,
|
|
713
|
+
],
|
|
714
|
+
[MODEL, [VENDOR, SONY], [TYPE, MOBILE]],
|
|
715
|
+
[/sony tablet [ps]/i, /\b(?:sony)?sgp\w+(?: bui|\))/i],
|
|
716
|
+
[
|
|
717
|
+
[MODEL, 'Xperia Tablet'],
|
|
718
|
+
[VENDOR, SONY],
|
|
719
|
+
[TYPE, TABLET],
|
|
720
|
+
],
|
|
721
|
+
[
|
|
722
|
+
// OnePlus
|
|
723
|
+
/ (kb2005|in20[12]5|be20[12][59])\b/i,
|
|
724
|
+
/(?:one)?(?:plus)? (a\d0\d\d)(?: b|\))/i,
|
|
725
|
+
],
|
|
726
|
+
[MODEL, [VENDOR, ONEPLUS], [TYPE, MOBILE]],
|
|
727
|
+
[
|
|
728
|
+
// Amazon
|
|
729
|
+
/(alexa)webm/i,
|
|
730
|
+
/(kf[a-z]{2}wi|aeo(?!bc)\w\w)( bui|\))/i, // Kindle Fire without Silk / Echo Show
|
|
731
|
+
/(kf[a-z]+)( bui|\)).+silk\//i, // Kindle Fire HD
|
|
732
|
+
],
|
|
733
|
+
[MODEL, [VENDOR, AMAZON], [TYPE, TABLET]],
|
|
734
|
+
[
|
|
735
|
+
/((?:sd|kf)[0349hijorstuw]+)( bui|\)).+silk\//i, // Fire Phone
|
|
736
|
+
],
|
|
737
|
+
[
|
|
738
|
+
[MODEL, /(.+)/g, 'Fire Phone $1'],
|
|
739
|
+
[VENDOR, AMAZON],
|
|
740
|
+
[TYPE, MOBILE],
|
|
741
|
+
],
|
|
742
|
+
[
|
|
743
|
+
// BlackBerry
|
|
744
|
+
/(playbook);[-\w\),; ]+(rim)/i, // BlackBerry PlayBook
|
|
745
|
+
],
|
|
746
|
+
[MODEL, VENDOR, [TYPE, TABLET]],
|
|
747
|
+
[
|
|
748
|
+
/\b((?:bb[a-f]|st[hv])100-\d)/i,
|
|
749
|
+
/\(bb10; (\w+)/i, // BlackBerry 10
|
|
750
|
+
],
|
|
751
|
+
[MODEL, [VENDOR, BLACKBERRY], [TYPE, MOBILE]],
|
|
752
|
+
[
|
|
753
|
+
// Asus
|
|
754
|
+
/(?:\b|asus_)(transfo[prime ]{4,10} \w+|eeepc|slider \w+|nexus 7|padfone|p00[cj])/i,
|
|
755
|
+
],
|
|
756
|
+
[MODEL, [VENDOR, ASUS], [TYPE, TABLET]],
|
|
757
|
+
[/ (z[bes]6[027][012][km][ls]|zenfone \d\w?)\b/i],
|
|
758
|
+
[MODEL, [VENDOR, ASUS], [TYPE, MOBILE]],
|
|
759
|
+
[
|
|
760
|
+
// HTC
|
|
761
|
+
/(nexus 9)/i, // HTC Nexus 9
|
|
762
|
+
],
|
|
763
|
+
[MODEL, [VENDOR, 'HTC'], [TYPE, TABLET]],
|
|
764
|
+
[
|
|
765
|
+
/(htc)[-;_ ]{1,2}([\w ]+(?=\)| bui)|\w+)/i, // HTC
|
|
766
|
+
// ZTE
|
|
767
|
+
/(zte)[- ]([\w ]+?)(?: bui|\/|\))/i,
|
|
768
|
+
/(alcatel|geeksphone|nexian|panasonic(?!(?:;|\.))|sony(?!-bra))[-_ ]?([-\w]*)/i, // Alcatel/GeeksPhone/Nexian/Panasonic/Sony
|
|
769
|
+
],
|
|
770
|
+
[VENDOR, [MODEL, /_/g, ' '], [TYPE, MOBILE]],
|
|
771
|
+
[
|
|
772
|
+
// TCL
|
|
773
|
+
/droid [\w\.]+; ((?:8[14]9[16]|9(?:0(?:48|60|8[01])|1(?:3[27]|66)|2(?:6[69]|9[56])|466))[gqswx])\w*(\)| bui)/i,
|
|
774
|
+
],
|
|
775
|
+
[MODEL, [VENDOR, 'TCL'], [TYPE, TABLET]],
|
|
776
|
+
[
|
|
777
|
+
// itel
|
|
778
|
+
/(itel) ((\w+))/i,
|
|
779
|
+
],
|
|
780
|
+
[[VENDOR, lowerize], MODEL, [TYPE, strMapper, { tablet: ['p10001l', 'w7001'], '*': 'mobile' }]],
|
|
781
|
+
[
|
|
782
|
+
// Acer
|
|
783
|
+
/droid.+; ([ab][1-7]-?[0178a]\d\d?)/i,
|
|
784
|
+
],
|
|
785
|
+
[MODEL, [VENDOR, 'Acer'], [TYPE, TABLET]],
|
|
786
|
+
[
|
|
787
|
+
// Meizu
|
|
788
|
+
/droid.+; (m[1-5] note) bui/i,
|
|
789
|
+
/\bmz-([-\w]{2,})/i,
|
|
790
|
+
],
|
|
791
|
+
[MODEL, [VENDOR, 'Meizu'], [TYPE, MOBILE]],
|
|
792
|
+
[
|
|
793
|
+
// Ulefone
|
|
794
|
+
/; ((?:power )?armor(?:[\w ]{0,8}))(?: bui|\))/i,
|
|
795
|
+
],
|
|
796
|
+
[MODEL, [VENDOR, 'Ulefone'], [TYPE, MOBILE]],
|
|
797
|
+
[
|
|
798
|
+
// Energizer
|
|
799
|
+
/; (energy ?\w+)(?: bui|\))/i,
|
|
800
|
+
/; energizer ([\w ]+)(?: bui|\))/i,
|
|
801
|
+
],
|
|
802
|
+
[MODEL, [VENDOR, 'Energizer'], [TYPE, MOBILE]],
|
|
803
|
+
[
|
|
804
|
+
// Cat
|
|
805
|
+
/; cat (b35);/i,
|
|
806
|
+
/; (b15q?|s22 flip|s48c|s62 pro)(?: bui|\))/i,
|
|
807
|
+
],
|
|
808
|
+
[MODEL, [VENDOR, 'Cat'], [TYPE, MOBILE]],
|
|
809
|
+
[
|
|
810
|
+
// Smartfren
|
|
811
|
+
/((?:new )?andromax[\w- ]+)(?: bui|\))/i,
|
|
812
|
+
],
|
|
813
|
+
[MODEL, [VENDOR, 'Smartfren'], [TYPE, MOBILE]],
|
|
814
|
+
[
|
|
815
|
+
// Nothing
|
|
816
|
+
/droid.+; (a(?:015|06[35]|142p?))/i,
|
|
817
|
+
],
|
|
818
|
+
[MODEL, [VENDOR, 'Nothing'], [TYPE, MOBILE]],
|
|
819
|
+
[
|
|
820
|
+
// Archos
|
|
821
|
+
/; (x67 5g|tikeasy \w+|ac[1789]\d\w+)( b|\))/i,
|
|
822
|
+
/archos ?(5|gamepad2?|([\w ]*[t1789]|hello) ?\d+[\w ]*)( b|\))/i,
|
|
823
|
+
],
|
|
824
|
+
[MODEL, [VENDOR, 'Archos'], [TYPE, TABLET]],
|
|
825
|
+
[/archos ([\w ]+)( b|\))/i, /; (ac[3-6]\d\w{2,8})( b|\))/i],
|
|
826
|
+
[MODEL, [VENDOR, 'Archos'], [TYPE, MOBILE]],
|
|
827
|
+
[
|
|
828
|
+
// MIXED
|
|
829
|
+
/(imo) (tab \w+)/i, // IMO
|
|
830
|
+
/(infinix) (x1101b?)/i, // Infinix XPad
|
|
831
|
+
],
|
|
832
|
+
[VENDOR, MODEL, [TYPE, TABLET]],
|
|
833
|
+
[
|
|
834
|
+
/(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus(?! zenw)|dell|jolla|meizu|motorola|polytron|infinix|tecno|micromax|advan)[-_ ]?([-\w]*)/i,
|
|
835
|
+
// BlackBerry/BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron/Infinix/Tecno/Micromax/Advan
|
|
836
|
+
/; (hmd|imo) ([\w ]+?)(?: bui|\))/i, // HMD/IMO
|
|
837
|
+
/(hp) ([\w ]+\w)/i, // HP iPAQ
|
|
838
|
+
/(microsoft); (lumia[\w ]+)/i, // Microsoft Lumia
|
|
839
|
+
/(lenovo)[-_ ]?([-\w ]+?)(?: bui|\)|\/)/i, // Lenovo
|
|
840
|
+
/(oppo) ?([\w ]+) bui/i, // OPPO
|
|
841
|
+
],
|
|
842
|
+
[VENDOR, MODEL, [TYPE, MOBILE]],
|
|
843
|
+
[
|
|
844
|
+
/(kobo)\s(ereader|touch)/i, // Kobo
|
|
845
|
+
/(hp).+(touchpad(?!.+tablet)|tablet)/i, // HP TouchPad
|
|
846
|
+
/(kindle)\/([\w\.]+)/i, // Kindle
|
|
847
|
+
/(nook)[\w ]+build\/(\w+)/i, // Nook
|
|
848
|
+
/(dell) (strea[kpr\d ]*[\dko])/i, // Dell Streak
|
|
849
|
+
/(le[- ]+pan)[- ]+(\w{1,9}) bui/i, // Le Pan Tablets
|
|
850
|
+
/(trinity)[- ]*(t\d{3}) bui/i, // Trinity Tablets
|
|
851
|
+
/(gigaset)[- ]+(q\w{1,9}) bui/i, // Gigaset Tablets
|
|
852
|
+
/(vodafone) ([\w ]+)(?:\)| bui)/i, // Vodafone
|
|
853
|
+
],
|
|
854
|
+
[VENDOR, MODEL, [TYPE, TABLET]],
|
|
855
|
+
[
|
|
856
|
+
/(surface duo)/i, // Surface Duo
|
|
857
|
+
],
|
|
858
|
+
[MODEL, [VENDOR, MICROSOFT], [TYPE, TABLET]],
|
|
859
|
+
[
|
|
860
|
+
/droid [\d\.]+; (fp\du?)(?: b|\))/i, // Fairphone
|
|
861
|
+
],
|
|
862
|
+
[MODEL, [VENDOR, 'Fairphone'], [TYPE, MOBILE]],
|
|
863
|
+
[
|
|
864
|
+
/(u304aa)/i, // AT&T
|
|
865
|
+
],
|
|
866
|
+
[MODEL, [VENDOR, 'AT&T'], [TYPE, MOBILE]],
|
|
867
|
+
[
|
|
868
|
+
/\bsie-(\w*)/i, // Siemens
|
|
869
|
+
],
|
|
870
|
+
[MODEL, [VENDOR, 'Siemens'], [TYPE, MOBILE]],
|
|
871
|
+
[
|
|
872
|
+
/\b(rct\w+) b/i, // RCA Tablets
|
|
873
|
+
],
|
|
874
|
+
[MODEL, [VENDOR, 'RCA'], [TYPE, TABLET]],
|
|
875
|
+
[
|
|
876
|
+
/\b(venue[\d ]{2,7}) b/i, // Dell Venue Tablets
|
|
877
|
+
],
|
|
878
|
+
[MODEL, [VENDOR, 'Dell'], [TYPE, TABLET]],
|
|
879
|
+
[
|
|
880
|
+
/\b(q(?:mv|ta)\w+) b/i, // Verizon Tablet
|
|
881
|
+
],
|
|
882
|
+
[MODEL, [VENDOR, 'Verizon'], [TYPE, TABLET]],
|
|
883
|
+
[
|
|
884
|
+
/\b(?:barnes[& ]+noble |bn[rt])([\w\+ ]*) b/i, // Barnes & Noble Tablet
|
|
885
|
+
],
|
|
886
|
+
[MODEL, [VENDOR, 'Barnes & Noble'], [TYPE, TABLET]],
|
|
887
|
+
[/\b(tm\d{3}\w+) b/i],
|
|
888
|
+
[MODEL, [VENDOR, 'NuVision'], [TYPE, TABLET]],
|
|
889
|
+
[
|
|
890
|
+
/\b(k88) b/i, // ZTE K Series Tablet
|
|
891
|
+
],
|
|
892
|
+
[MODEL, [VENDOR, 'ZTE'], [TYPE, TABLET]],
|
|
893
|
+
[
|
|
894
|
+
/\b(nx\d{3}j) b/i, // ZTE Nubia
|
|
895
|
+
],
|
|
896
|
+
[MODEL, [VENDOR, 'ZTE'], [TYPE, MOBILE]],
|
|
897
|
+
[
|
|
898
|
+
/\b(gen\d{3}) b.+49h/i, // Swiss GEN Mobile
|
|
899
|
+
],
|
|
900
|
+
[MODEL, [VENDOR, 'Swiss'], [TYPE, MOBILE]],
|
|
901
|
+
[
|
|
902
|
+
/\b(zur\d{3}) b/i, // Swiss ZUR Tablet
|
|
903
|
+
],
|
|
904
|
+
[MODEL, [VENDOR, 'Swiss'], [TYPE, TABLET]],
|
|
905
|
+
[
|
|
906
|
+
/\b((zeki)?tb.*\b) b/i, // Zeki Tablets
|
|
907
|
+
],
|
|
908
|
+
[MODEL, [VENDOR, 'Zeki'], [TYPE, TABLET]],
|
|
909
|
+
[
|
|
910
|
+
/\b([yr]\d{2}) b/i,
|
|
911
|
+
/\b(dragon[- ]+touch |dt)(\w{5}) b/i, // Dragon Touch Tablet
|
|
912
|
+
],
|
|
913
|
+
[[VENDOR, 'Dragon Touch'], MODEL, [TYPE, TABLET]],
|
|
914
|
+
[
|
|
915
|
+
/\b(ns-?\w{0,9}) b/i, // Insignia Tablets
|
|
916
|
+
],
|
|
917
|
+
[MODEL, [VENDOR, 'Insignia'], [TYPE, TABLET]],
|
|
918
|
+
[
|
|
919
|
+
/\b((nxa|next)-?\w{0,9}) b/i, // NextBook Tablets
|
|
920
|
+
],
|
|
921
|
+
[MODEL, [VENDOR, 'NextBook'], [TYPE, TABLET]],
|
|
922
|
+
[
|
|
923
|
+
/\b(xtreme\_)?(v(1[045]|2[015]|[3469]0|7[05])) b/i, // Voice Xtreme Phones
|
|
924
|
+
],
|
|
925
|
+
[[VENDOR, 'Voice'], MODEL, [TYPE, MOBILE]],
|
|
926
|
+
[
|
|
927
|
+
/\b(lvtel\-)?(v1[12]) b/i, // LvTel Phones
|
|
928
|
+
],
|
|
929
|
+
[[VENDOR, 'LvTel'], MODEL, [TYPE, MOBILE]],
|
|
930
|
+
[
|
|
931
|
+
/\b(ph-1) /i, // Essential PH-1
|
|
932
|
+
],
|
|
933
|
+
[MODEL, [VENDOR, 'Essential'], [TYPE, MOBILE]],
|
|
934
|
+
[
|
|
935
|
+
/\b(v(100md|700na|7011|917g).*\b) b/i, // Envizen Tablets
|
|
936
|
+
],
|
|
937
|
+
[MODEL, [VENDOR, 'Envizen'], [TYPE, TABLET]],
|
|
938
|
+
[
|
|
939
|
+
/\b(trio[-\w\. ]+) b/i, // MachSpeed Tablets
|
|
940
|
+
],
|
|
941
|
+
[MODEL, [VENDOR, 'MachSpeed'], [TYPE, TABLET]],
|
|
942
|
+
[
|
|
943
|
+
/\btu_(1491) b/i, // Rotor Tablets
|
|
944
|
+
],
|
|
945
|
+
[MODEL, [VENDOR, 'Rotor'], [TYPE, TABLET]],
|
|
946
|
+
[
|
|
947
|
+
/((?:tegranote|shield t(?!.+d tv))[\w- ]*?)(?: b|\))/i, // Nvidia Tablets
|
|
948
|
+
],
|
|
949
|
+
[MODEL, [VENDOR, NVIDIA], [TYPE, TABLET]],
|
|
950
|
+
[
|
|
951
|
+
/(sprint) (\w+)/i, // Sprint Phones
|
|
952
|
+
],
|
|
953
|
+
[VENDOR, MODEL, [TYPE, MOBILE]],
|
|
954
|
+
[
|
|
955
|
+
/(kin\.[onetw]{3})/i, // Microsoft Kin
|
|
956
|
+
],
|
|
957
|
+
[
|
|
958
|
+
[MODEL, /\./g, ' '],
|
|
959
|
+
[VENDOR, MICROSOFT],
|
|
960
|
+
[TYPE, MOBILE],
|
|
961
|
+
],
|
|
962
|
+
[
|
|
963
|
+
/droid.+; (cc6666?|et5[16]|mc[239][23]x?|vc8[03]x?)\)/i, // Zebra
|
|
964
|
+
],
|
|
965
|
+
[MODEL, [VENDOR, ZEBRA], [TYPE, TABLET]],
|
|
966
|
+
[/droid.+; (ec30|ps20|tc[2-8]\d[kx])\)/i],
|
|
967
|
+
[MODEL, [VENDOR, ZEBRA], [TYPE, MOBILE]],
|
|
968
|
+
[
|
|
969
|
+
///////////////////
|
|
970
|
+
// SMARTTVS
|
|
971
|
+
///////////////////
|
|
972
|
+
/smart-tv.+(samsung)/i, // Samsung
|
|
973
|
+
],
|
|
974
|
+
[VENDOR, [TYPE, SMARTTV]],
|
|
975
|
+
[/hbbtv.+maple;(\d+)/i],
|
|
976
|
+
[
|
|
977
|
+
[MODEL, /^/, 'SmartTV'],
|
|
978
|
+
[VENDOR, SAMSUNG],
|
|
979
|
+
[TYPE, SMARTTV],
|
|
980
|
+
],
|
|
981
|
+
[
|
|
982
|
+
/(nux; netcast.+smarttv|lg (netcast\.tv-201\d|android tv))/i, // LG SmartTV
|
|
983
|
+
],
|
|
984
|
+
[
|
|
985
|
+
[VENDOR, LG],
|
|
986
|
+
[TYPE, SMARTTV],
|
|
987
|
+
],
|
|
988
|
+
[
|
|
989
|
+
/(apple) ?tv/i, // Apple TV
|
|
990
|
+
],
|
|
991
|
+
[VENDOR, [MODEL, APPLE + ' TV'], [TYPE, SMARTTV]],
|
|
992
|
+
[
|
|
993
|
+
/crkey/i, // Google Chromecast
|
|
994
|
+
],
|
|
995
|
+
[
|
|
996
|
+
[MODEL, CHROME + 'cast'],
|
|
997
|
+
[VENDOR, GOOGLE],
|
|
998
|
+
[TYPE, SMARTTV],
|
|
999
|
+
],
|
|
1000
|
+
[
|
|
1001
|
+
/droid.+aft(\w+)( bui|\))/i, // Fire TV
|
|
1002
|
+
],
|
|
1003
|
+
[MODEL, [VENDOR, AMAZON], [TYPE, SMARTTV]],
|
|
1004
|
+
[
|
|
1005
|
+
/(shield \w+ tv)/i, // Nvidia Shield TV
|
|
1006
|
+
],
|
|
1007
|
+
[MODEL, [VENDOR, NVIDIA], [TYPE, SMARTTV]],
|
|
1008
|
+
[
|
|
1009
|
+
/\(dtv[\);].+(aquos)/i,
|
|
1010
|
+
/(aquos-tv[\w ]+)\)/i, // Sharp
|
|
1011
|
+
],
|
|
1012
|
+
[MODEL, [VENDOR, SHARP], [TYPE, SMARTTV]],
|
|
1013
|
+
[
|
|
1014
|
+
/(bravia[\w ]+)( bui|\))/i, // Sony
|
|
1015
|
+
],
|
|
1016
|
+
[MODEL, [VENDOR, SONY], [TYPE, SMARTTV]],
|
|
1017
|
+
[
|
|
1018
|
+
/(mi(tv|box)-?\w+) bui/i, // Xiaomi
|
|
1019
|
+
],
|
|
1020
|
+
[MODEL, [VENDOR, XIAOMI], [TYPE, SMARTTV]],
|
|
1021
|
+
[
|
|
1022
|
+
/Hbbtv.*(technisat) (.*);/i, // TechniSAT
|
|
1023
|
+
],
|
|
1024
|
+
[VENDOR, MODEL, [TYPE, SMARTTV]],
|
|
1025
|
+
[
|
|
1026
|
+
/\b(roku)[\dx]*[\)\/]((?:dvp-)?[\d\.]*)/i, // Roku
|
|
1027
|
+
/hbbtv\/\d+\.\d+\.\d+ +\([\w\+ ]*; *([\w\d][^;]*);([^;]*)/i, // HbbTV devices
|
|
1028
|
+
],
|
|
1029
|
+
[
|
|
1030
|
+
[VENDOR, trimStr],
|
|
1031
|
+
[MODEL, trimStr],
|
|
1032
|
+
[TYPE, SMARTTV],
|
|
1033
|
+
],
|
|
1034
|
+
[
|
|
1035
|
+
// SmartTV from Unidentified Vendors
|
|
1036
|
+
/droid.+; ([\w- ]+) (?:android tv|smart[- ]?tv)/i,
|
|
1037
|
+
],
|
|
1038
|
+
[MODEL, [TYPE, SMARTTV]],
|
|
1039
|
+
[/\b(android tv|smart[- ]?tv|opera tv|tv; rv:)\b/i],
|
|
1040
|
+
[[TYPE, SMARTTV]],
|
|
1041
|
+
[
|
|
1042
|
+
///////////////////
|
|
1043
|
+
// CONSOLES
|
|
1044
|
+
///////////////////
|
|
1045
|
+
/(ouya)/i, // Ouya
|
|
1046
|
+
/(nintendo) ([wids3utch]+)/i, // Nintendo
|
|
1047
|
+
],
|
|
1048
|
+
[VENDOR, MODEL, [TYPE, CONSOLE]],
|
|
1049
|
+
[
|
|
1050
|
+
/droid.+; (shield)( bui|\))/i, // Nvidia Portable
|
|
1051
|
+
],
|
|
1052
|
+
[MODEL, [VENDOR, NVIDIA], [TYPE, CONSOLE]],
|
|
1053
|
+
[
|
|
1054
|
+
/(playstation \w+)/i, // Playstation
|
|
1055
|
+
],
|
|
1056
|
+
[MODEL, [VENDOR, SONY], [TYPE, CONSOLE]],
|
|
1057
|
+
[
|
|
1058
|
+
/\b(xbox(?: one)?(?!; xbox))[\); ]/i, // Microsoft Xbox
|
|
1059
|
+
],
|
|
1060
|
+
[MODEL, [VENDOR, MICROSOFT], [TYPE, CONSOLE]],
|
|
1061
|
+
[
|
|
1062
|
+
///////////////////
|
|
1063
|
+
// WEARABLES
|
|
1064
|
+
///////////////////
|
|
1065
|
+
/\b(sm-[lr]\d\d[0156][fnuw]?s?|gear live)\b/i, // Samsung Galaxy Watch
|
|
1066
|
+
],
|
|
1067
|
+
[MODEL, [VENDOR, SAMSUNG], [TYPE, WEARABLE]],
|
|
1068
|
+
[
|
|
1069
|
+
/((pebble))app/i, // Pebble
|
|
1070
|
+
/(asus|google|lg|oppo) ((pixel |zen)?watch[\w ]*)( bui|\))/i, // Asus ZenWatch / LG Watch / Pixel Watch
|
|
1071
|
+
],
|
|
1072
|
+
[VENDOR, MODEL, [TYPE, WEARABLE]],
|
|
1073
|
+
[
|
|
1074
|
+
/(ow(?:19|20)?we?[1-3]{1,3})/i, // Oppo Watch
|
|
1075
|
+
],
|
|
1076
|
+
[MODEL, [VENDOR, OPPO], [TYPE, WEARABLE]],
|
|
1077
|
+
[
|
|
1078
|
+
/(watch)(?: ?os[,\/]|\d,\d\/)[\d\.]+/i, // Apple Watch
|
|
1079
|
+
],
|
|
1080
|
+
[MODEL, [VENDOR, APPLE], [TYPE, WEARABLE]],
|
|
1081
|
+
[
|
|
1082
|
+
/(opwwe\d{3})/i, // OnePlus Watch
|
|
1083
|
+
],
|
|
1084
|
+
[MODEL, [VENDOR, ONEPLUS], [TYPE, WEARABLE]],
|
|
1085
|
+
[
|
|
1086
|
+
/(moto 360)/i, // Motorola 360
|
|
1087
|
+
],
|
|
1088
|
+
[MODEL, [VENDOR, MOTOROLA], [TYPE, WEARABLE]],
|
|
1089
|
+
[
|
|
1090
|
+
/(smartwatch 3)/i, // Sony SmartWatch
|
|
1091
|
+
],
|
|
1092
|
+
[MODEL, [VENDOR, SONY], [TYPE, WEARABLE]],
|
|
1093
|
+
[
|
|
1094
|
+
/(g watch r)/i, // LG G Watch R
|
|
1095
|
+
],
|
|
1096
|
+
[MODEL, [VENDOR, LG], [TYPE, WEARABLE]],
|
|
1097
|
+
[/droid.+; (wt63?0{2,3})\)/i],
|
|
1098
|
+
[MODEL, [VENDOR, ZEBRA], [TYPE, WEARABLE]],
|
|
1099
|
+
[
|
|
1100
|
+
///////////////////
|
|
1101
|
+
// XR
|
|
1102
|
+
///////////////////
|
|
1103
|
+
/droid.+; (glass) \d/i, // Google Glass
|
|
1104
|
+
],
|
|
1105
|
+
[MODEL, [VENDOR, GOOGLE], [TYPE, WEARABLE]],
|
|
1106
|
+
[
|
|
1107
|
+
/(pico) (4|neo3(?: link|pro)?)/i, // Pico
|
|
1108
|
+
],
|
|
1109
|
+
[VENDOR, MODEL, [TYPE, WEARABLE]],
|
|
1110
|
+
[
|
|
1111
|
+
/; (quest( \d| pro)?)/i, // Oculus Quest
|
|
1112
|
+
],
|
|
1113
|
+
[MODEL, [VENDOR, FACEBOOK], [TYPE, WEARABLE]],
|
|
1114
|
+
[
|
|
1115
|
+
///////////////////
|
|
1116
|
+
// EMBEDDED
|
|
1117
|
+
///////////////////
|
|
1118
|
+
/(tesla)(?: qtcarbrowser|\/[-\w\.]+)/i, // Tesla
|
|
1119
|
+
],
|
|
1120
|
+
[VENDOR, [TYPE, EMBEDDED]],
|
|
1121
|
+
[
|
|
1122
|
+
/(aeobc)\b/i, // Echo Dot
|
|
1123
|
+
],
|
|
1124
|
+
[MODEL, [VENDOR, AMAZON], [TYPE, EMBEDDED]],
|
|
1125
|
+
[
|
|
1126
|
+
/(homepod).+mac os/i, // Apple HomePod
|
|
1127
|
+
],
|
|
1128
|
+
[MODEL, [VENDOR, APPLE], [TYPE, EMBEDDED]],
|
|
1129
|
+
[/windows iot/i],
|
|
1130
|
+
[[TYPE, EMBEDDED]],
|
|
1131
|
+
[
|
|
1132
|
+
////////////////////
|
|
1133
|
+
// MIXED (GENERIC)
|
|
1134
|
+
///////////////////
|
|
1135
|
+
/droid .+?; ([^;]+?)(?: bui|; wv\)|\) applew).+? mobile safari/i, // Android Phones from Unidentified Vendors
|
|
1136
|
+
],
|
|
1137
|
+
[MODEL, [TYPE, MOBILE]],
|
|
1138
|
+
[
|
|
1139
|
+
/droid .+?; ([^;]+?)(?: bui|\) applew).+?(?! mobile) safari/i, // Android Tablets from Unidentified Vendors
|
|
1140
|
+
],
|
|
1141
|
+
[MODEL, [TYPE, TABLET]],
|
|
1142
|
+
[
|
|
1143
|
+
/\b((tablet|tab)[;\/]|focus\/\d(?!.+mobile))/i, // Unidentifiable Tablet
|
|
1144
|
+
],
|
|
1145
|
+
[[TYPE, TABLET]],
|
|
1146
|
+
[
|
|
1147
|
+
/(phone|mobile(?:[;\/]| [ \w\/\.]*safari)|pda(?=.+windows ce))/i, // Unidentifiable Mobile
|
|
1148
|
+
],
|
|
1149
|
+
[[TYPE, MOBILE]],
|
|
1150
|
+
[
|
|
1151
|
+
/droid .+?; ([\w\. -]+)( bui|\))/i, // Generic Android Device
|
|
1152
|
+
],
|
|
1153
|
+
[MODEL, [VENDOR, 'Generic']],
|
|
1154
|
+
],
|
|
1155
|
+
engine: [
|
|
1156
|
+
[
|
|
1157
|
+
/windows.+ edge\/([\w\.]+)/i, // EdgeHTML
|
|
1158
|
+
],
|
|
1159
|
+
[VERSION, [NAME, EDGE + 'HTML']],
|
|
1160
|
+
[
|
|
1161
|
+
/(arkweb)\/([\w\.]+)/i, // ArkWeb
|
|
1162
|
+
],
|
|
1163
|
+
[NAME, VERSION],
|
|
1164
|
+
[
|
|
1165
|
+
/webkit\/537\.36.+chrome\/(?!27)([\w\.]+)/i, // Blink
|
|
1166
|
+
],
|
|
1167
|
+
[VERSION, [NAME, 'Blink']],
|
|
1168
|
+
[
|
|
1169
|
+
/(presto)\/([\w\.]+)/i, // Presto
|
|
1170
|
+
/(webkit|trident|netfront|netsurf|amaya|lynx|w3m|goanna|servo)\/([\w\.]+)/i, // WebKit/Trident/NetFront/NetSurf/Amaya/Lynx/w3m/Goanna/Servo
|
|
1171
|
+
/ekioh(flow)\/([\w\.]+)/i, // Flow
|
|
1172
|
+
/(khtml|tasman|links)[\/ ]\(?([\w\.]+)/i, // KHTML/Tasman/Links
|
|
1173
|
+
/(icab)[\/ ]([23]\.[\d\.]+)/i, // iCab
|
|
1174
|
+
/\b(libweb)/i, // LibWeb
|
|
1175
|
+
],
|
|
1176
|
+
[NAME, VERSION],
|
|
1177
|
+
[/ladybird\//i],
|
|
1178
|
+
[[NAME, 'LibWeb']],
|
|
1179
|
+
[
|
|
1180
|
+
/rv\:([\w\.]{1,9})\b.+(gecko)/i, // Gecko
|
|
1181
|
+
],
|
|
1182
|
+
[VERSION, NAME],
|
|
1183
|
+
],
|
|
1184
|
+
os: [
|
|
1185
|
+
[
|
|
1186
|
+
// Windows
|
|
1187
|
+
/microsoft (windows) (vista|xp)/i, // Windows (iTunes)
|
|
1188
|
+
],
|
|
1189
|
+
[NAME, VERSION],
|
|
1190
|
+
[
|
|
1191
|
+
/(windows (?:phone(?: os)?|mobile|iot))[\/ ]?([\d\.\w ]*)/i, // Windows Phone
|
|
1192
|
+
],
|
|
1193
|
+
[NAME, [VERSION, strMapper, windowsVersionMap]],
|
|
1194
|
+
[
|
|
1195
|
+
/windows nt 6\.2; (arm)/i, // Windows RT
|
|
1196
|
+
/windows[\/ ]([ntce\d\. ]+\w)(?!.+xbox)/i,
|
|
1197
|
+
/(?:win(?=3|9|n)|win 9x )([nt\d\.]+)/i,
|
|
1198
|
+
],
|
|
1199
|
+
[
|
|
1200
|
+
[VERSION, strMapper, windowsVersionMap],
|
|
1201
|
+
[NAME, 'Windows'],
|
|
1202
|
+
],
|
|
1203
|
+
[
|
|
1204
|
+
// iOS/macOS
|
|
1205
|
+
/[adehimnop]{4,7}\b(?:.*os ([\w]+) like mac|; opera)/i, // iOS
|
|
1206
|
+
/(?:ios;fbsv\/|iphone.+ios[\/ ])([\d\.]+)/i,
|
|
1207
|
+
/cfnetwork\/.+darwin/i,
|
|
1208
|
+
],
|
|
1209
|
+
[
|
|
1210
|
+
[VERSION, /_/g, '.'],
|
|
1211
|
+
[NAME, 'iOS'],
|
|
1212
|
+
],
|
|
1213
|
+
[
|
|
1214
|
+
/(mac os x) ?([\w\. ]*)/i,
|
|
1215
|
+
/(macintosh|mac_powerpc\b)(?!.+haiku)/i, // Mac OS
|
|
1216
|
+
],
|
|
1217
|
+
[
|
|
1218
|
+
[NAME, MAC_OS],
|
|
1219
|
+
[VERSION, /_/g, '.'],
|
|
1220
|
+
],
|
|
1221
|
+
[
|
|
1222
|
+
// Mobile OSes
|
|
1223
|
+
/droid ([\w\.]+)\b.+(android[- ]x86|harmonyos)/i, // Android-x86/HarmonyOS
|
|
1224
|
+
],
|
|
1225
|
+
[VERSION, NAME],
|
|
1226
|
+
[
|
|
1227
|
+
/(ubuntu) ([\w\.]+) like android/i, // Ubuntu Touch
|
|
1228
|
+
],
|
|
1229
|
+
[[NAME, /(.+)/, '$1 Touch'], VERSION],
|
|
1230
|
+
[
|
|
1231
|
+
// Android/Blackberry/WebOS/QNX/Bada/RIM/KaiOS/Maemo/MeeGo/S40/Sailfish OS/OpenHarmony/Tizen
|
|
1232
|
+
/(android|bada|blackberry|kaios|maemo|meego|openharmony|qnx|rim tablet os|sailfish|series40|symbian|tizen|webos)\w*[-\/; ]?([\d\.]*)/i,
|
|
1233
|
+
],
|
|
1234
|
+
[NAME, VERSION],
|
|
1235
|
+
[
|
|
1236
|
+
/\(bb(10);/i, // BlackBerry 10
|
|
1237
|
+
],
|
|
1238
|
+
[VERSION, [NAME, BLACKBERRY]],
|
|
1239
|
+
[
|
|
1240
|
+
/(?:symbian ?os|symbos|s60(?=;)|series ?60)[-\/ ]?([\w\.]*)/i, // Symbian
|
|
1241
|
+
],
|
|
1242
|
+
[VERSION, [NAME, 'Symbian']],
|
|
1243
|
+
[
|
|
1244
|
+
/mozilla\/[\d\.]+ \((?:mobile|tablet|tv|mobile; [\w ]+); rv:.+ gecko\/([\w\.]+)/i, // Firefox OS
|
|
1245
|
+
],
|
|
1246
|
+
[VERSION, [NAME, FIREFOX + ' OS']],
|
|
1247
|
+
[
|
|
1248
|
+
/web0s;.+rt(tv)/i,
|
|
1249
|
+
/\b(?:hp)?wos(?:browser)?\/([\w\.]+)/i, // WebOS
|
|
1250
|
+
],
|
|
1251
|
+
[VERSION, [NAME, 'webOS']],
|
|
1252
|
+
[
|
|
1253
|
+
/watch(?: ?os[,\/]|\d,\d\/)([\d\.]+)/i, // watchOS
|
|
1254
|
+
],
|
|
1255
|
+
[VERSION, [NAME, 'watchOS']],
|
|
1256
|
+
[
|
|
1257
|
+
// Google Chromecast
|
|
1258
|
+
/crkey\/([\d\.]+)/i, // Google Chromecast
|
|
1259
|
+
],
|
|
1260
|
+
[VERSION, [NAME, CHROME + 'cast']],
|
|
1261
|
+
[
|
|
1262
|
+
/(cros) [\w]+(?:\)| ([\w\.]+)\b)/i, // Chromium OS
|
|
1263
|
+
],
|
|
1264
|
+
[[NAME, CHROMIUM_OS], VERSION],
|
|
1265
|
+
[
|
|
1266
|
+
// Smart TVs
|
|
1267
|
+
/panasonic;(viera)/i, // Panasonic Viera
|
|
1268
|
+
/(netrange)mmh/i, // Netrange
|
|
1269
|
+
/(nettv)\/(\d+\.[\w\.]+)/i, // NetTV
|
|
1270
|
+
// Console
|
|
1271
|
+
/(nintendo|playstation) ([wids345portablevuch]+)/i, // Nintendo/Playstation
|
|
1272
|
+
/(xbox); +xbox ([^\);]+)/i, // Microsoft Xbox (360, One, X, S, Series X, Series S)
|
|
1273
|
+
// Other
|
|
1274
|
+
/\b(joli|palm)\b ?(?:os)?\/?([\w\.]*)/i, // Joli/Palm
|
|
1275
|
+
/(mint)[\/\(\) ]?(\w*)/i, // Mint
|
|
1276
|
+
/(mageia|vectorlinux)[; ]/i, // Mageia/VectorLinux
|
|
1277
|
+
/([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,
|
|
1278
|
+
// Ubuntu/Debian/SUSE/Gentoo/Arch/Slackware/Fedora/Mandriva/CentOS/PCLinuxOS/RedHat/Zenwalk/Linpus/Raspbian/Plan9/Minix/RISCOS/Contiki/Deepin/Manjaro/elementary/Sabayon/Linspire
|
|
1279
|
+
/(hurd|linux)(?: arm\w*| x86\w*| ?)([\w\.]*)/i, // Hurd/Linux
|
|
1280
|
+
/(gnu) ?([\w\.]*)/i, // GNU
|
|
1281
|
+
/\b([-frentopcghs]{0,5}bsd|dragonfly)[\/ ]?(?!amd|[ix346]{1,2}86)([\w\.]*)/i, // FreeBSD/NetBSD/OpenBSD/PC-BSD/GhostBSD/DragonFly
|
|
1282
|
+
/(haiku) (\w+)/i, // Haiku
|
|
1283
|
+
],
|
|
1284
|
+
[NAME, VERSION],
|
|
1285
|
+
[
|
|
1286
|
+
/(sunos) ?([\w\.\d]*)/i, // Solaris
|
|
1287
|
+
],
|
|
1288
|
+
[[NAME, 'Solaris'], VERSION],
|
|
1289
|
+
[
|
|
1290
|
+
/((?:open)?solaris)[-\/ ]?([\w\.]*)/i, // Solaris
|
|
1291
|
+
/(aix) ((\d)(?=\.|\)| )[\w\.])*/i, // AIX
|
|
1292
|
+
/\b(beos|os\/2|amigaos|morphos|openvms|fuchsia|hp-ux|serenityos)/i, // BeOS/OS2/AmigaOS/MorphOS/OpenVMS/Fuchsia/HP-UX/SerenityOS
|
|
1293
|
+
/(unix) ?([\w\.]*)/i, // UNIX
|
|
1294
|
+
],
|
|
1295
|
+
[NAME, VERSION],
|
|
1296
|
+
],
|
|
1297
|
+
};
|