ua-parser-js 2.0.0-alpha.2 → 2.0.0-alpha.3

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/readme.md CHANGED
@@ -3,11 +3,14 @@
3
3
  </p>
4
4
 
5
5
  <p align="center">
6
- <a href="https://travis-ci.org/faisalman/ua-parser-js"><img src="https://travis-ci.org/faisalman/ua-parser-js.svg?branch=master"></a>
7
- <a href="https://www.npmjs.com/package/ua-parser-js"><img src="https://img.shields.io/npm/v/ua-parser-js.svg"></a>
8
- <a href="https://www.npmjs.com/package/ua-parser-js"><img src="https://img.shields.io/npm/dw/ua-parser-js.svg"></a>
9
- <a href="https://www.jsdelivr.com/package/npm/ua-parser-js"><img src="https://data.jsdelivr.com/v1/package/npm/ua-parser-js/badge"></a>
10
- <a href="https://cdnjs.com/libraries/UAParser.js"><img src="https://img.shields.io/cdnjs/v/UAParser.js.svg"></a>
6
+ <a href="https://www.npmjs.com/package/ua-parser-js"><img src="https://img.shields.io/npm/dw/ua-parser-js?color=red&logo=npm&label=NPM%20DOWNLOADS&style=for-the-badge"></a>
7
+ <a href="https://www.jsdelivr.com/package/npm/ua-parser-js"><img src="https://img.shields.io/jsdelivr/gh/hw/faisalman/ua-parser-js?logo=jsdelivr&style=for-the-badge"></a>
8
+ <a href="https://github.com/faisalman/ua-parser-js"><img src="https://img.shields.io/github/stars/faisalman/ua-parser-js?color=yellow&logo=github&style=for-the-badge"></a>
9
+ <a href="https://bundlephobia.com/package/ua-parser-js@1.0.35"><img src="https://img.shields.io/bundlephobia/minzip/ua-parser-js?logo=hackthebox&logoColor=white&style=for-the-badge"/></a>
10
+ <a href="https://github.com/faisalman/ua-parser-js/graphs/contributors"><img src="https://img.shields.io/github/contributors/faisalman/ua-parser-js?color=purple&logo=githubsponsors&style=for-the-badge"></a>
11
+ <a href="https://www.npmjs.com/package/ua-parser-js"><img src="https://img.shields.io/npm/v/ua-parser-js.svg?logo=npm&color=red&style=for-the-badge"></a>
12
+ <a href="https://cdnjs.com/libraries/UAParser.js"><img src="https://img.shields.io/cdnjs/v/UAParser.js.svg?color=orange&style=for-the-badge"></a>
13
+ <img src="https://img.shields.io/ossf-scorecard/github.com/faisalman/ua-parser-js?label=openssf%20scorecard&style=for-the-badge">
11
14
  </p>
12
15
 
13
16
  # UAParser.js
@@ -17,6 +20,9 @@ JavaScript library to detect Browser, Engine, OS, CPU, and Device type/model fro
17
20
  * Author : Faisal Salman <<f@faisalman.com>>
18
21
  * Demo : https://faisalman.github.io/ua-parser-js
19
22
  * Source : https://github.com/faisalman/ua-parser-js
23
+ * Documentation :
24
+ * v1 : https://github.com/faisalman/ua-parser-js/tree/1.0.35#documentation
25
+ * v2 : https://faisalman.github.io/ua-parser-js-docs/v2
20
26
 
21
27
  ***
22
28
 
@@ -26,14 +32,6 @@ JavaScript library to detect Browser, Engine, OS, CPU, and Device type/model fro
26
32
  </thead>
27
33
  <tbody>
28
34
  <tr>
29
- <td align="center" width="200px" rowspan="2"><a href="https://www.npmjs.com/package/@51degrees/ua-parser-js"><img src="images/51degrees.svg" alt="51degrees" width="75%" height="75%" ></a></td>
30
- <td align="left" width="400px"><a href="https://www.npmjs.com/package/@51degrees/ua-parser-js">↗ @51degrees/ua-parser-js</a></td>
31
- </tr>
32
- <tr>
33
- <td><br/><p>UAParser.js has been upgraded to detect comprehensive device data based on the User-Agent and User-Agent Client Hints.</p><p>This package supports all device types including Apple and Android devices and can be used either in a browser (client-side) or Node.js environment (server-side).</p><p>Visit <a href="https://www.npmjs.com/package/@51degrees/ua-parser-js">↗ 51Degrees <u>UAParser</u></a> to get started.</p>
34
- </td>
35
- </tr>
36
- <tr>
37
35
  <td colspan="2">
38
36
  <a href="https://opencollective.com/ua-parser-js">↗ Become a sponsor</a>
39
37
  </td>
@@ -47,39 +45,47 @@ JavaScript library to detect Browser, Engine, OS, CPU, and Device type/model fro
47
45
  What's new & breaking, please read [CHANGELOG](changelog.md) before upgrading.
48
46
 
49
47
  # Documentation
50
- ### UAParser([user-agent:string][,extensions:object][,headers:object(since@2.0)])
51
-
52
- In the browser environment you dont need to pass the user-agent string to the function, you can just call the funtion and it should automatically get the string from the `window.navigator.userAgent`, but that is not the case in nodejs. The user-agent string must be passed in' nodejs for the function to work. Usually you can find the user agent in: `request.headers["user-agent"]`.
48
+ ### `UAParser([user-agent:string][,extensions:object][,headers:object(since@2.0)]):IData`
53
49
 
50
+ In browser environment you don't need to pass the user-agent string to the function, as it should automatically get the string from the `window.navigator.userAgent`. Whereas in nodejs environment, the user-agent string must be passed in order for the function to work (usually you can find the user-agent in: `request.headers["user-agent"]`).
54
51
 
55
52
  ## Constructor
53
+
54
+ #### * `new UAParser([user-agent:string][,extensions:object][,headers:object(since@2.0)]):UAParser`
55
+
56
56
  When you call `UAParser` with the `new` keyword, `UAParser` will return a new instance with an empty result object, you have to call one of the available methods to get the information from the user-agent string.
57
57
  Like so:
58
- * `new UAParser([user-agent:string][,extensions:object][,headers:object(since@2.0)])`
58
+
59
59
  ```js
60
60
  let parser = new UAParser("your user-agent here"); // you need to pass the user-agent for nodejs
61
61
  console.log(parser); // {}
62
62
  let parserResults = parser.getResult();
63
63
  console.log(parserResults);
64
- /** {
65
- "ua" : "",
66
- "browser" : {},
67
- "engine" : {},
68
- "os" : {},
69
- "device" : {},
70
- "cpu" : {}
71
- } */
64
+ /*
65
+ {
66
+ ua : "",
67
+ browser : {},
68
+ engine : {},
69
+ os : {},
70
+ device : {},
71
+ cpu : {}
72
+ }
73
+ */
72
74
  ```
73
75
 
74
- When you call UAParser without the `new` keyword, it will automatically call `getResult()` function and return the parsed results.
75
- * `UAParser([user-agent:string][,extensions:object][,headers:object(since@2.0)])`
76
- * returns result object `{ ua: '', browser: {}, cpu: {}, device: {}, engine: {}, os: {} }`
76
+ #### * `UAParser([user-agent:string][,extensions:object][,headers:object(since@2.0)]):IData`
77
77
 
78
- ## Methods
78
+ When you call `UAParser` without the `new` keyword, it will automatically call `getResult()` function and return the parsed results.
79
+
80
+ ```sh
81
+ returns result object `{ ua: '', browser: {}, cpu: {}, device: {}, engine: {}, os: {} }`
82
+ ```
83
+
84
+ ## `UAParser`:
79
85
 
80
86
  #### Methods table
81
87
  The methods are self explanatory, here's a small overview on all the available methods:
82
- * `getResult()` - returns all function object calls, user-agent string, browser info, cpu, device, engine, os:
88
+ * `getResult()` - returns all function object calls, user-agent string, browser info, cpu, device, engine, os:
83
89
  `{ ua: '', browser: {}, cpu: {}, device: {}, engine: {}, os: {} }`.
84
90
 
85
91
  * `getBrowser()` - returns the browser name and version.
@@ -88,17 +94,21 @@ The methods are self explanatory, here's a small overview on all the available m
88
94
  * `getOS()` - returns the running operating system name and version.
89
95
  * `getCPU()` - returns CPU architectural design name.
90
96
  * `getUA()` - returns the user-agent string.
91
- * `setUA(user-agent)` - set a custom user-agent to be parsed.
97
+ * `setUA(ua)` - set a custom user-agent to be parsed.
92
98
 
93
99
  ---
94
100
 
95
- * `getResult()`
96
- * returns `{ ua: '', browser: {}, cpu: {}, device: {}, engine: {}, os: {} }`
101
+ #### * `getResult():IData`
102
+
103
+ ```sh
104
+ returns `{ ua: '', browser: {}, cpu: {}, device: {}, engine: {}, os: {} }`
105
+ ```
97
106
 
98
- * `getBrowser()`
99
- * returns `{ name: '', version: '' }`
107
+ #### * `getBrowser():IData`
100
108
 
101
109
  ```sh
110
+ returns `{ name: '', version: '' }`
111
+
102
112
  # Possible 'browser.name':
103
113
  2345Explorer, 360 Browser, Amaya, Android Browser, Arora, Avant, Avast, AVG,
104
114
  BIDUBrowser, Baidu, Basilisk, Blazer, Bolt, Brave, Bowser, Camino, Chimera,
@@ -113,16 +123,18 @@ NetSurf, Netfront, Netscape, NokiaBrowser, Obigo, Oculus Browser, OmniWeb,
113
123
  Opera Coast, Opera [Mini/Mobi/Tablet], PaleMoon, PhantomJS, Phoenix, Polaris,
114
124
  Puffin, QQ, QQBrowser, QQBrowserLite, Quark, QupZilla, RockMelt, [Mobile] Safari,
115
125
  Sailfish Browser, Samsung Browser, SeaMonkey, Silk, Skyfire, Sleipnir, Slim,
116
- SlimBrowser, Swiftfox, Tesla, TikTok, Tizen Browser, UCBrowser, UP.Browser, Viera,
117
- Vivaldi, Waterfox, WeChat, Weibo, Yandex, baidu, iCab, w3m, Whale Browser, ...
126
+ SlimBrowser, Snapchat, Swiftfox, Tesla, TikTok, Tizen Browser, UCBrowser,
127
+ UP.Browser, Viera, Vivaldi, Waterfox, WeChat, Weibo, Yandex, baidu, iCab, w3m,
128
+ Whale Browser, ...
118
129
 
119
130
  # 'browser.version' determined dynamically
120
131
  ```
121
132
 
122
- * `getDevice()`
123
- * returns `{ model: '', type: '', vendor: '' }`
133
+ #### * `getDevice():IData`
124
134
 
125
135
  ```sh
136
+ returns `{ model: '', type: '', vendor: '' }`
137
+
126
138
  # Possible 'device.type':
127
139
  console, mobile, tablet, smarttv, wearable, embedded
128
140
 
@@ -135,18 +147,20 @@ console, mobile, tablet, smarttv, wearable, embedded
135
147
 
136
148
  # Possible 'device.vendor':
137
149
  Acer, Alcatel, Amazon, Apple, Archos, ASUS, AT&T, BenQ, BlackBerry, Dell,
138
- Essential, Facebook, Fairphone, GeeksPhone, Google, HP, HTC, Huawei, Jolla, Kobo,
139
- Lenovo, LG, Meizu, Microsoft, Motorola, Nexian, Nintendo, Nokia, Nvidia, OnePlus,
140
- OPPO, Ouya, Palm, Panasonic, Pebble, Polytron, Realme, RIM, Roku, Samsung, Sharp,
141
- Siemens, Sony[Ericsson], Sprint, Tesla, Vivo, Vodafone, Xbox, Xiaomi, Zebra, ZTE, ...
150
+ Essential, Facebook, Fairphone, GeeksPhone, Google, HP, HTC, Huawei, Infinix, Jolla,
151
+ Kobo, Lenovo, LG, Meizu, Microsoft, Motorola, Nexian, Nintendo, Nokia, Nvidia,
152
+ OnePlus, OPPO, Ouya, Palm, Panasonic, Pebble, Polytron, Realme, RIM, Roku, Samsung,
153
+ Sharp, Siemens, Sony[Ericsson], Sprint, Tecno, Tesla, Vivo, Vodafone, Xbox, Xiaomi,
154
+ Zebra, ZTE, ...
142
155
 
143
156
  # 'device.model' determined dynamically
144
157
  ```
145
158
 
146
- * `getEngine()`
147
- * returns `{ name: '', version: '' }`
159
+ #### * `getEngine():IData`
148
160
 
149
161
  ```sh
162
+ returns `{ name: '', version: '' }`
163
+
150
164
  # Possible 'engine.name'
151
165
  Amaya, Blink, EdgeHTML, Flow, Gecko, Goanna, iCab, KHTML, LibWeb, Links, Lynx,
152
166
  NetFront, NetSurf, Presto, Tasman, Trident, w3m, WebKit
@@ -154,10 +168,11 @@ NetFront, NetSurf, Presto, Tasman, Trident, w3m, WebKit
154
168
  # 'engine.version' determined dynamically
155
169
  ```
156
170
 
157
- * `getOS()`
158
- * returns `{ name: '', version: '' }`
171
+ #### * `getOS():IData`
159
172
 
160
173
  ```sh
174
+ returns `{ name: '', version: '' }`
175
+
161
176
  # Possible 'os.name'
162
177
  AIX, Amiga OS, Android[-x86], Arch, Bada, BeOS, BlackBerry, CentOS, Chromium OS,
163
178
  Contiki, Fedora, Firefox OS, FreeBSD, Debian, Deepin, DragonFly, elementary OS,
@@ -172,22 +187,42 @@ Zenwalk, ...
172
187
  # 'os.version' determined dynamically
173
188
  ```
174
189
 
175
- * `getCPU()`
176
- * returns `{ architecture: '' }`
190
+ #### * `getCPU():IData`
177
191
 
178
192
  ```sh
193
+ returns `{ architecture: '' }`
194
+
179
195
  # Possible 'cpu.architecture'
180
196
  68k, amd64, arm[64/hf], avr, ia[32/64], irix[64], mips[64], pa-risc, ppc, sparc[64]
181
197
  ```
182
198
 
183
- * `getUA()`
184
- * returns UA string of current instance
199
+ #### * `getUA():string`
200
+
201
+ ```sh
202
+ returns user-agent string of current instance
203
+ ```
185
204
 
186
- * `setUA(uastring)`
187
- * set UA string to be parsed
188
- * returns current instance
205
+ #### * `setUA(ua:string):UAParser`
189
206
 
190
- #### * `is():boolean` utility `since@2.0`
207
+ ```sh
208
+ set user-agent string to be parsed
209
+ returns current instance
210
+ ```
211
+
212
+ ---
213
+
214
+ ## `IData`: `since@2.0`
215
+
216
+ #### Methods table
217
+ The methods are self explanatory, here's a small overview on all the available methods:
218
+ * `is(value)` - returns `true` if the passed value matches a value of current object, `false` otherwise
219
+ * `toString()` - returns the full-name values of current object as a string
220
+ * `withClientHints()` - returns an object with re-updated data from client hints
221
+ * `withFeatureCheck()` - returns an object with re-updated data from feature detection
222
+
223
+ ---
224
+
225
+ #### * `is(value:string):boolean`
191
226
 
192
227
  ```js
193
228
  // Is just a shorthand comparison to check whether the value of specified item equals one of its properties (in a case-insensitive way)
@@ -246,7 +281,7 @@ let engine = uap.getEngine();
246
281
  engine.is("Blink"); // true
247
282
  ```
248
283
 
249
- #### * `toString():string` utility `since@2.0`
284
+ #### * `toString():string`
250
285
 
251
286
  ```js
252
287
  // Retrieve full-name values as a string
@@ -287,7 +322,7 @@ engine.version; // "28.0.1500.95"
287
322
  engine.toString(); // "Blink 28.0.1500.95"
288
323
  ```
289
324
 
290
- #### * `withClientHints():Promise<object>|Thenable<object>|object` `since@2.0`
325
+ #### * `withClientHints():Promise<IData>|Thenable<IData>|IData`
291
326
 
292
327
  Recently, Chrome limits the information exposed through user-agent and introduces a new experimental set of data called "client-hints". In browser-environment, obtaining the client-hints data via JavaScript must be done in an asynchronous way. In `UAParser` you can chain the result object from `get*` method with `withClientHints()` to also read the client-hints data from the browser and return the updated data as a `Promise`.
293
328
 
@@ -346,6 +381,21 @@ new UAParser(request.headers)
346
381
  });
347
382
  ```
348
383
 
384
+ #### * `withFeatureCheck():IData`
385
+
386
+ This method allows us to examine other features beyond `navigator.userAgent` to further improve detection of the following:
387
+ - browser : Brave (check for `navigator.isBrave`)
388
+ - device : iPad (check for `navigator.standalone` & `navigator.maxTouchPoints`)
389
+
390
+ ```js
391
+ // suppose this code runs on iPad
392
+ const withoutFeatureCheck = UAParser();
393
+ const withFeatureCheck = UAParser().withFeatureCheck();
394
+
395
+ console.log(withoutFeatureCheck.device); // { vendor : "Apple", model : "Macintosh", type : undefined }
396
+ console.log(withFeatureCheck.device); // { vendor : "Apple", model : "iPad", type : "tablet" }
397
+ ```
398
+
349
399
  ## Extending Regex
350
400
 
351
401
  If you want to detect something that's not currently provided by UAParser.js (eg: `bots`, specific apps, etc), you can pass a list of regexes to extend internal UAParser.js regexes with your own.
@@ -1,10 +1,12 @@
1
1
  ///////////////////////////////////////////////
2
- /* Enums for UAParser.js v2.0.0-alpha.2
2
+ /* Enums for UAParser.js v2.0.0-alpha.3
3
3
  https://github.com/faisalman/ua-parser-js
4
4
  Author: Faisal Salman <f@faisalman.com>
5
5
  MIT License */
6
6
  //////////////////////////////////////////////
7
7
 
8
+ /*jshint esversion: 6 */
9
+
8
10
  const BrowserName = Object.freeze({
9
11
  CHROME : 'Chrome',
10
12
  EDGE : 'Edge',
@@ -98,4 +100,4 @@ module.exports = {
98
100
  DeviceVendor,
99
101
  EngineName,
100
102
  OSName
101
- }
103
+ };
@@ -1,14 +1,16 @@
1
1
  // Generated ESM version of UAParser.js enums
2
2
  // DO NOT EDIT THIS FILE!
3
- // Source: /src/enum/ua-parser-enum.js
3
+ // Source: /src/enums/ua-parser-enums.js
4
4
 
5
5
  ///////////////////////////////////////////////
6
- /* Enums for UAParser.js v2.0.0-alpha.2
6
+ /* Enums for UAParser.js v2.0.0-alpha.3
7
7
  https://github.com/faisalman/ua-parser-js
8
8
  Author: Faisal Salman <f@faisalman.com>
9
9
  MIT License */
10
10
  //////////////////////////////////////////////
11
11
 
12
+ /*jshint esversion: 6 */
13
+
12
14
  const BrowserName = Object.freeze({
13
15
  CHROME : 'Chrome',
14
16
  EDGE : 'Edge',
@@ -102,4 +104,4 @@ export {
102
104
  DeviceVendor,
103
105
  EngineName,
104
106
  OSName
105
- }
107
+ };
@@ -0,0 +1,248 @@
1
+ ///////////////////////////////////////////////
2
+ /* Extensions for UAParser.js v2.0.0-alpha.3
3
+ https://github.com/faisalman/ua-parser-js
4
+ Author: Faisal Salman <f@faisalman.com>
5
+ MIT License */
6
+ //////////////////////////////////////////////
7
+
8
+ /*jshint esversion: 6 */
9
+
10
+ const MODEL = 'model';
11
+ const NAME = 'name';
12
+ const TYPE = 'type';
13
+ const VENDOR = 'vendor';
14
+ const VERSION = 'version';
15
+ const MOBILE = 'mobile';
16
+ const TABLET = 'tablet';
17
+
18
+ const Apps = Object.freeze({
19
+ browser : [
20
+ [/chatlyio\/([\d\.]+)/i], [VERSION, 'Slack', [TYPE, 'app']]
21
+ ]
22
+ });
23
+
24
+ const Bots = Object.freeze({
25
+ browser : [
26
+ // Googlebot / BingBot / MSNBot / FacebookBot
27
+ [/((?:google|bing|msn|facebook)bot(?:[\-imagevdo]{0,6})|bingpreview)\/([\w\.]+)/i], [NAME, VERSION, [TYPE, 'bot']],
28
+
29
+ // GPTBot - https://platform.openai.com/docs/gptbot
30
+ [/(gptbot)\/([\w\.]+)/i], [NAME, VERSION, [TYPE, 'bot']],
31
+
32
+ // Slackbot - https://api.slack.com/robots
33
+ [/(slack(?:bot)?(?:-imgproxy|-linkexpanding)?) ([\w\.]+)/i], [NAME, VERSION, [TYPE, 'bot']]
34
+ ]
35
+ });
36
+
37
+ const CLIs = Object.freeze({
38
+ browser : [
39
+ // wget / curl / lynx
40
+ [/(wget|curl|lynx)\/([\w\.]+)/i], [NAME, VERSION, [TYPE, 'cli']]
41
+ ]
42
+ });
43
+
44
+ const ExtraDevices = Object.freeze({
45
+ device : [[
46
+ /(nook)[\w ]+build\/(\w+)/i, // Nook
47
+ /(dell) (strea[kpr\d ]*[\dko])/i, // Dell Streak
48
+ /(le[- ]+pan)[- ]+(\w{1,9}) bui/i, // Le Pan Tablets
49
+ /(trinity)[- ]*(t\d{3}) bui/i, // Trinity Tablets
50
+ /(gigaset)[- ]+(q\w{1,9}) bui/i, // Gigaset Tablets
51
+ /(vodafone) ([\w ]+)(?:\)| bui)/i // Vodafone
52
+ ], [VENDOR, MODEL, [TYPE, TABLET]], [
53
+
54
+ /(u304aa)/i // AT&T
55
+ ], [MODEL, [VENDOR, 'AT&T'], [TYPE, MOBILE]], [
56
+
57
+ /\bsie-(\w*)/i // Siemens
58
+ ], [MODEL, [VENDOR, 'Siemens'], [TYPE, MOBILE]], [
59
+
60
+ /\b(rct\w+) b/i // RCA Tablets
61
+ ], [MODEL, [VENDOR, 'RCA'], [TYPE, TABLET]], [
62
+
63
+ /\b(venue[\d ]{2,7}) b/i // Dell Venue Tablets
64
+ ], [MODEL, [VENDOR, 'Dell'], [TYPE, TABLET]], [
65
+
66
+ /\b(q(?:mv|ta)\w+) b/i // Verizon Tablet
67
+ ], [MODEL, [VENDOR, 'Verizon'], [TYPE, TABLET]], [
68
+
69
+ /\b(?:barnes[& ]+noble |bn[rt])([\w\+ ]*) b/i // Barnes & Noble Tablet
70
+ ], [MODEL, [VENDOR, 'Barnes & Noble'], [TYPE, TABLET]], [
71
+
72
+ /\b(tm\d{3}\w+) b/i
73
+ ], [MODEL, [VENDOR, 'NuVision'], [TYPE, TABLET]], [
74
+
75
+ /\b(k88) b/i // ZTE K Series Tablet
76
+ ], [MODEL, [VENDOR, 'ZTE'], [TYPE, TABLET]], [
77
+
78
+ /\b(nx\d{3}j) b/i // ZTE Nubia
79
+ ], [MODEL, [VENDOR, 'ZTE'], [TYPE, MOBILE]], [
80
+
81
+ /\b(gen\d{3}) b.+49h/i // Swiss GEN Mobile
82
+ ], [MODEL, [VENDOR, 'Swiss'], [TYPE, MOBILE]], [
83
+
84
+ /\b(zur\d{3}) b/i // Swiss ZUR Tablet
85
+ ], [MODEL, [VENDOR, 'Swiss'], [TYPE, TABLET]], [
86
+
87
+ /\b((zeki)?tb.*\b) b/i // Zeki Tablets
88
+ ], [MODEL, [VENDOR, 'Zeki'], [TYPE, TABLET]], [
89
+
90
+ /\b([yr]\d{2}) b/i,
91
+ /\b(?:dragon[- ]+touch |dt)(\w{5}) b/i // Dragon Touch Tablet
92
+ ], [MODEL, [VENDOR, 'Dragon Touch'], [TYPE, TABLET]], [
93
+
94
+ /\b(ns-?\w{0,9}) b/i // Insignia Tablets
95
+ ], [MODEL, [VENDOR, 'Insignia'], [TYPE, TABLET]], [
96
+
97
+ /\b((nxa|next)-?\w{0,9}) b/i // NextBook Tablets
98
+ ], [MODEL, [VENDOR, 'NextBook'], [TYPE, TABLET]], [
99
+
100
+ /\b(xtreme\_)?(v(1[045]|2[015]|[3469]0|7[05])) b/i // Voice Xtreme Phones
101
+ ], [[VENDOR, 'Voice'], MODEL, [TYPE, MOBILE]], [
102
+
103
+ /\b(lvtel\-)?(v1[12]) b/i // LvTel Phones
104
+ ], [[VENDOR, 'LvTel'], MODEL, [TYPE, MOBILE]], [
105
+
106
+ /\b(ph-1) /i // Essential PH-1
107
+ ], [MODEL, [VENDOR, 'Essential'], [TYPE, MOBILE]], [
108
+
109
+ /\b(v(100md|700na|7011|917g).*\b) b/i // Envizen Tablets
110
+ ], [MODEL, [VENDOR, 'Envizen'], [TYPE, TABLET]], [
111
+
112
+ /\b(trio[-\w\. ]+) b/i // MachSpeed Tablets
113
+ ], [MODEL, [VENDOR, 'MachSpeed'], [TYPE, TABLET]], [
114
+
115
+ /\btu_(1491) b/i // Rotor Tablets
116
+ ], [MODEL, [VENDOR, 'Rotor'], [TYPE, TABLET]]
117
+ ]
118
+ });
119
+
120
+ const Emails = Object.freeze({
121
+ browser : [
122
+ // Microsoft Outlook / Thunderbird
123
+ [/(microsoft outlook|thunderbird)[\s\/]([\w\.]+)/i], [NAME, VERSION, [TYPE, 'email']]
124
+ ]
125
+ });
126
+
127
+ const MediaPlayers = Object.freeze({
128
+ browser : [[
129
+
130
+ /(apple(?:coremedia|))\/([\w\._]+)/i, // Generic Apple CoreMedia
131
+ /(coremedia) v([\w\._]+)/i
132
+ ], [NAME, VERSION], [
133
+
134
+ /(aqualung|lyssna|bsplayer)\/([\w\.-]+)/i // Aqualung/Lyssna/BSPlayer
135
+ ], [NAME, VERSION], [
136
+
137
+ /(ares|ossproxy)\s([\w\.-]+)/i // Ares/OSSProxy
138
+ ], [NAME, VERSION], [
139
+
140
+ /(audacious|audimusicstream|amarok|bass|core|dalvik|gnomemplayer|music on console|nsplayer|psp-internetradioplayer|videos)\/([\w\.-]+)/i,
141
+ // Audacious/AudiMusicStream/Amarok/BASS/OpenCORE/Dalvik/GnomeMplayer/MoC
142
+ // NSPlayer/PSP-InternetRadioPlayer/Videos
143
+ /(clementine|music player daemon)\s([\w\.-]+)/i, // Clementine/MPD
144
+ /(lg player|nexplayer)\s([\d\.]+)/i,
145
+ /player\/(nexplayer|lg player)\s([\w\.-]+)/i // NexPlayer/LG Player
146
+ ], [NAME, VERSION], [
147
+ /(nexplayer)\s([\w\.-]+)/i // Nexplayer
148
+ ], [NAME, VERSION], [
149
+
150
+ /(flrp)\/([\w\.-]+)/i // Flip Player
151
+ ], [[NAME, 'Flip Player'], VERSION], [
152
+
153
+ /(fstream|nativehost|queryseekspider|ia-archiver|facebookexternalhit)/i
154
+ // FStream/NativeHost/QuerySeekSpider/IA Archiver/facebookexternalhit
155
+ ], [NAME], [
156
+
157
+ /(gstreamer) souphttpsrc.+libsoup\/([\w\.-]+)/i
158
+ // Gstreamer
159
+ ], [NAME, VERSION], [
160
+
161
+ /(htc streaming player)\s[\w_]+\s\/\s([\d\.]+)/i, // HTC Streaming Player
162
+ /(java|python-urllib|python-requests|wget|libcurl)\/([\w\.-_]+)/i,
163
+ // Java/urllib/requests/wget/cURL
164
+ /(lavf)([\d\.]+)/i // Lavf (FFMPEG)
165
+ ], [NAME, VERSION], [
166
+
167
+ /(htc_one_s)\/([\d\.]+)/i, // HTC One S
168
+ ], [[NAME, /_/g, ' '], VERSION], [
169
+
170
+ /(mplayer)(?:\s|\/)(?:(?:sherpya-){0,1}svn)(?:-|\s)(r\d+(?:-\d+[\w\.-]+))/i,
171
+ // MPlayer SVN
172
+ ], [NAME, VERSION], [
173
+
174
+ /(mplayer)(?:\s|\/)([\w\.-]+)/i, // MPlayer
175
+ /(mplayer) unknown-([\w\.\-]+)/i // MPlayer UNKNOWN
176
+ ], [NAME, VERSION], [
177
+
178
+ /(mplayer)/i, // MPlayer (no other info)
179
+ /(yourmuze)/i, // YourMuze
180
+ /(media player classic|nero showtime)/i // Media Player Classic/Nero ShowTime
181
+ ], [NAME], [
182
+
183
+ /(nero (?:home|scout))\/([\w\.-]+)/i // Nero Home/Nero Scout
184
+ ], [NAME, VERSION], [
185
+
186
+ /(nokia\d+)\/([\w\.-]+)/i // Nokia
187
+ ], [NAME, VERSION], [
188
+
189
+ /\s(songbird)\/([\w\.-]+)/i // Songbird/Philips-Songbird
190
+ ], [NAME, VERSION], [
191
+
192
+ /(winamp)3 version ([\w\.-]+)/i, // Winamp
193
+ /(winamp)\s([\w\.-]+)/i,
194
+ /(winamp)mpeg\/([\w\.-]+)/i
195
+ ], [NAME, VERSION], [
196
+
197
+ /(ocms-bot|tapinradio|tunein radio|unknown|winamp|inlight radio)/i // OCMS-bot/tap in radio/tunein/unknown/winamp (no other info)
198
+ // inlight radio
199
+ ], [NAME], [
200
+
201
+ /(quicktime|rma|radioapp|radioclientapplication|soundtap|totem|stagefright|streamium)\/([\w\.-]+)/i
202
+ // QuickTime/RealMedia/RadioApp/RadioClientApplication/
203
+ // SoundTap/Totem/Stagefright/Streamium
204
+ ], [NAME, VERSION], [
205
+
206
+ /(smp)([\d\.]+)/i // SMP
207
+ ], [NAME, VERSION], [
208
+
209
+ /(vlc) media player - version ([\w\.]+)/i, // VLC Videolan
210
+ /(vlc)\/([\w\.-]+)/i,
211
+ /(xbmc|gvfs|xine|xmms|irapp)\/([\w\.-]+)/i, // XBMC/gvfs/Xine/XMMS/irapp
212
+ /(foobar2000)\/([\d\.]+)/i, // Foobar2000
213
+ /(itunes)\/([\d\.]+)/i // iTunes
214
+ ], [NAME, VERSION], [
215
+
216
+ /(wmplayer)\/([\w\.-]+)/i, // Windows Media Player
217
+ /(windows-media-player)\/([\w\.-]+)/i
218
+ ], [[NAME, /-/g, ' '], VERSION], [
219
+
220
+ /windows\/([\w\.-]+) upnp\/[\d\.]+ dlnadoc\/[\d\.]+ (home media server)/i,
221
+ // Windows Media Server
222
+ ], [VERSION, [NAME, 'Windows']], [
223
+
224
+ /(com\.riseupradioalarm)\/([\d\.]*)/i // RiseUP Radio Alarm
225
+ ], [NAME, VERSION], [
226
+
227
+ /(rad.io)\s([\d\.]+)/i, // Rad.io
228
+ /(radio.(?:de|at|fr))\s([\d\.]+)/i
229
+ ], [[NAME, 'rad.io'], VERSION]
230
+ ]
231
+ });
232
+
233
+ const Modules = Object.freeze({
234
+ browser : [
235
+ // Axios/jsdom/Scrapy
236
+ [/\b(axios|jsdom|scrapy)\/([\w\.]+)/i], [NAME, VERSION, [TYPE, 'module']]
237
+ ]
238
+ });
239
+
240
+ module.exports = {
241
+ Apps,
242
+ Bots,
243
+ CLIs,
244
+ ExtraDevices,
245
+ Emails,
246
+ MediaPlayers,
247
+ Modules
248
+ };