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