ua-parser-js 1.0.37 → 2.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.
Files changed (205) hide show
  1. package/LICENSE.md +616 -0
  2. package/README.md +251 -0
  3. package/dist/icons/color/LICENSE.md +3 -0
  4. package/dist/icons/color/browser/android-browser.svg +1 -0
  5. package/dist/icons/color/browser/avant.png +0 -0
  6. package/dist/icons/color/browser/basilisk.png +0 -0
  7. package/dist/icons/color/browser/basilisk.svg +1 -0
  8. package/dist/icons/color/browser/brave.png +0 -0
  9. package/dist/icons/color/browser/brave.svg +1 -0
  10. package/dist/icons/color/browser/chrome.png +0 -0
  11. package/dist/icons/color/browser/chrome.svg +1 -0
  12. package/dist/icons/color/browser/chromium.png +0 -0
  13. package/dist/icons/color/browser/chromium.svg +1 -0
  14. package/dist/icons/color/browser/coc-coc.png +0 -0
  15. package/dist/icons/color/browser/default.png +0 -0
  16. package/dist/icons/color/browser/default.svg +1 -0
  17. package/dist/icons/color/browser/dolphin.png +0 -0
  18. package/dist/icons/color/browser/edge.png +0 -0
  19. package/dist/icons/color/browser/edge.svg +1 -0
  20. package/dist/icons/color/browser/electron.png +0 -0
  21. package/dist/icons/color/browser/electron.svg +1 -0
  22. package/dist/icons/color/browser/falkon.png +0 -0
  23. package/dist/icons/color/browser/falkon.svg +1 -0
  24. package/dist/icons/color/browser/firefox-reality.png +0 -0
  25. package/dist/icons/color/browser/firefox-reality.svg +1 -0
  26. package/dist/icons/color/browser/firefox.png +0 -0
  27. package/dist/icons/color/browser/firefox.svg +1 -0
  28. package/dist/icons/color/browser/gsa.svg +9 -0
  29. package/dist/icons/color/browser/icecat.png +0 -0
  30. package/dist/icons/color/browser/ie.svg +6 -0
  31. package/dist/icons/color/browser/konqueror.png +0 -0
  32. package/dist/icons/color/browser/konqueror.svg +1 -0
  33. package/dist/icons/color/browser/maxthon.png +0 -0
  34. package/dist/icons/color/browser/midori.png +0 -0
  35. package/dist/icons/color/browser/midori.svg +1 -0
  36. package/dist/icons/color/browser/netsurf.png +0 -0
  37. package/dist/icons/color/browser/netsurf.svg +1 -0
  38. package/dist/icons/color/browser/opera-gx.png +0 -0
  39. package/dist/icons/color/browser/opera-gx.svg +1 -0
  40. package/dist/icons/color/browser/opera-mini.png +0 -0
  41. package/dist/icons/color/browser/opera-touch.png +0 -0
  42. package/dist/icons/color/browser/opera.png +0 -0
  43. package/dist/icons/color/browser/opera.svg +1 -0
  44. package/dist/icons/color/browser/palemoon.png +0 -0
  45. package/dist/icons/color/browser/puffin.png +0 -0
  46. package/dist/icons/color/browser/safari.png +0 -0
  47. package/dist/icons/color/browser/safari.svg +1 -0
  48. package/dist/icons/color/browser/samsung-internet.png +0 -0
  49. package/dist/icons/color/browser/samsung-internet.svg +1 -0
  50. package/dist/icons/color/browser/seamonkey.png +0 -0
  51. package/dist/icons/color/browser/silk.png +0 -0
  52. package/dist/icons/color/browser/sogou-mobile.png +0 -0
  53. package/dist/icons/color/browser/ucbrowser.png +0 -0
  54. package/dist/icons/color/browser/ucbrowser.svg +1 -0
  55. package/dist/icons/color/browser/vivaldi.png +0 -0
  56. package/dist/icons/color/browser/vivaldi.svg +1 -0
  57. package/dist/icons/color/browser/webkit.png +0 -0
  58. package/dist/icons/color/browser/webkit.svg +1 -0
  59. package/dist/icons/color/browser/yandex.png +0 -0
  60. package/dist/icons/color/os/centos.svg +1 -0
  61. package/dist/icons/mono/LICENSE.md +3 -0
  62. package/dist/icons/mono/browser/alipay.svg +1 -0
  63. package/dist/icons/mono/browser/android-browser.svg +1 -0
  64. package/dist/icons/mono/browser/avast-secure-browser.svg +1 -0
  65. package/dist/icons/mono/browser/baidu-browser.svg +1 -0
  66. package/dist/icons/mono/browser/brave.svg +1 -0
  67. package/dist/icons/mono/browser/chrome-headless.svg +1 -0
  68. package/dist/icons/mono/browser/chrome-webview.svg +1 -0
  69. package/dist/icons/mono/browser/chrome.svg +1 -0
  70. package/dist/icons/mono/browser/chromium.svg +1 -0
  71. package/dist/icons/mono/browser/duckduckgo.svg +1 -0
  72. package/dist/icons/mono/browser/edge.svg +1 -0
  73. package/dist/icons/mono/browser/electron.svg +1 -0
  74. package/dist/icons/mono/browser/facebook.svg +1 -0
  75. package/dist/icons/mono/browser/firefox-focus.svg +1 -0
  76. package/dist/icons/mono/browser/firefox-reality.svg +1 -0
  77. package/dist/icons/mono/browser/firefox.svg +1 -0
  78. package/dist/icons/mono/browser/gsa.svg +1 -0
  79. package/dist/icons/mono/browser/huawei-browser.svg +1 -0
  80. package/dist/icons/mono/browser/icecat.svg +1 -0
  81. package/dist/icons/mono/browser/ie.svg +1 -0
  82. package/dist/icons/mono/browser/instagram.svg +1 -0
  83. package/dist/icons/mono/browser/jasmine.svg +1 -0
  84. package/dist/icons/mono/browser/kakaotalk.svg +1 -0
  85. package/dist/icons/mono/browser/klarna.svg +1 -0
  86. package/dist/icons/mono/browser/line.svg +1 -0
  87. package/dist/icons/mono/browser/linkedin.svg +1 -0
  88. package/dist/icons/mono/browser/miui-browser.svg +1 -0
  89. package/dist/icons/mono/browser/mobile-chrome.svg +1 -0
  90. package/dist/icons/mono/browser/mobile-firefox.svg +1 -0
  91. package/dist/icons/mono/browser/mobile-safari.svg +1 -0
  92. package/dist/icons/mono/browser/mozilla.svg +1 -0
  93. package/dist/icons/mono/browser/naver.svg +1 -0
  94. package/dist/icons/mono/browser/nokia-browser.svg +1 -0
  95. package/dist/icons/mono/browser/oculus-browser.svg +1 -0
  96. package/dist/icons/mono/browser/opera-coast.svg +1 -0
  97. package/dist/icons/mono/browser/opera-gx.svg +1 -0
  98. package/dist/icons/mono/browser/opera-mini.svg +1 -0
  99. package/dist/icons/mono/browser/opera-mobi.svg +1 -0
  100. package/dist/icons/mono/browser/opera-tablet.svg +1 -0
  101. package/dist/icons/mono/browser/opera-touch.svg +1 -0
  102. package/dist/icons/mono/browser/opera.svg +1 -0
  103. package/dist/icons/mono/browser/qqbrowser.svg +1 -0
  104. package/dist/icons/mono/browser/qqbrowserlite.svg +1 -0
  105. package/dist/icons/mono/browser/safari.svg +1 -0
  106. package/dist/icons/mono/browser/sailfish-browser.svg +1 -0
  107. package/dist/icons/mono/browser/samsung-internet.svg +1 -0
  108. package/dist/icons/mono/browser/smart-lenovo-browser.svg +1 -0
  109. package/dist/icons/mono/browser/snapchat.svg +1 -0
  110. package/dist/icons/mono/browser/sogou-explorer.svg +1 -0
  111. package/dist/icons/mono/browser/sogou-mobile.svg +1 -0
  112. package/dist/icons/mono/browser/tesla.svg +1 -0
  113. package/dist/icons/mono/browser/tiktok.svg +1 -0
  114. package/dist/icons/mono/browser/twitter.svg +1 -0
  115. package/dist/icons/mono/browser/vivaldi.svg +1 -0
  116. package/dist/icons/mono/browser/vivo-browser.svg +1 -0
  117. package/dist/icons/mono/browser/wechat.svg +1 -0
  118. package/dist/icons/mono/browser/weibo.svg +1 -0
  119. package/dist/icons/mono/browser/yandex.svg +1 -0
  120. package/dist/icons/mono/device/acer.svg +1 -0
  121. package/dist/icons/mono/device/amazon.svg +1 -0
  122. package/dist/icons/mono/device/apple.svg +1 -0
  123. package/dist/icons/mono/device/asus.svg +1 -0
  124. package/dist/icons/mono/device/att.svg +1 -0
  125. package/dist/icons/mono/device/blackberry.svg +1 -0
  126. package/dist/icons/mono/device/dell.svg +1 -0
  127. package/dist/icons/mono/device/facebook.svg +1 -0
  128. package/dist/icons/mono/device/fairphone.svg +1 -0
  129. package/dist/icons/mono/device/google.svg +1 -0
  130. package/dist/icons/mono/device/hp.svg +1 -0
  131. package/dist/icons/mono/device/huawei.svg +1 -0
  132. package/dist/icons/mono/device/lenovo.svg +1 -0
  133. package/dist/icons/mono/device/lg.svg +1 -0
  134. package/dist/icons/mono/device/meizu.svg +1 -0
  135. package/dist/icons/mono/device/microsoft.svg +1 -0
  136. package/dist/icons/mono/device/motorola.svg +1 -0
  137. package/dist/icons/mono/device/nintendo.svg +1 -0
  138. package/dist/icons/mono/device/nokia.svg +1 -0
  139. package/dist/icons/mono/device/nvidia.svg +1 -0
  140. package/dist/icons/mono/device/oneplus.svg +1 -0
  141. package/dist/icons/mono/device/oppo.svg +1 -0
  142. package/dist/icons/mono/device/panasonic.svg +1 -0
  143. package/dist/icons/mono/device/roku.svg +1 -0
  144. package/dist/icons/mono/device/samsung.svg +1 -0
  145. package/dist/icons/mono/device/siemens.svg +1 -0
  146. package/dist/icons/mono/device/sony.svg +1 -0
  147. package/dist/icons/mono/device/tesla.svg +1 -0
  148. package/dist/icons/mono/device/vivo.svg +1 -0
  149. package/dist/icons/mono/device/vodafone.svg +1 -0
  150. package/dist/icons/mono/device/xiaomi.svg +1 -0
  151. package/dist/icons/mono/device/zebra.svg +1 -0
  152. package/dist/icons/mono/os/android.svg +1 -0
  153. package/dist/icons/mono/os/arch.svg +1 -0
  154. package/dist/icons/mono/os/blackberry.svg +1 -0
  155. package/dist/icons/mono/os/centos.svg +1 -0
  156. package/dist/icons/mono/os/chrome-os.svg +1 -0
  157. package/dist/icons/mono/os/chromecast.svg +1 -0
  158. package/dist/icons/mono/os/debian.svg +1 -0
  159. package/dist/icons/mono/os/deepin.svg +1 -0
  160. package/dist/icons/mono/os/elementary-os.svg +1 -0
  161. package/dist/icons/mono/os/fedora.svg +1 -0
  162. package/dist/icons/mono/os/firefox.svg +1 -0
  163. package/dist/icons/mono/os/freebsd.svg +1 -0
  164. package/dist/icons/mono/os/gentoo.svg +1 -0
  165. package/dist/icons/mono/os/gnu.svg +1 -0
  166. package/dist/icons/mono/os/harmonyos.svg +1 -0
  167. package/dist/icons/mono/os/ios.svg +1 -0
  168. package/dist/icons/mono/os/kaios.svg +1 -0
  169. package/dist/icons/mono/os/linux.svg +1 -0
  170. package/dist/icons/mono/os/macos.svg +1 -0
  171. package/dist/icons/mono/os/manjaro.svg +1 -0
  172. package/dist/icons/mono/os/mint.svg +1 -0
  173. package/dist/icons/mono/os/netbsd.svg +1 -0
  174. package/dist/icons/mono/os/nintendo.svg +1 -0
  175. package/dist/icons/mono/os/openbsd.svg +1 -0
  176. package/dist/icons/mono/os/playstation.svg +1 -0
  177. package/dist/icons/mono/os/raspbian.svg +1 -0
  178. package/dist/icons/mono/os/redhat.svg +1 -0
  179. package/dist/icons/mono/os/sailfish.svg +1 -0
  180. package/dist/icons/mono/os/slackware.svg +1 -0
  181. package/dist/icons/mono/os/suse.svg +1 -0
  182. package/dist/icons/mono/os/ubuntu.svg +1 -0
  183. package/dist/icons/mono/os/windows.svg +1 -0
  184. package/dist/icons/mono/os/xbox.svg +1 -0
  185. package/dist/ua-parser.min.js +4 -4
  186. package/dist/ua-parser.min.mjs +4 -0
  187. package/dist/ua-parser.pack.js +4 -4
  188. package/dist/ua-parser.pack.mjs +4 -0
  189. package/package.json +86 -36
  190. package/script/cli.js +4 -0
  191. package/src/enums/ua-parser-enums.d.ts +366 -0
  192. package/src/enums/ua-parser-enums.js +393 -0
  193. package/src/enums/ua-parser-enums.mjs +397 -0
  194. package/src/extensions/ua-parser-extensions.d.ts +16 -0
  195. package/src/extensions/ua-parser-extensions.js +366 -0
  196. package/src/extensions/ua-parser-extensions.mjs +370 -0
  197. package/src/helpers/ua-parser-helpers.d.ts +27 -0
  198. package/src/helpers/ua-parser-helpers.js +137 -0
  199. package/src/helpers/ua-parser-helpers.mjs +141 -0
  200. package/src/main/ua-parser.d.ts +113 -0
  201. package/src/main/ua-parser.js +1439 -0
  202. package/src/main/ua-parser.mjs +1397 -0
  203. package/license.md +0 -21
  204. package/readme.md +0 -385
  205. package/src/ua-parser.js +0 -946
@@ -0,0 +1,1439 @@
1
+ /////////////////////////////////////////////////////////////////////////////////
2
+ /* UAParser.js v2.0.2
3
+ Copyright © 2012-2024 Faisal Salman <f@faisalman.com>
4
+ AGPLv3 License *//*
5
+ Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data.
6
+ Supports browser & node.js environment.
7
+ Demo : https://uaparser.dev
8
+ Source : https://github.com/faisalman/ua-parser-js */
9
+ /////////////////////////////////////////////////////////////////////////////////
10
+
11
+ /* jshint esversion: 3 */
12
+ /* globals window */
13
+
14
+ (function (window, undefined) {
15
+
16
+ 'use strict';
17
+
18
+ //////////////
19
+ // Constants
20
+ /////////////
21
+
22
+ var LIBVERSION = '2.0.2',
23
+ UA_MAX_LENGTH = 500,
24
+ USER_AGENT = 'user-agent',
25
+ EMPTY = '',
26
+ UNKNOWN = '?',
27
+
28
+ // typeof
29
+ FUNC_TYPE = 'function',
30
+ UNDEF_TYPE = 'undefined',
31
+ OBJ_TYPE = 'object',
32
+ STR_TYPE = 'string',
33
+
34
+ // properties
35
+ UA_BROWSER = 'browser',
36
+ UA_CPU = 'cpu',
37
+ UA_DEVICE = 'device',
38
+ UA_ENGINE = 'engine',
39
+ UA_OS = 'os',
40
+ UA_RESULT = 'result',
41
+
42
+ NAME = 'name',
43
+ TYPE = 'type',
44
+ VENDOR = 'vendor',
45
+ VERSION = 'version',
46
+ ARCHITECTURE= 'architecture',
47
+ MAJOR = 'major',
48
+ MODEL = 'model',
49
+
50
+ // device types
51
+ CONSOLE = 'console',
52
+ MOBILE = 'mobile',
53
+ TABLET = 'tablet',
54
+ SMARTTV = 'smarttv',
55
+ WEARABLE = 'wearable',
56
+ XR = 'xr',
57
+ EMBEDDED = 'embedded',
58
+
59
+ // browser types
60
+ INAPP = 'inapp',
61
+
62
+ // client hints
63
+ BRANDS = 'brands',
64
+ FORMFACTORS = 'formFactors',
65
+ FULLVERLIST = 'fullVersionList',
66
+ PLATFORM = 'platform',
67
+ PLATFORMVER = 'platformVersion',
68
+ BITNESS = 'bitness',
69
+ CH_HEADER = 'sec-ch-ua',
70
+ CH_HEADER_FULL_VER_LIST = CH_HEADER + '-full-version-list',
71
+ CH_HEADER_ARCH = CH_HEADER + '-arch',
72
+ CH_HEADER_BITNESS = CH_HEADER + '-' + BITNESS,
73
+ CH_HEADER_FORM_FACTORS = CH_HEADER + '-form-factors',
74
+ CH_HEADER_MOBILE = CH_HEADER + '-' + MOBILE,
75
+ CH_HEADER_MODEL = CH_HEADER + '-' + MODEL,
76
+ CH_HEADER_PLATFORM = CH_HEADER + '-' + PLATFORM,
77
+ CH_HEADER_PLATFORM_VER = CH_HEADER_PLATFORM + '-version',
78
+ CH_ALL_VALUES = [BRANDS, FULLVERLIST, MOBILE, MODEL, PLATFORM, PLATFORMVER, ARCHITECTURE, FORMFACTORS, BITNESS],
79
+
80
+ // device vendors
81
+ AMAZON = 'Amazon',
82
+ APPLE = 'Apple',
83
+ ASUS = 'ASUS',
84
+ BLACKBERRY = 'BlackBerry',
85
+ GOOGLE = 'Google',
86
+ HUAWEI = 'Huawei',
87
+ LENOVO = 'Lenovo',
88
+ HONOR = 'Honor',
89
+ LG = 'LG',
90
+ MICROSOFT = 'Microsoft',
91
+ MOTOROLA = 'Motorola',
92
+ NVIDIA = 'Nvidia',
93
+ ONEPLUS = 'OnePlus',
94
+ OPPO = 'OPPO',
95
+ SAMSUNG = 'Samsung',
96
+ SHARP = 'Sharp',
97
+ SONY = 'Sony',
98
+ XIAOMI = 'Xiaomi',
99
+ ZEBRA = 'Zebra',
100
+
101
+ // browsers
102
+ CHROME = 'Chrome',
103
+ CHROMIUM = 'Chromium',
104
+ CHROMECAST = 'Chromecast',
105
+ EDGE = 'Edge',
106
+ FIREFOX = 'Firefox',
107
+ OPERA = 'Opera',
108
+ FACEBOOK = 'Facebook',
109
+ SOGOU = 'Sogou',
110
+
111
+ PREFIX_MOBILE = 'Mobile ',
112
+ SUFFIX_BROWSER = ' Browser',
113
+
114
+ // os
115
+ WINDOWS = 'Windows';
116
+
117
+ var isWindow = typeof window !== UNDEF_TYPE,
118
+ NAVIGATOR = (isWindow && window.navigator) ?
119
+ window.navigator :
120
+ undefined,
121
+ NAVIGATOR_UADATA = (NAVIGATOR && NAVIGATOR.userAgentData) ?
122
+ NAVIGATOR.userAgentData :
123
+ undefined;
124
+
125
+ ///////////
126
+ // Helper
127
+ //////////
128
+
129
+ var extend = function (defaultRgx, extensions) {
130
+ var mergedRgx = {};
131
+ var extraRgx = extensions;
132
+ if (!isExtensions(extensions)) {
133
+ extraRgx = {};
134
+ for (var i in extensions) {
135
+ for (var j in extensions[i]) {
136
+ extraRgx[j] = extensions[i][j].concat(extraRgx[j] ? extraRgx[j] : []);
137
+ }
138
+ }
139
+ }
140
+ for (var k in defaultRgx) {
141
+ mergedRgx[k] = extraRgx[k] && extraRgx[k].length % 2 === 0 ? extraRgx[k].concat(defaultRgx[k]) : defaultRgx[k];
142
+ }
143
+ return mergedRgx;
144
+ },
145
+ enumerize = function (arr) {
146
+ var enums = {};
147
+ for (var i=0; i<arr.length; i++) {
148
+ enums[arr[i].toUpperCase()] = arr[i];
149
+ }
150
+ return enums;
151
+ },
152
+ has = function (str1, str2) {
153
+ if (typeof str1 === OBJ_TYPE && str1.length > 0) {
154
+ for (var i in str1) {
155
+ if (lowerize(str1[i]) == lowerize(str2)) return true;
156
+ }
157
+ return false;
158
+ }
159
+ return isString(str1) ? lowerize(str2).indexOf(lowerize(str1)) !== -1 : false;
160
+ },
161
+ isExtensions = function (obj, deep) {
162
+ for (var prop in obj) {
163
+ return /^(browser|cpu|device|engine|os)$/.test(prop) || (deep ? isExtensions(obj[prop]) : false);
164
+ }
165
+ },
166
+ isString = function (val) {
167
+ return typeof val === STR_TYPE;
168
+ },
169
+ itemListToArray = function (header) {
170
+ if (!header) return undefined;
171
+ var arr = [];
172
+ var tokens = strip(/\\?\"/g, header).split(',');
173
+ for (var i = 0; i < tokens.length; i++) {
174
+ if (tokens[i].indexOf(';') > -1) {
175
+ var token = trim(tokens[i]).split(';v=');
176
+ arr[i] = { brand : token[0], version : token[1] };
177
+ } else {
178
+ arr[i] = trim(tokens[i]);
179
+ }
180
+ }
181
+ return arr;
182
+ },
183
+ lowerize = function (str) {
184
+ return isString(str) ? str.toLowerCase() : str;
185
+ },
186
+ majorize = function (version) {
187
+ return isString(version) ? strip(/[^\d\.]/g, version).split('.')[0] : undefined;
188
+ },
189
+ setProps = function (arr) {
190
+ for (var i in arr) {
191
+ var propName = arr[i];
192
+ if (typeof propName == OBJ_TYPE && propName.length == 2) {
193
+ this[propName[0]] = propName[1];
194
+ } else {
195
+ this[propName] = undefined;
196
+ }
197
+ }
198
+ return this;
199
+ },
200
+ strip = function (pattern, str) {
201
+ return isString(str) ? str.replace(pattern, EMPTY) : str;
202
+ },
203
+ stripQuotes = function (str) {
204
+ return strip(/\\?\"/g, str);
205
+ },
206
+ trim = function (str, len) {
207
+ if (isString(str)) {
208
+ str = strip(/^\s\s*/, str);
209
+ return typeof len === UNDEF_TYPE ? str : str.substring(0, UA_MAX_LENGTH);
210
+ }
211
+ };
212
+
213
+ ///////////////
214
+ // Map helper
215
+ //////////////
216
+
217
+ var rgxMapper = function (ua, arrays) {
218
+
219
+ if(!ua || !arrays) return;
220
+
221
+ var i = 0, j, k, p, q, matches, match;
222
+
223
+ // loop through all regexes maps
224
+ while (i < arrays.length && !matches) {
225
+
226
+ var regex = arrays[i], // even sequence (0,2,4,..)
227
+ props = arrays[i + 1]; // odd sequence (1,3,5,..)
228
+ j = k = 0;
229
+
230
+ // try matching uastring with regexes
231
+ while (j < regex.length && !matches) {
232
+
233
+ if (!regex[j]) { break; }
234
+ matches = regex[j++].exec(ua);
235
+
236
+ if (!!matches) {
237
+ for (p = 0; p < props.length; p++) {
238
+ match = matches[++k];
239
+ q = props[p];
240
+ // check if given property is actually array
241
+ if (typeof q === OBJ_TYPE && q.length > 0) {
242
+ if (q.length === 2) {
243
+ if (typeof q[1] == FUNC_TYPE) {
244
+ // assign modified match
245
+ this[q[0]] = q[1].call(this, match);
246
+ } else {
247
+ // assign given value, ignore regex match
248
+ this[q[0]] = q[1];
249
+ }
250
+ } else if (q.length === 3) {
251
+ // check whether function or regex
252
+ if (typeof q[1] === FUNC_TYPE && !(q[1].exec && q[1].test)) {
253
+ // call function (usually string mapper)
254
+ this[q[0]] = match ? q[1].call(this, match, q[2]) : undefined;
255
+ } else {
256
+ // sanitize match using given regex
257
+ this[q[0]] = match ? match.replace(q[1], q[2]) : undefined;
258
+ }
259
+ } else if (q.length === 4) {
260
+ this[q[0]] = match ? q[3].call(this, match.replace(q[1], q[2])) : undefined;
261
+ }
262
+ } else {
263
+ this[q] = match ? match : undefined;
264
+ }
265
+ }
266
+ }
267
+ }
268
+ i += 2;
269
+ }
270
+ },
271
+
272
+ strMapper = function (str, map) {
273
+
274
+ for (var i in map) {
275
+ // check if current value is array
276
+ if (typeof map[i] === OBJ_TYPE && map[i].length > 0) {
277
+ for (var j = 0; j < map[i].length; j++) {
278
+ if (has(map[i][j], str)) {
279
+ return (i === UNKNOWN) ? undefined : i;
280
+ }
281
+ }
282
+ } else if (has(map[i], str)) {
283
+ return (i === UNKNOWN) ? undefined : i;
284
+ }
285
+ }
286
+ return map.hasOwnProperty('*') ? map['*'] : str;
287
+ };
288
+
289
+ ///////////////
290
+ // String map
291
+ //////////////
292
+
293
+ var windowsVersionMap = {
294
+ 'ME' : '4.90',
295
+ 'NT 3.11' : 'NT3.51',
296
+ 'NT 4.0' : 'NT4.0',
297
+ '2000' : 'NT 5.0',
298
+ 'XP' : ['NT 5.1', 'NT 5.2'],
299
+ 'Vista' : 'NT 6.0',
300
+ '7' : 'NT 6.1',
301
+ '8' : 'NT 6.2',
302
+ '8.1' : 'NT 6.3',
303
+ '10' : ['NT 6.4', 'NT 10.0'],
304
+ 'RT' : 'ARM'
305
+ },
306
+
307
+ formFactorsMap = {
308
+ 'embedded' : 'Automotive',
309
+ 'mobile' : 'Mobile',
310
+ 'tablet' : ['Tablet', 'EInk'],
311
+ 'smarttv' : 'TV',
312
+ 'wearable' : 'Watch',
313
+ 'xr' : ['VR', 'XR'],
314
+ '?' : ['Desktop', 'Unknown'],
315
+ '*' : undefined
316
+ };
317
+
318
+ //////////////
319
+ // Regex map
320
+ /////////////
321
+
322
+ var defaultRegexes = {
323
+
324
+ browser : [[
325
+
326
+ // Most common regardless engine
327
+ /\b(?:crmo|crios)\/([\w\.]+)/i // Chrome for Android/iOS
328
+ ], [VERSION, [NAME, PREFIX_MOBILE + 'Chrome']], [
329
+ /edg(?:e|ios|a)?\/([\w\.]+)/i // Microsoft Edge
330
+ ], [VERSION, [NAME, 'Edge']], [
331
+
332
+ // Presto based
333
+ /(opera mini)\/([-\w\.]+)/i, // Opera Mini
334
+ /(opera [mobiletab]{3,6})\b.+version\/([-\w\.]+)/i, // Opera Mobi/Tablet
335
+ /(opera)(?:.+version\/|[\/ ]+)([\w\.]+)/i // Opera
336
+ ], [NAME, VERSION], [
337
+ /opios[\/ ]+([\w\.]+)/i // Opera mini on iphone >= 8.0
338
+ ], [VERSION, [NAME, OPERA+' Mini']], [
339
+ /\bop(?:rg)?x\/([\w\.]+)/i // Opera GX
340
+ ], [VERSION, [NAME, OPERA+' GX']], [
341
+ /\bopr\/([\w\.]+)/i // Opera Webkit
342
+ ], [VERSION, [NAME, OPERA]], [
343
+
344
+ // Mixed
345
+ /\bb[ai]*d(?:uhd|[ub]*[aekoprswx]{5,6})[\/ ]?([\w\.]+)/i // Baidu
346
+ ], [VERSION, [NAME, 'Baidu']], [
347
+ /\b(?:mxbrowser|mxios|myie2)\/?([-\w\.]*)\b/i // Maxthon
348
+ ], [VERSION, [NAME, 'Maxthon']], [
349
+ /(kindle)\/([\w\.]+)/i, // Kindle
350
+ /(lunascape|maxthon|netfront|jasmine|blazer|sleipnir)[\/ ]?([\w\.]*)/i,
351
+ // Lunascape/Maxthon/Netfront/Jasmine/Blazer/Sleipnir
352
+ // Trident based
353
+ /(avant|iemobile|slim(?:browser|boat|jet))[\/ ]?([\d\.]*)/i, // Avant/IEMobile/SlimBrowser/SlimBoat/Slimjet
354
+ /(?:ms|\()(ie) ([\w\.]+)/i, // Internet Explorer
355
+
356
+ // Blink/Webkit/KHTML based // Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS/Bowser/QupZilla/Falkon
357
+ /(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,
358
+ // Rekonq/Puffin/Brave/Whale/QQBrowserLite/QQ//Vivaldi/DuckDuckGo/Klar/Helio/Dragon
359
+ /(heytap|ovi|115)browser\/([\d\.]+)/i, // HeyTap/Ovi/115
360
+ /(weibo)__([\d\.]+)/i // Weibo
361
+ ], [NAME, VERSION], [
362
+ /quark(?:pc)?\/([-\w\.]+)/i // Quark
363
+ ], [VERSION, [NAME, 'Quark']], [
364
+ /\bddg\/([\w\.]+)/i // DuckDuckGo
365
+ ], [VERSION, [NAME, 'DuckDuckGo']], [
366
+ /(?:\buc? ?browser|(?:juc.+)ucweb)[\/ ]?([\w\.]+)/i // UCBrowser
367
+ ], [VERSION, [NAME, 'UCBrowser']], [
368
+ /microm.+\bqbcore\/([\w\.]+)/i, // WeChat Desktop for Windows Built-in Browser
369
+ /\bqbcore\/([\w\.]+).+microm/i,
370
+ /micromessenger\/([\w\.]+)/i // WeChat
371
+ ], [VERSION, [NAME, 'WeChat']], [
372
+ /konqueror\/([\w\.]+)/i // Konqueror
373
+ ], [VERSION, [NAME, 'Konqueror']], [
374
+ /trident.+rv[: ]([\w\.]{1,9})\b.+like gecko/i // IE11
375
+ ], [VERSION, [NAME, 'IE']], [
376
+ /ya(?:search)?browser\/([\w\.]+)/i // Yandex
377
+ ], [VERSION, [NAME, 'Yandex']], [
378
+ /slbrowser\/([\w\.]+)/i // Smart Lenovo Browser
379
+ ], [VERSION, [NAME, 'Smart ' + LENOVO + SUFFIX_BROWSER]], [
380
+ /(avast|avg)\/([\w\.]+)/i // Avast/AVG Secure Browser
381
+ ], [[NAME, /(.+)/, '$1 Secure' + SUFFIX_BROWSER], VERSION], [
382
+ /\bfocus\/([\w\.]+)/i // Firefox Focus
383
+ ], [VERSION, [NAME, FIREFOX+' Focus']], [
384
+ /\bopt\/([\w\.]+)/i // Opera Touch
385
+ ], [VERSION, [NAME, OPERA+' Touch']], [
386
+ /coc_coc\w+\/([\w\.]+)/i // Coc Coc Browser
387
+ ], [VERSION, [NAME, 'Coc Coc']], [
388
+ /dolfin\/([\w\.]+)/i // Dolphin
389
+ ], [VERSION, [NAME, 'Dolphin']], [
390
+ /coast\/([\w\.]+)/i // Opera Coast
391
+ ], [VERSION, [NAME, OPERA+' Coast']], [
392
+ /miuibrowser\/([\w\.]+)/i // MIUI Browser
393
+ ], [VERSION, [NAME, 'MIUI' + SUFFIX_BROWSER]], [
394
+ /fxios\/([\w\.-]+)/i // Firefox for iOS
395
+ ], [VERSION, [NAME, PREFIX_MOBILE + FIREFOX]], [
396
+ /\bqihoobrowser\/?([\w\.]*)/i // 360
397
+ ], [VERSION, [NAME, '360']], [
398
+ /\b(qq)\/([\w\.]+)/i // QQ
399
+ ], [[NAME, /(.+)/, '$1Browser'], VERSION], [
400
+ /(oculus|sailfish|huawei|vivo|pico)browser\/([\w\.]+)/i
401
+ ], [[NAME, /(.+)/, '$1' + SUFFIX_BROWSER], VERSION], [ // Oculus/Sailfish/HuaweiBrowser/VivoBrowser/PicoBrowser
402
+ /samsungbrowser\/([\w\.]+)/i // Samsung Internet
403
+ ], [VERSION, [NAME, SAMSUNG + ' Internet']], [
404
+ /metasr[\/ ]?([\d\.]+)/i // Sogou Explorer
405
+ ], [VERSION, [NAME, SOGOU + ' Explorer']], [
406
+ /(sogou)mo\w+\/([\d\.]+)/i // Sogou Mobile
407
+ ], [[NAME, SOGOU + ' Mobile'], VERSION], [
408
+ /(electron)\/([\w\.]+) safari/i, // Electron-based App
409
+ /(tesla)(?: qtcarbrowser|\/(20\d\d\.[-\w\.]+))/i, // Tesla
410
+ /m?(qqbrowser|2345(?=browser|chrome|explorer))\w*[\/ ]?v?([\w\.]+)/i // QQ/2345
411
+ ], [NAME, VERSION], [
412
+ /(lbbrowser|rekonq)/i // LieBao Browser/Rekonq
413
+ ], [NAME], [
414
+ /ome\/([\w\.]+) \w* ?(iron) saf/i, // Iron
415
+ /ome\/([\w\.]+).+qihu (360)[es]e/i // 360
416
+ ], [VERSION, NAME], [
417
+
418
+ // WebView
419
+ /((?:fban\/fbios|fb_iab\/fb4a)(?!.+fbav)|;fbav\/([\w\.]+);)/i // Facebook App for iOS & Android
420
+ ], [[NAME, FACEBOOK], VERSION, [TYPE, INAPP]], [
421
+ /(Klarna)\/([\w\.]+)/i, // Klarna Shopping Browser for iOS & Android
422
+ /(kakao(?:talk|story))[\/ ]([\w\.]+)/i, // Kakao App
423
+ /(naver)\(.*?(\d+\.[\w\.]+).*\)/i, // Naver InApp
424
+ /(daum)apps[\/ ]([\w\.]+)/i, // Daum App
425
+ /safari (line)\/([\w\.]+)/i, // Line App for iOS
426
+ /\b(line)\/([\w\.]+)\/iab/i, // Line App for Android
427
+ /(alipay)client\/([\w\.]+)/i, // Alipay
428
+ /(twitter)(?:and| f.+e\/([\w\.]+))/i, // Twitter
429
+ /(instagram|snapchat)[\/ ]([-\w\.]+)/i // Instagram/Snapchat
430
+ ], [NAME, VERSION, [TYPE, INAPP]], [
431
+ /\bgsa\/([\w\.]+) .*safari\//i // Google Search Appliance on iOS
432
+ ], [VERSION, [NAME, 'GSA'], [TYPE, INAPP]], [
433
+ /musical_ly(?:.+app_?version\/|_)([\w\.]+)/i // TikTok
434
+ ], [VERSION, [NAME, 'TikTok'], [TYPE, INAPP]], [
435
+ /\[(linkedin)app\]/i // LinkedIn App for iOS & Android
436
+ ], [NAME, [TYPE, INAPP]], [
437
+
438
+ /(chromium)[\/ ]([-\w\.]+)/i // Chromium
439
+ ], [NAME, VERSION], [
440
+
441
+ /headlesschrome(?:\/([\w\.]+)| )/i // Chrome Headless
442
+ ], [VERSION, [NAME, CHROME+' Headless']], [
443
+
444
+ / wv\).+(chrome)\/([\w\.]+)/i // Chrome WebView
445
+ ], [[NAME, CHROME+' WebView'], VERSION], [
446
+
447
+ /droid.+ version\/([\w\.]+)\b.+(?:mobile safari|safari)/i // Android Browser
448
+ ], [VERSION, [NAME, 'Android' + SUFFIX_BROWSER]], [
449
+
450
+ /chrome\/([\w\.]+) mobile/i // Chrome Mobile
451
+ ], [VERSION, [NAME, PREFIX_MOBILE + 'Chrome']], [
452
+
453
+ /(chrome|omniweb|arora|[tizenoka]{5} ?browser)\/v?([\w\.]+)/i // Chrome/OmniWeb/Arora/Tizen/Nokia
454
+ ], [NAME, VERSION], [
455
+
456
+ /version\/([\w\.\,]+) .*mobile(?:\/\w+ | ?)safari/i // Safari Mobile
457
+ ], [VERSION, [NAME, PREFIX_MOBILE + 'Safari']], [
458
+ /iphone .*mobile(?:\/\w+ | ?)safari/i
459
+ ], [[NAME, PREFIX_MOBILE + 'Safari']], [
460
+ /version\/([\w\.\,]+) .*(safari)/i // Safari
461
+ ], [VERSION, NAME], [
462
+ /webkit.+?(mobile ?safari|safari)(\/[\w\.]+)/i // Safari < 3.0
463
+ ], [NAME, [VERSION, '1']], [
464
+
465
+ /(webkit|khtml)\/([\w\.]+)/i
466
+ ], [NAME, VERSION], [
467
+
468
+ // Gecko based
469
+ /(?:mobile|tablet);.*(firefox)\/([\w\.-]+)/i // Firefox Mobile
470
+ ], [[NAME, PREFIX_MOBILE + FIREFOX], VERSION], [
471
+ /(navigator|netscape\d?)\/([-\w\.]+)/i // Netscape
472
+ ], [[NAME, 'Netscape'], VERSION], [
473
+ /(wolvic|librewolf)\/([\w\.]+)/i // Wolvic/LibreWolf
474
+ ], [NAME, VERSION], [
475
+ /mobile vr; rv:([\w\.]+)\).+firefox/i // Firefox Reality
476
+ ], [VERSION, [NAME, FIREFOX+' Reality']], [
477
+ /ekiohf.+(flow)\/([\w\.]+)/i, // Flow
478
+ /(swiftfox)/i, // Swiftfox
479
+ /(icedragon|iceweasel|camino|chimera|fennec|maemo browser|minimo|conkeror)[\/ ]?([\w\.\+]+)/i,
480
+ // IceDragon/Iceweasel/Camino/Chimera/Fennec/Maemo/Minimo/Conkeror
481
+ /(seamonkey|k-meleon|icecat|iceape|firebird|phoenix|palemoon|basilisk|waterfox)\/([-\w\.]+)$/i,
482
+ // Firefox/SeaMonkey/K-Meleon/IceCat/IceApe/Firebird/Phoenix
483
+ /(firefox)\/([\w\.]+)/i, // Other Firefox-based
484
+ /(mozilla)\/([\w\.]+) .+rv\:.+gecko\/\d+/i, // Mozilla
485
+
486
+ // Other
487
+ /(amaya|dillo|doris|icab|ladybird|lynx|mosaic|netsurf|obigo|polaris|w3m|(?:go|ice|up)[\. ]?browser)[-\/ ]?v?([\w\.]+)/i,
488
+ // Polaris/Lynx/Dillo/iCab/Doris/Amaya/w3m/NetSurf/Obigo/Mosaic/Go/ICE/UP.Browser/Ladybird
489
+ /\b(links) \(([\w\.]+)/i // Links
490
+ ], [NAME, [VERSION, /_/g, '.']], [
491
+
492
+ /(cobalt)\/([\w\.]+)/i // Cobalt
493
+ ], [NAME, [VERSION, /[^\d\.]+./, EMPTY]]
494
+ ],
495
+
496
+ cpu : [[
497
+
498
+ /\b((amd|x|x86[-_]?|wow|win)64)\b/i // AMD64 (x64)
499
+ ], [[ARCHITECTURE, 'amd64']], [
500
+
501
+ /(ia32(?=;))/i, // IA32 (quicktime)
502
+ /\b((i[346]|x)86)(pc)?\b/i // IA32 (x86)
503
+ ], [[ARCHITECTURE, 'ia32']], [
504
+
505
+ /\b(aarch64|arm(v?[89]e?l?|_?64))\b/i // ARM64
506
+ ], [[ARCHITECTURE, 'arm64']], [
507
+
508
+ /\b(arm(v[67])?ht?n?[fl]p?)\b/i // ARMHF
509
+ ], [[ARCHITECTURE, 'armhf']], [
510
+
511
+ // PocketPC mistakenly identified as PowerPC
512
+ /( (ce|mobile); ppc;|\/[\w\.]+arm\b)/i
513
+ ], [[ARCHITECTURE, 'arm']], [
514
+
515
+ /((ppc|powerpc)(64)?)( mac|;|\))/i // PowerPC
516
+ ], [[ARCHITECTURE, /ower/, EMPTY, lowerize]], [
517
+
518
+ / sun4\w[;\)]/i // SPARC
519
+ ], [[ARCHITECTURE, 'sparc']], [
520
+
521
+ /\b(avr32|ia64(?=;)|68k(?=\))|\barm(?=v([1-7]|[5-7]1)l?|;|eabi)|(irix|mips|sparc)(64)?\b|pa-risc)/i
522
+ // IA64, 68K, ARM/64, AVR/32, IRIX/64, MIPS/64, SPARC/64, PA-RISC
523
+ ], [[ARCHITECTURE, lowerize]]
524
+ ],
525
+
526
+ device : [[
527
+
528
+ //////////////////////////
529
+ // MOBILES & TABLETS
530
+ /////////////////////////
531
+
532
+ // Samsung
533
+ /\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
534
+ ], [MODEL, [VENDOR, SAMSUNG], [TYPE, TABLET]], [
535
+ /\b((?:s[cgp]h|gt|sm)-(?![lr])\w+|sc[g-]?[\d]+a?|galaxy nexus)/i,
536
+ /samsung[- ]((?!sm-[lr])[-\w]+)/i,
537
+ /sec-(sgh\w+)/i
538
+ ], [MODEL, [VENDOR, SAMSUNG], [TYPE, MOBILE]], [
539
+
540
+ // Apple
541
+ /(?:\/|\()(ip(?:hone|od)[\w, ]*)(?:\/|;)/i // iPod/iPhone
542
+ ], [MODEL, [VENDOR, APPLE], [TYPE, MOBILE]], [
543
+ /\((ipad);[-\w\),; ]+apple/i, // iPad
544
+ /applecoremedia\/[\w\.]+ \((ipad)/i,
545
+ /\b(ipad)\d\d?,\d\d?[;\]].+ios/i
546
+ ], [MODEL, [VENDOR, APPLE], [TYPE, TABLET]], [
547
+ /(macintosh);/i
548
+ ], [MODEL, [VENDOR, APPLE]], [
549
+
550
+ // Sharp
551
+ /\b(sh-?[altvz]?\d\d[a-ekm]?)/i
552
+ ], [MODEL, [VENDOR, SHARP], [TYPE, MOBILE]], [
553
+
554
+ // Honor
555
+ /\b((?:brt|eln|hey2?|gdi|jdn)-a?[lnw]09|(?:ag[rm]3?|jdn2|kob2)-a?[lw]0[09]hn)(?: bui|\)|;)/i
556
+ ], [MODEL, [VENDOR, HONOR], [TYPE, TABLET]], [
557
+ /honor([-\w ]+)[;\)]/i
558
+ ], [MODEL, [VENDOR, HONOR], [TYPE, MOBILE]], [
559
+
560
+ // Huawei
561
+ /\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
562
+ ], [MODEL, [VENDOR, HUAWEI], [TYPE, TABLET]], [
563
+ /(?:huawei)([-\w ]+)[;\)]/i,
564
+ /\b(nexus 6p|\w{2,4}e?-[atu]?[ln][\dx][012359c][adn]?)\b(?!.+d\/s)/i
565
+ ], [MODEL, [VENDOR, HUAWEI], [TYPE, MOBILE]], [
566
+
567
+ // Xiaomi
568
+ /oid[^\)]+; (2[\dbc]{4}(182|283|rp\w{2})[cgl]|m2105k81a?c)(?: bui|\))/i,
569
+ /\b((?:red)?mi[-_ ]?pad[\w- ]*)(?: bui|\))/i // Mi Pad tablets
570
+ ],[[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, TABLET]], [
571
+
572
+ /\b(poco[\w ]+|m2\d{3}j\d\d[a-z]{2})(?: bui|\))/i, // Xiaomi POCO
573
+ /\b; (\w+) build\/hm\1/i, // Xiaomi Hongmi 'numeric' models
574
+ /\b(hm[-_ ]?note?[_ ]?(?:\d\w)?) bui/i, // Xiaomi Hongmi
575
+ /\b(redmi[\-_ ]?(?:note|k)?[\w_ ]+)(?: bui|\))/i, // Xiaomi Redmi
576
+ /oid[^\)]+; (m?[12][0-389][01]\w{3,6}[c-y])( bui|; wv|\))/i, // Xiaomi Redmi 'numeric' models
577
+ /\b(mi[-_ ]?(?:a\d|one|one[_ ]plus|note lte|max|cc)?[_ ]?(?:\d?\w?)[_ ]?(?:plus|se|lite|pro)?)(?: bui|\))/i, // Xiaomi Mi
578
+ / ([\w ]+) miui\/v?\d/i
579
+ ], [[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, MOBILE]], [
580
+
581
+ // OPPO
582
+ /; (\w+) bui.+ oppo/i,
583
+ /\b(cph[12]\d{3}|p(?:af|c[al]|d\w|e[ar])[mt]\d0|x9007|a101op)\b/i
584
+ ], [MODEL, [VENDOR, OPPO], [TYPE, MOBILE]], [
585
+ /\b(opd2(\d{3}a?))(?: bui|\))/i
586
+ ], [MODEL, [VENDOR, strMapper, { 'OnePlus' : ['304', '403', '203'], '*' : OPPO }], [TYPE, TABLET]], [
587
+
588
+ // Vivo
589
+ /vivo (\w+)(?: bui|\))/i,
590
+ /\b(v[12]\d{3}\w?[at])(?: bui|;)/i
591
+ ], [MODEL, [VENDOR, 'Vivo'], [TYPE, MOBILE]], [
592
+
593
+ // Realme
594
+ /\b(rmx[1-3]\d{3})(?: bui|;|\))/i
595
+ ], [MODEL, [VENDOR, 'Realme'], [TYPE, MOBILE]], [
596
+
597
+ // Motorola
598
+ /\b(milestone|droid(?:[2-4x]| (?:bionic|x2|pro|razr))?:?( 4g)?)\b[\w ]+build\//i,
599
+ /\bmot(?:orola)?[- ](\w*)/i,
600
+ /((?:moto(?! 360)[\w\(\) ]+|xt\d{3,4}|nexus 6)(?= bui|\)))/i
601
+ ], [MODEL, [VENDOR, MOTOROLA], [TYPE, MOBILE]], [
602
+ /\b(mz60\d|xoom[2 ]{0,2}) build\//i
603
+ ], [MODEL, [VENDOR, MOTOROLA], [TYPE, TABLET]], [
604
+
605
+ // LG
606
+ /((?=lg)?[vl]k\-?\d{3}) bui| 3\.[-\w; ]{10}lg?-([06cv9]{3,4})/i
607
+ ], [MODEL, [VENDOR, LG], [TYPE, TABLET]], [
608
+ /(lm(?:-?f100[nv]?|-[\w\.]+)(?= bui|\))|nexus [45])/i,
609
+ /\blg[-e;\/ ]+((?!browser|netcast|android tv|watch)\w+)/i,
610
+ /\blg-?([\d\w]+) bui/i
611
+ ], [MODEL, [VENDOR, LG], [TYPE, MOBILE]], [
612
+
613
+ // Lenovo
614
+ /(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,
615
+ /lenovo ?(b[68]0[08]0-?[hf]?|tab(?:[\w- ]+?)|tb[\w-]{6,7})( bui|;|\)|\/)/i
616
+ ], [MODEL, [VENDOR, LENOVO], [TYPE, TABLET]], [
617
+
618
+ // Nokia
619
+ /(nokia) (t[12][01])/i
620
+ ], [VENDOR, MODEL, [TYPE, TABLET]], [
621
+ /(?:maemo|nokia).*(n900|lumia \d+|rm-\d+)/i,
622
+ /nokia[-_ ]?(([-\w\. ]*))/i
623
+ ], [[MODEL, /_/g, ' '], [TYPE, MOBILE], [VENDOR, 'Nokia']], [
624
+
625
+ // Google
626
+ /(pixel (c|tablet))\b/i // Google Pixel C/Tablet
627
+ ], [MODEL, [VENDOR, GOOGLE], [TYPE, TABLET]], [
628
+ /droid.+; (pixel[\daxl ]{0,6})(?: bui|\))/i // Google Pixel
629
+ ], [MODEL, [VENDOR, GOOGLE], [TYPE, MOBILE]], [
630
+
631
+ // Sony
632
+ /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
633
+ ], [MODEL, [VENDOR, SONY], [TYPE, MOBILE]], [
634
+ /sony tablet [ps]/i,
635
+ /\b(?:sony)?sgp\w+(?: bui|\))/i
636
+ ], [[MODEL, 'Xperia Tablet'], [VENDOR, SONY], [TYPE, TABLET]], [
637
+
638
+ // OnePlus
639
+ / (kb2005|in20[12]5|be20[12][59])\b/i,
640
+ /(?:one)?(?:plus)? (a\d0\d\d)(?: b|\))/i
641
+ ], [MODEL, [VENDOR, ONEPLUS], [TYPE, MOBILE]], [
642
+
643
+ // Amazon
644
+ /(alexa)webm/i,
645
+ /(kf[a-z]{2}wi|aeo(?!bc)\w\w)( bui|\))/i, // Kindle Fire without Silk / Echo Show
646
+ /(kf[a-z]+)( bui|\)).+silk\//i // Kindle Fire HD
647
+ ], [MODEL, [VENDOR, AMAZON], [TYPE, TABLET]], [
648
+ /((?:sd|kf)[0349hijorstuw]+)( bui|\)).+silk\//i // Fire Phone
649
+ ], [[MODEL, /(.+)/g, 'Fire Phone $1'], [VENDOR, AMAZON], [TYPE, MOBILE]], [
650
+
651
+ // BlackBerry
652
+ /(playbook);[-\w\),; ]+(rim)/i // BlackBerry PlayBook
653
+ ], [MODEL, VENDOR, [TYPE, TABLET]], [
654
+ /\b((?:bb[a-f]|st[hv])100-\d)/i,
655
+ /\(bb10; (\w+)/i // BlackBerry 10
656
+ ], [MODEL, [VENDOR, BLACKBERRY], [TYPE, MOBILE]], [
657
+
658
+ // Asus
659
+ /(?:\b|asus_)(transfo[prime ]{4,10} \w+|eeepc|slider \w+|nexus 7|padfone|p00[cj])/i
660
+ ], [MODEL, [VENDOR, ASUS], [TYPE, TABLET]], [
661
+ / (z[bes]6[027][012][km][ls]|zenfone \d\w?)\b/i
662
+ ], [MODEL, [VENDOR, ASUS], [TYPE, MOBILE]], [
663
+
664
+ // HTC
665
+ /(nexus 9)/i // HTC Nexus 9
666
+ ], [MODEL, [VENDOR, 'HTC'], [TYPE, TABLET]], [
667
+ /(htc)[-;_ ]{1,2}([\w ]+(?=\)| bui)|\w+)/i, // HTC
668
+
669
+ // ZTE
670
+ /(zte)[- ]([\w ]+?)(?: bui|\/|\))/i,
671
+ /(alcatel|geeksphone|nexian|panasonic(?!(?:;|\.))|sony(?!-bra))[-_ ]?([-\w]*)/i // Alcatel/GeeksPhone/Nexian/Panasonic/Sony
672
+ ], [VENDOR, [MODEL, /_/g, ' '], [TYPE, MOBILE]], [
673
+
674
+ // TCL
675
+ /tcl (xess p17aa)/i,
676
+ /droid [\w\.]+; ((?:8[14]9[16]|9(?:0(?:48|60|8[01])|1(?:3[27]|66)|2(?:6[69]|9[56])|466))[gqswx])(_\w(\w|\w\w))?(\)| bui)/i
677
+ ], [MODEL, [VENDOR, 'TCL'], [TYPE, TABLET]], [
678
+ /droid [\w\.]+; (418(?:7d|8v)|5087z|5102l|61(?:02[dh]|25[adfh]|27[ai]|56[dh]|59k|65[ah])|a509dl|t(?:43(?:0w|1[adepqu])|50(?:6d|7[adju])|6(?:09dl|10k|12b|71[efho]|76[hjk])|7(?:66[ahju]|67[hw]|7[045][bh]|71[hk]|73o|76[ho]|79w|81[hks]?|82h|90[bhsy]|99b)|810[hs]))(_\w(\w|\w\w))?(\)| bui)/i
679
+ ], [MODEL, [VENDOR, 'TCL'], [TYPE, MOBILE]], [
680
+
681
+ // itel
682
+ /(itel) ((\w+))/i
683
+ ], [[VENDOR, lowerize], MODEL, [TYPE, strMapper, { 'tablet' : ['p10001l', 'w7001'], '*' : 'mobile' }]], [
684
+
685
+ // Acer
686
+ /droid.+; ([ab][1-7]-?[0178a]\d\d?)/i
687
+ ], [MODEL, [VENDOR, 'Acer'], [TYPE, TABLET]], [
688
+
689
+ // Meizu
690
+ /droid.+; (m[1-5] note) bui/i,
691
+ /\bmz-([-\w]{2,})/i
692
+ ], [MODEL, [VENDOR, 'Meizu'], [TYPE, MOBILE]], [
693
+
694
+ // Ulefone
695
+ /; ((?:power )?armor(?:[\w ]{0,8}))(?: bui|\))/i
696
+ ], [MODEL, [VENDOR, 'Ulefone'], [TYPE, MOBILE]], [
697
+
698
+ // Energizer
699
+ /; (energy ?\w+)(?: bui|\))/i,
700
+ /; energizer ([\w ]+)(?: bui|\))/i
701
+ ], [MODEL, [VENDOR, 'Energizer'], [TYPE, MOBILE]], [
702
+
703
+ // Cat
704
+ /; cat (b35);/i,
705
+ /; (b15q?|s22 flip|s48c|s62 pro)(?: bui|\))/i
706
+ ], [MODEL, [VENDOR, 'Cat'], [TYPE, MOBILE]], [
707
+
708
+ // Smartfren
709
+ /((?:new )?andromax[\w- ]+)(?: bui|\))/i
710
+ ], [MODEL, [VENDOR, 'Smartfren'], [TYPE, MOBILE]], [
711
+
712
+ // Nothing
713
+ /droid.+; (a(?:015|06[35]|142p?))/i
714
+ ], [MODEL, [VENDOR, 'Nothing'], [TYPE, MOBILE]], [
715
+
716
+ // MIXED
717
+ /(imo) (tab \w+)/i, // IMO
718
+ /(infinix) (x1101b?)/i // Infinix XPad
719
+ ], [VENDOR, MODEL, [TYPE, TABLET]], [
720
+
721
+ /(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus(?! zenw)|dell|jolla|meizu|motorola|polytron|infinix|tecno|micromax|advan)[-_ ]?([-\w]*)/i,
722
+ // BlackBerry/BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron/Infinix/Tecno/Micromax/Advan
723
+ /; (hmd|imo) ([\w ]+?)(?: bui|\))/i, // HMD/IMO
724
+ /(hp) ([\w ]+\w)/i, // HP iPAQ
725
+ /(microsoft); (lumia[\w ]+)/i, // Microsoft Lumia
726
+ /(lenovo)[-_ ]?([-\w ]+?)(?: bui|\)|\/)/i, // Lenovo
727
+ /(oppo) ?([\w ]+) bui/i // OPPO
728
+ ], [VENDOR, MODEL, [TYPE, MOBILE]], [
729
+
730
+ /(kobo)\s(ereader|touch)/i, // Kobo
731
+ /(archos) (gamepad2?)/i, // Archos
732
+ /(hp).+(touchpad(?!.+tablet)|tablet)/i, // HP TouchPad
733
+ /(kindle)\/([\w\.]+)/i // Kindle
734
+ ], [VENDOR, MODEL, [TYPE, TABLET]], [
735
+
736
+ /(surface duo)/i // Surface Duo
737
+ ], [MODEL, [VENDOR, MICROSOFT], [TYPE, TABLET]], [
738
+ /droid [\d\.]+; (fp\du?)(?: b|\))/i // Fairphone
739
+ ], [MODEL, [VENDOR, 'Fairphone'], [TYPE, MOBILE]], [
740
+ /((?:tegranote|shield t(?!.+d tv))[\w- ]*?)(?: b|\))/i // Nvidia Tablets
741
+ ], [MODEL, [VENDOR, NVIDIA], [TYPE, TABLET]], [
742
+ /(sprint) (\w+)/i // Sprint Phones
743
+ ], [VENDOR, MODEL, [TYPE, MOBILE]], [
744
+ /(kin\.[onetw]{3})/i // Microsoft Kin
745
+ ], [[MODEL, /\./g, ' '], [VENDOR, MICROSOFT], [TYPE, MOBILE]], [
746
+ /droid.+; ([c6]+|et5[16]|mc[239][23]x?|vc8[03]x?)\)/i // Zebra
747
+ ], [MODEL, [VENDOR, ZEBRA], [TYPE, TABLET]], [
748
+ /droid.+; (ec30|ps20|tc[2-8]\d[kx])\)/i
749
+ ], [MODEL, [VENDOR, ZEBRA], [TYPE, MOBILE]], [
750
+
751
+ ///////////////////
752
+ // SMARTTVS
753
+ ///////////////////
754
+
755
+ /smart-tv.+(samsung)/i // Samsung
756
+ ], [VENDOR, [TYPE, SMARTTV]], [
757
+ /hbbtv.+maple;(\d+)/i
758
+ ], [[MODEL, /^/, 'SmartTV'], [VENDOR, SAMSUNG], [TYPE, SMARTTV]], [
759
+ /(nux; netcast.+smarttv|lg (netcast\.tv-201\d|android tv))/i // LG SmartTV
760
+ ], [[VENDOR, LG], [TYPE, SMARTTV]], [
761
+ /(apple) ?tv/i // Apple TV
762
+ ], [VENDOR, [MODEL, APPLE+' TV'], [TYPE, SMARTTV]], [
763
+ /crkey.*devicetype\/chromecast/i // Google Chromecast Third Generation
764
+ ], [[MODEL, CHROMECAST+' Third Generation'], [VENDOR, GOOGLE], [TYPE, SMARTTV]], [
765
+ /crkey.*devicetype\/([^/]*)/i // Google Chromecast with specific device type
766
+ ], [[MODEL, /^/, 'Chromecast '], [VENDOR, GOOGLE], [TYPE, SMARTTV]], [
767
+ /fuchsia.*crkey/i // Google Chromecast Nest Hub
768
+ ], [[MODEL, CHROMECAST+' Nest Hub'], [VENDOR, GOOGLE], [TYPE, SMARTTV]], [
769
+ /crkey/i // Google Chromecast, Linux-based or unknown
770
+ ], [[MODEL, CHROMECAST], [VENDOR, GOOGLE], [TYPE, SMARTTV]], [
771
+ /droid.+aft(\w+)( bui|\))/i // Fire TV
772
+ ], [MODEL, [VENDOR, AMAZON], [TYPE, SMARTTV]], [
773
+ /(shield \w+ tv)/i // Nvidia Shield TV
774
+ ], [MODEL, [VENDOR, NVIDIA], [TYPE, SMARTTV]], [
775
+ /\(dtv[\);].+(aquos)/i,
776
+ /(aquos-tv[\w ]+)\)/i // Sharp
777
+ ], [MODEL, [VENDOR, SHARP], [TYPE, SMARTTV]],[
778
+ /(bravia[\w ]+)( bui|\))/i // Sony
779
+ ], [MODEL, [VENDOR, SONY], [TYPE, SMARTTV]], [
780
+ /(mi(tv|box)-?\w+) bui/i // Xiaomi
781
+ ], [MODEL, [VENDOR, XIAOMI], [TYPE, SMARTTV]], [
782
+ /Hbbtv.*(technisat) (.*);/i // TechniSAT
783
+ ], [VENDOR, MODEL, [TYPE, SMARTTV]], [
784
+ /\b(roku)[\dx]*[\)\/]((?:dvp-)?[\d\.]*)/i, // Roku
785
+ /hbbtv\/\d+\.\d+\.\d+ +\([\w\+ ]*; *([\w\d][^;]*);([^;]*)/i // HbbTV devices
786
+ ], [[VENDOR, trim], [MODEL, trim], [TYPE, SMARTTV]], [
787
+ // SmartTV from Unidentified Vendors
788
+ /droid.+; ([\w- ]+) (?:android tv|smart[- ]?tv)/i
789
+ ], [MODEL, [TYPE, SMARTTV]], [
790
+ /\b(android tv|smart[- ]?tv|opera tv|tv; rv:)\b/i
791
+ ], [[TYPE, SMARTTV]], [
792
+
793
+ ///////////////////
794
+ // CONSOLES
795
+ ///////////////////
796
+
797
+ /(ouya)/i, // Ouya
798
+ /(nintendo) (\w+)/i // Nintendo
799
+ ], [VENDOR, MODEL, [TYPE, CONSOLE]], [
800
+ /droid.+; (shield)( bui|\))/i // Nvidia Portable
801
+ ], [MODEL, [VENDOR, NVIDIA], [TYPE, CONSOLE]], [
802
+ /(playstation \w+)/i // Playstation
803
+ ], [MODEL, [VENDOR, SONY], [TYPE, CONSOLE]], [
804
+ /\b(xbox(?: one)?(?!; xbox))[\); ]/i // Microsoft Xbox
805
+ ], [MODEL, [VENDOR, MICROSOFT], [TYPE, CONSOLE]], [
806
+
807
+ ///////////////////
808
+ // WEARABLES
809
+ ///////////////////
810
+
811
+ /\b(sm-[lr]\d\d[0156][fnuw]?s?|gear live)\b/i // Samsung Galaxy Watch
812
+ ], [MODEL, [VENDOR, SAMSUNG], [TYPE, WEARABLE]], [
813
+ /((pebble))app/i, // Pebble
814
+ /(asus|google|lg|oppo) ((pixel |zen)?watch[\w ]*)( bui|\))/i // Asus ZenWatch / LG Watch / Pixel Watch
815
+ ], [VENDOR, MODEL, [TYPE, WEARABLE]], [
816
+ /(ow(?:19|20)?we?[1-3]{1,3})/i // Oppo Watch
817
+ ], [MODEL, [VENDOR, OPPO], [TYPE, WEARABLE]], [
818
+ /(watch)(?: ?os[,\/]|\d,\d\/)[\d\.]+/i // Apple Watch
819
+ ], [MODEL, [VENDOR, APPLE], [TYPE, WEARABLE]], [
820
+ /(opwwe\d{3})/i // OnePlus Watch
821
+ ], [MODEL, [VENDOR, ONEPLUS], [TYPE, WEARABLE]], [
822
+ /(moto 360)/i // Motorola 360
823
+ ], [MODEL, [VENDOR, MOTOROLA], [TYPE, WEARABLE]], [
824
+ /(smartwatch 3)/i // Sony SmartWatch
825
+ ], [MODEL, [VENDOR, SONY], [TYPE, WEARABLE]], [
826
+ /(g watch r)/i // LG G Watch R
827
+ ], [MODEL, [VENDOR, LG], [TYPE, WEARABLE]], [
828
+ /droid.+; (wt63?0{2,3})\)/i
829
+ ], [MODEL, [VENDOR, ZEBRA], [TYPE, WEARABLE]], [
830
+
831
+ ///////////////////
832
+ // XR
833
+ ///////////////////
834
+
835
+ /droid.+; (glass) \d/i // Google Glass
836
+ ], [MODEL, [VENDOR, GOOGLE], [TYPE, XR]], [
837
+ /(pico) (4|neo3(?: link|pro)?)/i // Pico
838
+ ], [VENDOR, MODEL, [TYPE, XR]], [
839
+ /; (quest( \d| pro)?)/i // Oculus Quest
840
+ ], [MODEL, [VENDOR, FACEBOOK], [TYPE, XR]], [
841
+
842
+ ///////////////////
843
+ // EMBEDDED
844
+ ///////////////////
845
+
846
+ /(tesla)(?: qtcarbrowser|\/[-\w\.]+)/i // Tesla
847
+ ], [VENDOR, [TYPE, EMBEDDED]], [
848
+ /(aeobc)\b/i // Echo Dot
849
+ ], [MODEL, [VENDOR, AMAZON], [TYPE, EMBEDDED]], [
850
+ /(homepod).+mac os/i // Apple HomePod
851
+ ], [MODEL, [VENDOR, APPLE], [TYPE, EMBEDDED]], [
852
+ /windows iot/i
853
+ ], [[TYPE, EMBEDDED]], [
854
+
855
+ ////////////////////
856
+ // MIXED (GENERIC)
857
+ ///////////////////
858
+
859
+ /droid .+?; ([^;]+?)(?: bui|; wv\)|\) applew).+?(mobile|vr|\d) safari/i
860
+ ], [MODEL, [TYPE, strMapper, { 'mobile' : 'Mobile', 'xr' : 'VR', '*' : TABLET }]], [
861
+ /\b((tablet|tab)[;\/]|focus\/\d(?!.+mobile))/i // Unidentifiable Tablet
862
+ ], [[TYPE, TABLET]], [
863
+ /(phone|mobile(?:[;\/]| [ \w\/\.]*safari)|pda(?=.+windows ce))/i // Unidentifiable Mobile
864
+ ], [[TYPE, MOBILE]], [
865
+ /droid .+?; ([\w\. -]+)( bui|\))/i // Generic Android Device
866
+ ], [MODEL, [VENDOR, 'Generic']]
867
+ ],
868
+
869
+ engine : [[
870
+
871
+ /windows.+ edge\/([\w\.]+)/i // EdgeHTML
872
+ ], [VERSION, [NAME, EDGE+'HTML']], [
873
+
874
+ /(arkweb)\/([\w\.]+)/i // ArkWeb
875
+ ], [NAME, VERSION], [
876
+
877
+ /webkit\/537\.36.+chrome\/(?!27)([\w\.]+)/i // Blink
878
+ ], [VERSION, [NAME, 'Blink']], [
879
+
880
+ /(presto)\/([\w\.]+)/i, // Presto
881
+ /(webkit|trident|netfront|netsurf|amaya|lynx|w3m|goanna|servo)\/([\w\.]+)/i, // WebKit/Trident/NetFront/NetSurf/Amaya/Lynx/w3m/Goanna/Servo
882
+ /ekioh(flow)\/([\w\.]+)/i, // Flow
883
+ /(khtml|tasman|links)[\/ ]\(?([\w\.]+)/i, // KHTML/Tasman/Links
884
+ /(icab)[\/ ]([23]\.[\d\.]+)/i, // iCab
885
+
886
+ /\b(libweb)/i // LibWeb
887
+ ], [NAME, VERSION], [
888
+ /ladybird\//i
889
+ ], [[NAME, 'LibWeb']], [
890
+
891
+ /rv\:([\w\.]{1,9})\b.+(gecko)/i // Gecko
892
+ ], [VERSION, NAME]
893
+ ],
894
+
895
+ os : [[
896
+
897
+ // Windows
898
+ /microsoft (windows) (vista|xp)/i // Windows (iTunes)
899
+ ], [NAME, VERSION], [
900
+ /(windows (?:phone(?: os)?|mobile|iot))[\/ ]?([\d\.\w ]*)/i // Windows Phone
901
+ ], [NAME, [VERSION, strMapper, windowsVersionMap]], [
902
+ /windows nt 6\.2; (arm)/i, // Windows RT
903
+ /windows[\/ ]([ntce\d\. ]+\w)(?!.+xbox)/i,
904
+ /(?:win(?=3|9|n)|win 9x )([nt\d\.]+)/i
905
+ ], [[VERSION, strMapper, windowsVersionMap], [NAME, WINDOWS]], [
906
+
907
+ // iOS/macOS
908
+ /[adehimnop]{4,7}\b(?:.*os ([\w]+) like mac|; opera)/i, // iOS
909
+ /(?:ios;fbsv\/|iphone.+ios[\/ ])([\d\.]+)/i,
910
+ /cfnetwork\/.+darwin/i
911
+ ], [[VERSION, /_/g, '.'], [NAME, 'iOS']], [
912
+ /(mac os x) ?([\w\. ]*)/i,
913
+ /(macintosh|mac_powerpc\b)(?!.+haiku)/i // Mac OS
914
+ ], [[NAME, 'macOS'], [VERSION, /_/g, '.']], [
915
+
916
+ // Google Chromecast
917
+ /android ([\d\.]+).*crkey/i // Google Chromecast, Android-based
918
+ ], [VERSION, [NAME, CHROMECAST + ' Android']], [
919
+ /fuchsia.*crkey\/([\d\.]+)/i // Google Chromecast, Fuchsia-based
920
+ ], [VERSION, [NAME, CHROMECAST + ' Fuchsia']], [
921
+ /crkey\/([\d\.]+).*devicetype\/smartspeaker/i // Google Chromecast, Linux-based Smart Speaker
922
+ ], [VERSION, [NAME, CHROMECAST + ' SmartSpeaker']], [
923
+ /linux.*crkey\/([\d\.]+)/i // Google Chromecast, Legacy Linux-based
924
+ ], [VERSION, [NAME, CHROMECAST + ' Linux']], [
925
+ /crkey\/([\d\.]+)/i // Google Chromecast, unknown
926
+ ], [VERSION, [NAME, CHROMECAST]], [
927
+
928
+ // Mobile OSes
929
+ /droid ([\w\.]+)\b.+(android[- ]x86|harmonyos)/i // Android-x86/HarmonyOS
930
+ ], [VERSION, NAME], [
931
+ /(ubuntu) ([\w\.]+) like android/i // Ubuntu Touch
932
+ ], [[NAME, /(.+)/, '$1 Touch'], VERSION], [
933
+ // Android/Blackberry/WebOS/QNX/Bada/RIM/KaiOS/Maemo/MeeGo/S40/Sailfish OS/OpenHarmony/Tizen
934
+ /(android|bada|blackberry|kaios|maemo|meego|openharmony|qnx|rim tablet os|sailfish|series40|symbian|tizen|webos)\w*[-\/; ]?([\d\.]*)/i
935
+ ], [NAME, VERSION], [
936
+ /\(bb(10);/i // BlackBerry 10
937
+ ], [VERSION, [NAME, BLACKBERRY]], [
938
+ /(?:symbian ?os|symbos|s60(?=;)|series ?60)[-\/ ]?([\w\.]*)/i // Symbian
939
+ ], [VERSION, [NAME, 'Symbian']], [
940
+ /mozilla\/[\d\.]+ \((?:mobile|tablet|tv|mobile; [\w ]+); rv:.+ gecko\/([\w\.]+)/i // Firefox OS
941
+ ], [VERSION, [NAME, FIREFOX+' OS']], [
942
+ /web0s;.+rt(tv)/i,
943
+ /\b(?:hp)?wos(?:browser)?\/([\w\.]+)/i // WebOS
944
+ ], [VERSION, [NAME, 'webOS']], [
945
+ /watch(?: ?os[,\/]|\d,\d\/)([\d\.]+)/i // watchOS
946
+ ], [VERSION, [NAME, 'watchOS']], [
947
+
948
+ // Google ChromeOS
949
+ /(cros) [\w]+(?:\)| ([\w\.]+)\b)/i // Chromium OS
950
+ ], [[NAME, "Chrome OS"], VERSION],[
951
+
952
+ // Smart TVs
953
+ /panasonic;(viera)/i, // Panasonic Viera
954
+ /(netrange)mmh/i, // Netrange
955
+ /(nettv)\/(\d+\.[\w\.]+)/i, // NetTV
956
+
957
+ // Console
958
+ /(nintendo|playstation) (\w+)/i, // Nintendo/Playstation
959
+ /(xbox); +xbox ([^\);]+)/i, // Microsoft Xbox (360, One, X, S, Series X, Series S)
960
+ /(pico) .+os([\w\.]+)/i, // Pico
961
+
962
+ // Other
963
+ /\b(joli|palm)\b ?(?:os)?\/?([\w\.]*)/i, // Joli/Palm
964
+ /(mint)[\/\(\) ]?(\w*)/i, // Mint
965
+ /(mageia|vectorlinux)[; ]/i, // Mageia/VectorLinux
966
+ /([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,
967
+ // Ubuntu/Debian/SUSE/Gentoo/Arch/Slackware/Fedora/Mandriva/CentOS/PCLinuxOS/RedHat/Zenwalk/Linpus/Raspbian/Plan9/Minix/RISCOS/Contiki/Deepin/Manjaro/elementary/Sabayon/Linspire
968
+ /(hurd|linux)(?: arm\w*| x86\w*| ?)([\w\.]*)/i, // Hurd/Linux
969
+ /(gnu) ?([\w\.]*)/i, // GNU
970
+ /\b([-frentopcghs]{0,5}bsd|dragonfly)[\/ ]?(?!amd|[ix346]{1,2}86)([\w\.]*)/i, // FreeBSD/NetBSD/OpenBSD/PC-BSD/GhostBSD/DragonFly
971
+ /(haiku) (\w+)/i // Haiku
972
+ ], [NAME, VERSION], [
973
+ /(sunos) ?([\w\.\d]*)/i // Solaris
974
+ ], [[NAME, 'Solaris'], VERSION], [
975
+ /((?:open)?solaris)[-\/ ]?([\w\.]*)/i, // Solaris
976
+ /(aix) ((\d)(?=\.|\)| )[\w\.])*/i, // AIX
977
+ /\b(beos|os\/2|amigaos|morphos|openvms|fuchsia|hp-ux|serenityos)/i, // BeOS/OS2/AmigaOS/MorphOS/OpenVMS/Fuchsia/HP-UX/SerenityOS
978
+ /(unix) ?([\w\.]*)/i // UNIX
979
+ ], [NAME, VERSION]
980
+ ]
981
+ };
982
+
983
+ /////////////////
984
+ // Factories
985
+ ////////////////
986
+
987
+ var defaultProps = (function () {
988
+ var props = { init : {}, isIgnore : {}, isIgnoreRgx : {}, toString : {}};
989
+ setProps.call(props.init, [
990
+ [UA_BROWSER, [NAME, VERSION, MAJOR, TYPE]],
991
+ [UA_CPU, [ARCHITECTURE]],
992
+ [UA_DEVICE, [TYPE, MODEL, VENDOR]],
993
+ [UA_ENGINE, [NAME, VERSION]],
994
+ [UA_OS, [NAME, VERSION]]
995
+ ]);
996
+ setProps.call(props.isIgnore, [
997
+ [UA_BROWSER, [VERSION, MAJOR]],
998
+ [UA_ENGINE, [VERSION]],
999
+ [UA_OS, [VERSION]]
1000
+ ]);
1001
+ setProps.call(props.isIgnoreRgx, [
1002
+ [UA_BROWSER, / ?browser$/i],
1003
+ [UA_OS, / ?os$/i]
1004
+ ]);
1005
+ setProps.call(props.toString, [
1006
+ [UA_BROWSER, [NAME, VERSION]],
1007
+ [UA_CPU, [ARCHITECTURE]],
1008
+ [UA_DEVICE, [VENDOR, MODEL]],
1009
+ [UA_ENGINE, [NAME, VERSION]],
1010
+ [UA_OS, [NAME, VERSION]]
1011
+ ]);
1012
+ return props;
1013
+ })();
1014
+
1015
+ var createIData = function (item, itemType) {
1016
+
1017
+ var init_props = defaultProps.init[itemType],
1018
+ is_ignoreProps = defaultProps.isIgnore[itemType] || 0,
1019
+ is_ignoreRgx = defaultProps.isIgnoreRgx[itemType] || 0,
1020
+ toString_props = defaultProps.toString[itemType] || 0;
1021
+
1022
+ function IData () {
1023
+ setProps.call(this, init_props);
1024
+ }
1025
+
1026
+ IData.prototype.getItem = function () {
1027
+ return item;
1028
+ };
1029
+
1030
+ IData.prototype.withClientHints = function () {
1031
+
1032
+ // nodejs / non-client-hints browsers
1033
+ if (!NAVIGATOR_UADATA) {
1034
+ return item
1035
+ .parseCH()
1036
+ .get();
1037
+ }
1038
+
1039
+ // browsers based on chromium 85+
1040
+ return NAVIGATOR_UADATA
1041
+ .getHighEntropyValues(CH_ALL_VALUES)
1042
+ .then(function (res) {
1043
+ return item
1044
+ .setCH(new UACHData(res, false))
1045
+ .parseCH()
1046
+ .get();
1047
+ });
1048
+ };
1049
+
1050
+ IData.prototype.withFeatureCheck = function () {
1051
+ return item.detectFeature().get();
1052
+ };
1053
+
1054
+ if (itemType != UA_RESULT) {
1055
+ IData.prototype.is = function (strToCheck) {
1056
+ var is = false;
1057
+ for (var i in this) {
1058
+ if (this.hasOwnProperty(i) && !has(is_ignoreProps, i) && lowerize(is_ignoreRgx ? strip(is_ignoreRgx, this[i]) : this[i]) == lowerize(is_ignoreRgx ? strip(is_ignoreRgx, strToCheck) : strToCheck)) {
1059
+ is = true;
1060
+ if (strToCheck != UNDEF_TYPE) break;
1061
+ } else if (strToCheck == UNDEF_TYPE && is) {
1062
+ is = !is;
1063
+ break;
1064
+ }
1065
+ }
1066
+ return is;
1067
+ };
1068
+ IData.prototype.toString = function () {
1069
+ var str = EMPTY;
1070
+ for (var i in toString_props) {
1071
+ if (typeof(this[toString_props[i]]) !== UNDEF_TYPE) {
1072
+ str += (str ? ' ' : EMPTY) + this[toString_props[i]];
1073
+ }
1074
+ }
1075
+ return str || UNDEF_TYPE;
1076
+ };
1077
+ }
1078
+
1079
+ if (!NAVIGATOR_UADATA) {
1080
+ IData.prototype.then = function (cb) {
1081
+ var that = this;
1082
+ var IDataResolve = function () {
1083
+ for (var prop in that) {
1084
+ if (that.hasOwnProperty(prop)) {
1085
+ this[prop] = that[prop];
1086
+ }
1087
+ }
1088
+ };
1089
+ IDataResolve.prototype = {
1090
+ is : IData.prototype.is,
1091
+ toString : IData.prototype.toString
1092
+ };
1093
+ var resolveData = new IDataResolve();
1094
+ cb(resolveData);
1095
+ return resolveData;
1096
+ };
1097
+ }
1098
+
1099
+ return new IData();
1100
+ };
1101
+
1102
+ /////////////////
1103
+ // Constructor
1104
+ ////////////////
1105
+
1106
+ function UACHData (uach, isHttpUACH) {
1107
+ uach = uach || {};
1108
+ setProps.call(this, CH_ALL_VALUES);
1109
+ if (isHttpUACH) {
1110
+ setProps.call(this, [
1111
+ [BRANDS, itemListToArray(uach[CH_HEADER])],
1112
+ [FULLVERLIST, itemListToArray(uach[CH_HEADER_FULL_VER_LIST])],
1113
+ [MOBILE, /\?1/.test(uach[CH_HEADER_MOBILE])],
1114
+ [MODEL, stripQuotes(uach[CH_HEADER_MODEL])],
1115
+ [PLATFORM, stripQuotes(uach[CH_HEADER_PLATFORM])],
1116
+ [PLATFORMVER, stripQuotes(uach[CH_HEADER_PLATFORM_VER])],
1117
+ [ARCHITECTURE, stripQuotes(uach[CH_HEADER_ARCH])],
1118
+ [FORMFACTORS, itemListToArray(uach[CH_HEADER_FORM_FACTORS])],
1119
+ [BITNESS, stripQuotes(uach[CH_HEADER_BITNESS])]
1120
+ ]);
1121
+ } else {
1122
+ for (var prop in uach) {
1123
+ if(this.hasOwnProperty(prop) && typeof uach[prop] !== UNDEF_TYPE) this[prop] = uach[prop];
1124
+ }
1125
+ }
1126
+ }
1127
+
1128
+ function UAItem (itemType, ua, rgxMap, uaCH) {
1129
+
1130
+ this.get = function (prop) {
1131
+ if (!prop) return this.data;
1132
+ return this.data.hasOwnProperty(prop) ? this.data[prop] : undefined;
1133
+ };
1134
+
1135
+ this.set = function (prop, val) {
1136
+ this.data[prop] = val;
1137
+ return this;
1138
+ };
1139
+
1140
+ this.setCH = function (ch) {
1141
+ this.uaCH = ch;
1142
+ return this;
1143
+ };
1144
+
1145
+ this.detectFeature = function () {
1146
+ if (NAVIGATOR && NAVIGATOR.userAgent == this.ua) {
1147
+ switch (this.itemType) {
1148
+ case UA_BROWSER:
1149
+ // Brave-specific detection
1150
+ if (NAVIGATOR.brave && typeof NAVIGATOR.brave.isBrave == FUNC_TYPE) {
1151
+ this.set(NAME, 'Brave');
1152
+ }
1153
+ break;
1154
+ case UA_DEVICE:
1155
+ // Chrome-specific detection: check for 'mobile' value of navigator.userAgentData
1156
+ if (!this.get(TYPE) && NAVIGATOR_UADATA && NAVIGATOR_UADATA[MOBILE]) {
1157
+ this.set(TYPE, MOBILE);
1158
+ }
1159
+ // iPadOS-specific detection: identified as Mac, but has some iOS-only properties
1160
+ if (this.get(MODEL) == 'Macintosh' && NAVIGATOR && typeof NAVIGATOR.standalone !== UNDEF_TYPE && NAVIGATOR.maxTouchPoints && NAVIGATOR.maxTouchPoints > 2) {
1161
+ this.set(MODEL, 'iPad')
1162
+ .set(TYPE, TABLET);
1163
+ }
1164
+ break;
1165
+ case UA_OS:
1166
+ // Chrome-specific detection: check for 'platform' value of navigator.userAgentData
1167
+ if (!this.get(NAME) && NAVIGATOR_UADATA && NAVIGATOR_UADATA[PLATFORM]) {
1168
+ this.set(NAME, NAVIGATOR_UADATA[PLATFORM]);
1169
+ }
1170
+ break;
1171
+ case UA_RESULT:
1172
+ var data = this.data;
1173
+ var detect = function (itemType) {
1174
+ return data[itemType]
1175
+ .getItem()
1176
+ .detectFeature()
1177
+ .get();
1178
+ };
1179
+ this.set(UA_BROWSER, detect(UA_BROWSER))
1180
+ .set(UA_CPU, detect(UA_CPU))
1181
+ .set(UA_DEVICE, detect(UA_DEVICE))
1182
+ .set(UA_ENGINE, detect(UA_ENGINE))
1183
+ .set(UA_OS, detect(UA_OS));
1184
+ }
1185
+ }
1186
+ return this;
1187
+ };
1188
+
1189
+ this.parseUA = function () {
1190
+ if (this.itemType != UA_RESULT) {
1191
+ rgxMapper.call(this.data, this.ua, this.rgxMap);
1192
+ }
1193
+ if (this.itemType == UA_BROWSER) {
1194
+ this.set(MAJOR, majorize(this.get(VERSION)));
1195
+ }
1196
+ return this;
1197
+ };
1198
+
1199
+ this.parseCH = function () {
1200
+ var uaCH = this.uaCH,
1201
+ rgxMap = this.rgxMap;
1202
+
1203
+ switch (this.itemType) {
1204
+ case UA_BROWSER:
1205
+ case UA_ENGINE:
1206
+ var brands = uaCH[FULLVERLIST] || uaCH[BRANDS], prevName;
1207
+ if (brands) {
1208
+ for (var i in brands) {
1209
+ var brandName = brands[i].brand || brands[i],
1210
+ brandVersion = brands[i].version;
1211
+ if (this.itemType == UA_BROWSER && !/not.a.brand/i.test(brandName) && (!prevName || (/chrom/i.test(prevName) && brandName != CHROMIUM))) {
1212
+ brandName = strMapper(brandName, {
1213
+ 'Chrome' : 'Google Chrome',
1214
+ 'Edge' : 'Microsoft Edge',
1215
+ 'Chrome WebView' : 'Android WebView',
1216
+ 'Chrome Headless' : 'HeadlessChrome'
1217
+ });
1218
+ this.set(NAME, brandName)
1219
+ .set(VERSION, brandVersion)
1220
+ .set(MAJOR, majorize(brandVersion));
1221
+ prevName = brandName;
1222
+ }
1223
+ if (this.itemType == UA_ENGINE && brandName == CHROMIUM) {
1224
+ this.set(VERSION, brandVersion);
1225
+ }
1226
+ }
1227
+ }
1228
+ break;
1229
+ case UA_CPU:
1230
+ var archName = uaCH[ARCHITECTURE];
1231
+ if (archName) {
1232
+ if (archName && uaCH[BITNESS] == '64') archName += '64';
1233
+ rgxMapper.call(this.data, archName + ';', rgxMap);
1234
+ }
1235
+ break;
1236
+ case UA_DEVICE:
1237
+ if (uaCH[MOBILE]) {
1238
+ this.set(TYPE, MOBILE);
1239
+ }
1240
+ if (uaCH[MODEL]) {
1241
+ this.set(MODEL, uaCH[MODEL]);
1242
+ if (!this.get(TYPE) || !this.get(VENDOR)) {
1243
+ var reParse = {};
1244
+ rgxMapper.call(reParse, 'droid 9; ' + uaCH[MODEL] + ')', rgxMap);
1245
+ if (!this.get(TYPE) && !!reParse.type) {
1246
+ this.set(TYPE, reParse.type);
1247
+ }
1248
+ if (!this.get(VENDOR) && !!reParse.vendor) {
1249
+ this.set(VENDOR, reParse.vendor);
1250
+ }
1251
+ }
1252
+ }
1253
+ if (uaCH[FORMFACTORS]) {
1254
+ var ff;
1255
+ if (typeof uaCH[FORMFACTORS] !== 'string') {
1256
+ var idx = 0;
1257
+ while (!ff && idx < uaCH[FORMFACTORS].length) {
1258
+ ff = strMapper(uaCH[FORMFACTORS][idx++], formFactorsMap);
1259
+ }
1260
+ } else {
1261
+ ff = strMapper(uaCH[FORMFACTORS], formFactorsMap);
1262
+ }
1263
+ this.set(TYPE, ff);
1264
+ }
1265
+ break;
1266
+ case UA_OS:
1267
+ var osName = uaCH[PLATFORM];
1268
+ if(osName) {
1269
+ var osVersion = uaCH[PLATFORMVER];
1270
+ if (osName == WINDOWS) osVersion = (parseInt(majorize(osVersion), 10) >= 13 ? '11' : '10');
1271
+ this.set(NAME, osName)
1272
+ .set(VERSION, osVersion);
1273
+ }
1274
+ // Xbox-Specific Detection
1275
+ if (this.get(NAME) == WINDOWS && uaCH[MODEL] == 'Xbox') {
1276
+ this.set(NAME, 'Xbox')
1277
+ .set(VERSION, undefined);
1278
+ }
1279
+ break;
1280
+ case UA_RESULT:
1281
+ var data = this.data;
1282
+ var parse = function (itemType) {
1283
+ return data[itemType]
1284
+ .getItem()
1285
+ .setCH(uaCH)
1286
+ .parseCH()
1287
+ .get();
1288
+ };
1289
+ this.set(UA_BROWSER, parse(UA_BROWSER))
1290
+ .set(UA_CPU, parse(UA_CPU))
1291
+ .set(UA_DEVICE, parse(UA_DEVICE))
1292
+ .set(UA_ENGINE, parse(UA_ENGINE))
1293
+ .set(UA_OS, parse(UA_OS));
1294
+ }
1295
+ return this;
1296
+ };
1297
+
1298
+ setProps.call(this, [
1299
+ ['itemType', itemType],
1300
+ ['ua', ua],
1301
+ ['uaCH', uaCH],
1302
+ ['rgxMap', rgxMap],
1303
+ ['data', createIData(this, itemType)]
1304
+ ]);
1305
+
1306
+ return this;
1307
+ }
1308
+
1309
+ function UAParser (ua, extensions, headers) {
1310
+
1311
+ if (typeof ua === OBJ_TYPE) {
1312
+ if (isExtensions(ua, true)) {
1313
+ if (typeof extensions === OBJ_TYPE) {
1314
+ headers = extensions; // case UAParser(extensions, headers)
1315
+ }
1316
+ extensions = ua; // case UAParser(extensions)
1317
+ } else {
1318
+ headers = ua; // case UAParser(headers)
1319
+ extensions = undefined;
1320
+ }
1321
+ ua = undefined;
1322
+ } else if (typeof ua === STR_TYPE && !isExtensions(extensions, true)) {
1323
+ headers = extensions; // case UAParser(ua, headers)
1324
+ extensions = undefined;
1325
+ }
1326
+
1327
+ // Convert Headers object into a plain object
1328
+ if (headers && typeof headers.append === FUNC_TYPE) {
1329
+ var kv = {};
1330
+ headers.forEach(function (v, k) { kv[k] = v; });
1331
+ headers = kv;
1332
+ }
1333
+
1334
+ if (!(this instanceof UAParser)) {
1335
+ return new UAParser(ua, extensions, headers).getResult();
1336
+ }
1337
+
1338
+ var userAgent = typeof ua === STR_TYPE ? ua : // Passed user-agent string
1339
+ (headers && headers[USER_AGENT] ? headers[USER_AGENT] : // User-Agent from passed headers
1340
+ ((NAVIGATOR && NAVIGATOR.userAgent) ? NAVIGATOR.userAgent : // navigator.userAgent
1341
+ EMPTY)), // empty string
1342
+
1343
+ httpUACH = new UACHData(headers, true),
1344
+ regexMap = extensions ?
1345
+ extend(defaultRegexes, extensions) :
1346
+ defaultRegexes,
1347
+
1348
+ createItemFunc = function (itemType) {
1349
+ if (itemType == UA_RESULT) {
1350
+ return function () {
1351
+ return new UAItem(itemType, userAgent, regexMap, httpUACH)
1352
+ .set('ua', userAgent)
1353
+ .set(UA_BROWSER, this.getBrowser())
1354
+ .set(UA_CPU, this.getCPU())
1355
+ .set(UA_DEVICE, this.getDevice())
1356
+ .set(UA_ENGINE, this.getEngine())
1357
+ .set(UA_OS, this.getOS())
1358
+ .get();
1359
+ };
1360
+ } else {
1361
+ return function () {
1362
+ return new UAItem(itemType, userAgent, regexMap[itemType], httpUACH)
1363
+ .parseUA()
1364
+ .get();
1365
+ };
1366
+ }
1367
+ };
1368
+
1369
+ // public methods
1370
+ setProps.call(this, [
1371
+ ['getBrowser', createItemFunc(UA_BROWSER)],
1372
+ ['getCPU', createItemFunc(UA_CPU)],
1373
+ ['getDevice', createItemFunc(UA_DEVICE)],
1374
+ ['getEngine', createItemFunc(UA_ENGINE)],
1375
+ ['getOS', createItemFunc(UA_OS)],
1376
+ ['getResult', createItemFunc(UA_RESULT)],
1377
+ ['getUA', function () { return userAgent; }],
1378
+ ['setUA', function (ua) {
1379
+ if (isString(ua))
1380
+ userAgent = ua.length > UA_MAX_LENGTH ? trim(ua, UA_MAX_LENGTH) : ua;
1381
+ return this;
1382
+ }]
1383
+ ])
1384
+ .setUA(userAgent);
1385
+
1386
+ return this;
1387
+ }
1388
+
1389
+ UAParser.VERSION = LIBVERSION;
1390
+ UAParser.BROWSER = enumerize([NAME, VERSION, MAJOR, TYPE]);
1391
+ UAParser.CPU = enumerize([ARCHITECTURE]);
1392
+ UAParser.DEVICE = enumerize([MODEL, VENDOR, TYPE, CONSOLE, MOBILE, SMARTTV, TABLET, WEARABLE, EMBEDDED]);
1393
+ UAParser.ENGINE = UAParser.OS = enumerize([NAME, VERSION]);
1394
+
1395
+ ///////////
1396
+ // Export
1397
+ //////////
1398
+
1399
+ // check js environment
1400
+ if (typeof exports !== UNDEF_TYPE) {
1401
+ // nodejs env
1402
+ if (typeof module !== UNDEF_TYPE && module.exports) {
1403
+ exports = module.exports = UAParser;
1404
+ }
1405
+ exports.UAParser = UAParser;
1406
+ } else {
1407
+ // requirejs env (optional)
1408
+ if (typeof define === FUNC_TYPE && define.amd) {
1409
+ define(function () {
1410
+ return UAParser;
1411
+ });
1412
+ } else if (isWindow) {
1413
+ // browser env
1414
+ window.UAParser = UAParser;
1415
+ }
1416
+ }
1417
+
1418
+ // jQuery/Zepto specific (optional)
1419
+ // Note:
1420
+ // In AMD env the global scope should be kept clean, but jQuery is an exception.
1421
+ // jQuery always exports to global scope, unless jQuery.noConflict(true) is used,
1422
+ // and we should catch that.
1423
+ var $ = isWindow && (window.jQuery || window.Zepto);
1424
+ if ($ && !$.ua) {
1425
+ var parser = new UAParser();
1426
+ $.ua = parser.getResult();
1427
+ $.ua.get = function () {
1428
+ return parser.getUA();
1429
+ };
1430
+ $.ua.set = function (ua) {
1431
+ parser.setUA(ua);
1432
+ var result = parser.getResult();
1433
+ for (var prop in result) {
1434
+ $.ua[prop] = result[prop];
1435
+ }
1436
+ };
1437
+ }
1438
+
1439
+ })(typeof window === 'object' ? window : this);