ua-browser 1.4.0-beta.1 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +209 -108
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +28 -2
- package/dist/index.d.ts +28 -2
- package/dist/index.min.js +2 -2
- package/dist/index.min.js.map +1 -1
- package/dist/index.mjs +209 -109
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -4,7 +4,86 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
4
4
|
|
|
5
5
|
// package.json
|
|
6
6
|
var package_default = {
|
|
7
|
-
version: "1.4.0
|
|
7
|
+
version: "1.4.0"};
|
|
8
|
+
|
|
9
|
+
// src/constants/os.ts
|
|
10
|
+
var OS_DEFS = [
|
|
11
|
+
{ name: "WebOS", detect: /hpwOS/, versionPattern: /hpwOS\/([\d.]+)/ },
|
|
12
|
+
{ name: "Symbian", detect: /Symbian/, versionPattern: null },
|
|
13
|
+
{ name: "MeeGo", detect: /MeeGo/, versionPattern: null },
|
|
14
|
+
{ name: "BlackBerry", detect: /(BlackBerry|RIM)/, versionPattern: null },
|
|
15
|
+
{ name: "FreeBSD", detect: /FreeBSD/, versionPattern: null },
|
|
16
|
+
{ name: "Debian", detect: /Debian/, versionPattern: /Debian\/([\d.]+)/ },
|
|
17
|
+
{ name: "Ubuntu", detect: /Ubuntu/, versionPattern: null },
|
|
18
|
+
// Linux must come before Chrome OS: Chrome OS UAs contain "X11", so Linux matches first,
|
|
19
|
+
// then Chrome OS overrides it.
|
|
20
|
+
{ name: "Linux", detect: /(Linux|X11)/, versionPattern: null },
|
|
21
|
+
{ name: "Chrome OS", detect: /CrOS/, versionPattern: null },
|
|
22
|
+
{ name: "Tizen", detect: /Tizen/, versionPattern: /Tizen ([\d.]+)/ },
|
|
23
|
+
{ name: "iOS", detect: /like Mac OS X/, versionPattern: /OS ([\d_]+) like/ },
|
|
24
|
+
{
|
|
25
|
+
name: "MacOS",
|
|
26
|
+
detect: /Macintosh/,
|
|
27
|
+
versionPattern: /Mac OS X -?([\d_.]+)/,
|
|
28
|
+
versionNames: {
|
|
29
|
+
"10.9": "Mavericks",
|
|
30
|
+
"10.10": "Yosemite",
|
|
31
|
+
"10.11": "El Capitan",
|
|
32
|
+
"10.12": "Sierra",
|
|
33
|
+
"10.13": "High Sierra",
|
|
34
|
+
"10.14": "Mojave",
|
|
35
|
+
"10.15": "Catalina",
|
|
36
|
+
"11": "Big Sur",
|
|
37
|
+
"12": "Monterey",
|
|
38
|
+
"13": "Ventura",
|
|
39
|
+
"14": "Sonoma",
|
|
40
|
+
"15": "Sequoia"
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
// visionOS / tvOS must come AFTER iOS: their UAs also contain "like Mac OS X",
|
|
44
|
+
// so they need to override iOS via the last-match-wins iteration.
|
|
45
|
+
{ name: "visionOS", detect: /visionOS/, versionPattern: /visionOS ([\d_]+)/ },
|
|
46
|
+
{ name: "tvOS", detect: /Apple TV/, versionPattern: /OS ([\d_]+) like/ },
|
|
47
|
+
{ name: "Android", detect: /(Android|Adr)/, versionPattern: /(?:Android|Adr) ([\d.]+)/ },
|
|
48
|
+
// HarmonyOS must come after Android: HarmonyOS UAs include "Android", so Android matches
|
|
49
|
+
// first, then HarmonyOS overrides it. versionPattern tries direct extraction first (5.0+
|
|
50
|
+
// pure HarmonyOS UAs don't have Android token), then falls back to Android version + lookup.
|
|
51
|
+
{
|
|
52
|
+
name: "HarmonyOS",
|
|
53
|
+
detect: /HarmonyOS/,
|
|
54
|
+
versionPattern: [/HarmonyOS[\s/]([\d.]+)/, /Android ([\d.]+)[;)]/],
|
|
55
|
+
versionLookup: { "10": "2", "11": "3", "12": "3", "13": "4" }
|
|
56
|
+
},
|
|
57
|
+
// OpenHarmony (open-source base) must come after HarmonyOS to override any earlier match.
|
|
58
|
+
{ name: "OpenHarmony", detect: /OpenHarmony/, versionPattern: /OpenHarmony[\s/]([\d.]+)/ },
|
|
59
|
+
{ name: "KaiOS", detect: /KAIOS/, versionPattern: /KAIOS\/([\d.]+)/ },
|
|
60
|
+
// Windows must come before Windows Phone: Windows Phone UAs contain "Windows", so Windows
|
|
61
|
+
// matches first, then Windows Phone overrides it.
|
|
62
|
+
{
|
|
63
|
+
name: "Windows",
|
|
64
|
+
detect: /Windows/,
|
|
65
|
+
versionPattern: /Windows NT ([\d.]+)/,
|
|
66
|
+
versionLookup: {
|
|
67
|
+
"10": "10",
|
|
68
|
+
"6.4": "10",
|
|
69
|
+
"6.3": "8.1",
|
|
70
|
+
"6.2": "8",
|
|
71
|
+
"6.1": "7",
|
|
72
|
+
"6.0": "Vista",
|
|
73
|
+
"5.2": "XP",
|
|
74
|
+
"5.1": "XP",
|
|
75
|
+
"5.0": "2000"
|
|
76
|
+
},
|
|
77
|
+
versionNames: {
|
|
78
|
+
"7": "Windows 7",
|
|
79
|
+
"8": "Windows 8",
|
|
80
|
+
"8.1": "Windows 8.1",
|
|
81
|
+
"10": "Windows 10",
|
|
82
|
+
"11": "Windows 11"
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
{ name: "Windows Phone", detect: /(IEMobile|Windows Phone)/, versionPattern: /Windows Phone(?: OS)? ([\d.]+)/ }
|
|
86
|
+
];
|
|
8
87
|
|
|
9
88
|
// src/constants/browsers.ts
|
|
10
89
|
var BROWSER_DEFS = [
|
|
@@ -151,7 +230,7 @@ function detectBrowser(ua) {
|
|
|
151
230
|
}
|
|
152
231
|
}
|
|
153
232
|
}
|
|
154
|
-
if (!best) return { browser: "unknown", version: "unknown" };
|
|
233
|
+
if (!best) return { browser: "unknown", version: "unknown", browserType: "unknown", priority: 0 };
|
|
155
234
|
let version = null;
|
|
156
235
|
if (best.chromeLookup) {
|
|
157
236
|
version = lookupFromChromeVersion(ua, best.chromeLookup);
|
|
@@ -160,7 +239,9 @@ function detectBrowser(ua) {
|
|
|
160
239
|
const patterns = Array.isArray(best.versionPattern) ? best.versionPattern : [best.versionPattern];
|
|
161
240
|
version = extractVersionFromPatterns(ua, patterns);
|
|
162
241
|
}
|
|
163
|
-
|
|
242
|
+
const p = best.priority;
|
|
243
|
+
const browserType = p >= 500 ? "app" : p >= 300 ? "brand" : "browser";
|
|
244
|
+
return { browser: best.name, version: version != null ? version : "unknown", browserType, priority: p };
|
|
164
245
|
}
|
|
165
246
|
|
|
166
247
|
// src/constants/engines.ts
|
|
@@ -176,8 +257,17 @@ var ENGINE_DEFS = [
|
|
|
176
257
|
];
|
|
177
258
|
|
|
178
259
|
// src/detectors/engine.ts
|
|
260
|
+
var ENGINE_VERSION_RE = {
|
|
261
|
+
WebKit: /AppleWebKit\/([\d.]+)/,
|
|
262
|
+
Blink: /AppleWebKit\/([\d.]+)/,
|
|
263
|
+
ArkWeb: /AppleWebKit\/([\d.]+)/,
|
|
264
|
+
Gecko: /Gecko\/([\d.]+)/,
|
|
265
|
+
Trident: /Trident\/([\d.]+)/,
|
|
266
|
+
Presto: /Presto\/([\d.]+)/,
|
|
267
|
+
KHTML: /KHTML\/([\d.]+)/
|
|
268
|
+
};
|
|
179
269
|
function detectEngine(ua, browser, version) {
|
|
180
|
-
var _a, _b;
|
|
270
|
+
var _a, _b, _c, _d;
|
|
181
271
|
if (browser === void 0 || version === void 0) {
|
|
182
272
|
const b = detectBrowser(ua);
|
|
183
273
|
browser = browser != null ? browser : b.browser;
|
|
@@ -199,64 +289,19 @@ function detectEngine(ua, browser, version) {
|
|
|
199
289
|
if (browser === "Edge") {
|
|
200
290
|
engine = parseInt(version, 10) > 75 ? "Blink" : "EdgeHTML";
|
|
201
291
|
}
|
|
202
|
-
|
|
292
|
+
const engineVersion = ENGINE_VERSION_RE[engine] ? (_d = (_c = ENGINE_VERSION_RE[engine].exec(ua)) == null ? void 0 : _c[1]) != null ? _d : "unknown" : "unknown";
|
|
293
|
+
return { engine, engineVersion };
|
|
203
294
|
}
|
|
204
295
|
|
|
205
|
-
// src/constants/os.ts
|
|
206
|
-
var OS_DEFS = [
|
|
207
|
-
{ name: "WebOS", detect: /hpwOS/, versionPattern: /hpwOS\/([\d.]+)/ },
|
|
208
|
-
{ name: "Symbian", detect: /Symbian/, versionPattern: null },
|
|
209
|
-
{ name: "MeeGo", detect: /MeeGo/, versionPattern: null },
|
|
210
|
-
{ name: "BlackBerry", detect: /(BlackBerry|RIM)/, versionPattern: null },
|
|
211
|
-
{ name: "FreeBSD", detect: /FreeBSD/, versionPattern: null },
|
|
212
|
-
{ name: "Debian", detect: /Debian/, versionPattern: /Debian\/([\d.]+)/ },
|
|
213
|
-
{ name: "Ubuntu", detect: /Ubuntu/, versionPattern: null },
|
|
214
|
-
// Linux must come before Chrome OS: Chrome OS UAs contain "X11", so Linux matches first,
|
|
215
|
-
// then Chrome OS overrides it.
|
|
216
|
-
{ name: "Linux", detect: /(Linux|X11)/, versionPattern: null },
|
|
217
|
-
{ name: "Chrome OS", detect: /CrOS/, versionPattern: null },
|
|
218
|
-
{ name: "Tizen", detect: /Tizen/, versionPattern: /Tizen ([\d.]+)/ },
|
|
219
|
-
{ name: "iOS", detect: /like Mac OS X/, versionPattern: /OS ([\d_]+) like/ },
|
|
220
|
-
{ name: "MacOS", detect: /Macintosh/, versionPattern: /Mac OS X -?([\d_.]+)/ },
|
|
221
|
-
// visionOS / tvOS must come AFTER iOS: their UAs also contain "like Mac OS X",
|
|
222
|
-
// so they need to override iOS via the last-match-wins iteration.
|
|
223
|
-
{ name: "visionOS", detect: /visionOS/, versionPattern: /visionOS ([\d_]+)/ },
|
|
224
|
-
{ name: "tvOS", detect: /Apple TV/, versionPattern: /OS ([\d_]+) like/ },
|
|
225
|
-
{ name: "Android", detect: /(Android|Adr)/, versionPattern: /(?:Android|Adr) ([\d.]+)/ },
|
|
226
|
-
// HarmonyOS must come after Android: HarmonyOS UAs include "Android", so Android matches
|
|
227
|
-
// first, then HarmonyOS overrides it. versionPattern tries direct extraction first (5.0+
|
|
228
|
-
// pure HarmonyOS UAs don't have Android token), then falls back to Android version + lookup.
|
|
229
|
-
{
|
|
230
|
-
name: "HarmonyOS",
|
|
231
|
-
detect: /HarmonyOS/,
|
|
232
|
-
versionPattern: [/HarmonyOS[\s/]([\d.]+)/, /Android ([\d.]+)[;)]/],
|
|
233
|
-
versionLookup: { "10": "2", "11": "3", "12": "3", "13": "4" }
|
|
234
|
-
},
|
|
235
|
-
// OpenHarmony (open-source base) must come after HarmonyOS to override any earlier match.
|
|
236
|
-
{ name: "OpenHarmony", detect: /OpenHarmony/, versionPattern: /OpenHarmony[\s/]([\d.]+)/ },
|
|
237
|
-
{ name: "KaiOS", detect: /KAIOS/, versionPattern: /KAIOS\/([\d.]+)/ },
|
|
238
|
-
// Windows must come before Windows Phone: Windows Phone UAs contain "Windows", so Windows
|
|
239
|
-
// matches first, then Windows Phone overrides it.
|
|
240
|
-
{
|
|
241
|
-
name: "Windows",
|
|
242
|
-
detect: /Windows/,
|
|
243
|
-
versionPattern: /Windows NT ([\d.]+)/,
|
|
244
|
-
versionLookup: {
|
|
245
|
-
"10": "10",
|
|
246
|
-
"6.4": "10",
|
|
247
|
-
"6.3": "8.1",
|
|
248
|
-
"6.2": "8",
|
|
249
|
-
"6.1": "7",
|
|
250
|
-
"6.0": "Vista",
|
|
251
|
-
"5.2": "XP",
|
|
252
|
-
"5.1": "XP",
|
|
253
|
-
"5.0": "2000"
|
|
254
|
-
}
|
|
255
|
-
},
|
|
256
|
-
{ name: "Windows Phone", detect: /(IEMobile|Windows Phone)/, versionPattern: /Windows Phone(?: OS)? ([\d.]+)/ }
|
|
257
|
-
];
|
|
258
|
-
|
|
259
296
|
// src/detectors/os.ts
|
|
297
|
+
function lookupVersionName(map, version) {
|
|
298
|
+
const parts = version.split(".");
|
|
299
|
+
for (let len = parts.length; len >= 1; len--) {
|
|
300
|
+
const key = parts.slice(0, len).join(".");
|
|
301
|
+
if (Object.prototype.hasOwnProperty.call(map, key)) return map[key];
|
|
302
|
+
}
|
|
303
|
+
return "unknown";
|
|
304
|
+
}
|
|
260
305
|
function detectOs(ua, windowsVersion) {
|
|
261
306
|
let matchedDef = null;
|
|
262
307
|
for (const def of OS_DEFS) {
|
|
@@ -264,7 +309,7 @@ function detectOs(ua, windowsVersion) {
|
|
|
264
309
|
matchedDef = def;
|
|
265
310
|
}
|
|
266
311
|
}
|
|
267
|
-
if (!matchedDef) return { os: "unknown", osVersion: "unknown" };
|
|
312
|
+
if (!matchedDef) return { os: "unknown", osVersion: "unknown", osVersionName: "unknown" };
|
|
268
313
|
let osVersion = "unknown";
|
|
269
314
|
if (matchedDef.versionPattern) {
|
|
270
315
|
const raw = Array.isArray(matchedDef.versionPattern) ? extractVersionFromPatterns(ua, matchedDef.versionPattern) : extractVersion(ua, matchedDef.versionPattern);
|
|
@@ -288,7 +333,8 @@ function detectOs(ua, windowsVersion) {
|
|
|
288
333
|
if (matchedDef.name === "Windows" && windowsVersion) {
|
|
289
334
|
osVersion = windowsVersion;
|
|
290
335
|
}
|
|
291
|
-
|
|
336
|
+
const osVersionName = matchedDef.versionNames ? lookupVersionName(matchedDef.versionNames, osVersion) : "unknown";
|
|
337
|
+
return { os: matchedDef.name, osVersion, osVersionName };
|
|
292
338
|
}
|
|
293
339
|
|
|
294
340
|
// src/constants/devices.ts
|
|
@@ -353,57 +399,93 @@ function detectDevice(ua, nav) {
|
|
|
353
399
|
}
|
|
354
400
|
return (_b = (_a = hwDetect()) != null ? _a : uaDetect()) != null ? _b : "PC";
|
|
355
401
|
}
|
|
402
|
+
var VENDOR_MAP = [
|
|
403
|
+
[/^SM-|^GT-|^SGH-|^SCH-|^SHW-|^SPH-|^SAMSUNG /i, "Samsung"],
|
|
404
|
+
[/^Pixel |^Nexus /, "Google"],
|
|
405
|
+
[/^moto |^motorola /i, "Motorola"],
|
|
406
|
+
[/^HONOR /i, "Honor"],
|
|
407
|
+
[/^ELS-|^LYA-|^HMA-|^VOG-|^ANA-|^CLT-|^JNY-|^NOH-|^PLK-|^BAH-|^BKL-|^COL-|^DUB-|^FIG-|^KIW-|^MAR-|^VTR-|^WAS-/i, "Huawei"],
|
|
408
|
+
[/^CPH/, "OPPO"],
|
|
409
|
+
[/^RMX/, "Realme"],
|
|
410
|
+
[/^V\d{4}[A-Z]|^vivo /i, "Vivo"],
|
|
411
|
+
[/^iqoo/i, "Vivo"],
|
|
412
|
+
[/^Redmi |^POCO |^Mi /, "Xiaomi"],
|
|
413
|
+
[/^2\d{9}|^2\d{3}[A-Z]/, "Xiaomi"],
|
|
414
|
+
[/^OnePlus |^IN2|^KB2|^LE2/i, "OnePlus"],
|
|
415
|
+
[/^LM-|^LGE |^LG-/i, "LG"],
|
|
416
|
+
[/^HTC/i, "HTC"],
|
|
417
|
+
[/^Nokia/i, "Nokia"],
|
|
418
|
+
[/^XQ-/, "Sony"],
|
|
419
|
+
[/^ASUS_|^ZB6|^ZS6|^ZE[56]/i, "Asus"],
|
|
420
|
+
[/^Quest /i, "Meta"]
|
|
421
|
+
];
|
|
422
|
+
var ANDROID_MODEL_RE = /Android [0-9.]+;(?:\s*U;)?(?:\s*[a-z]{2}[-_][a-zA-Z]{2,4};)?\s*([^;)]+?)(?:\s+Build\/|[;)])/;
|
|
423
|
+
function detectVendorModel(ua) {
|
|
424
|
+
if (/visionOS/.test(ua)) return { vendor: "Apple", model: "Apple Vision Pro" };
|
|
425
|
+
if (/iPhone/.test(ua)) return { vendor: "Apple", model: "iPhone" };
|
|
426
|
+
if (/iPad/.test(ua)) return { vendor: "Apple", model: "iPad" };
|
|
427
|
+
if (/iPod/.test(ua)) return { vendor: "Apple", model: "iPod touch" };
|
|
428
|
+
const m = ANDROID_MODEL_RE.exec(ua);
|
|
429
|
+
if (m) {
|
|
430
|
+
const model = m[1].trim();
|
|
431
|
+
for (const [re, vendor] of VENDOR_MAP) {
|
|
432
|
+
if (re.test(model)) return { vendor, model };
|
|
433
|
+
}
|
|
434
|
+
return { vendor: "unknown", model };
|
|
435
|
+
}
|
|
436
|
+
return { vendor: "unknown", model: "unknown" };
|
|
437
|
+
}
|
|
356
438
|
|
|
357
439
|
// src/constants/bots.ts
|
|
358
440
|
var BOT_DEFS = [
|
|
359
441
|
// Search engines
|
|
360
|
-
{ name: "Googlebot", detect: /Googlebot
|
|
361
|
-
{ name: "Bingbot", detect: /(bingbot|BingPreview)
|
|
362
|
-
{ name: "Baiduspider", detect: /(Baiduspider|BaiduMobaider)
|
|
363
|
-
{ name: "Bytespider", detect: /Bytespider
|
|
364
|
-
{ name: "YandexBot", detect: /YandexBot
|
|
365
|
-
{ name: "DuckDuckBot", detect: /DuckDuckBot
|
|
366
|
-
{ name: "Slurp", detect: /Slurp
|
|
367
|
-
{ name: "Sogou", detect: /(Sogou|sogou).*[Ss]pider
|
|
368
|
-
{ name: "360Spider", detect: /360Spider
|
|
369
|
-
{ name: "PetalBot", detect: /PetalBot
|
|
370
|
-
{ name: "Applebot-Extended", detect: /Applebot-Extended
|
|
371
|
-
{ name: "Applebot", detect: /Applebot
|
|
442
|
+
{ name: "Googlebot", detect: /Googlebot/, category: "search-engine" },
|
|
443
|
+
{ name: "Bingbot", detect: /(bingbot|BingPreview)/, category: "search-engine" },
|
|
444
|
+
{ name: "Baiduspider", detect: /(Baiduspider|BaiduMobaider)/, category: "search-engine" },
|
|
445
|
+
{ name: "Bytespider", detect: /Bytespider/, category: "search-engine" },
|
|
446
|
+
{ name: "YandexBot", detect: /YandexBot/, category: "search-engine" },
|
|
447
|
+
{ name: "DuckDuckBot", detect: /DuckDuckBot/, category: "search-engine" },
|
|
448
|
+
{ name: "Slurp", detect: /Slurp/, category: "search-engine" },
|
|
449
|
+
{ name: "Sogou", detect: /(Sogou|sogou).*[Ss]pider/, category: "search-engine" },
|
|
450
|
+
{ name: "360Spider", detect: /360Spider/, category: "search-engine" },
|
|
451
|
+
{ name: "PetalBot", detect: /PetalBot/, category: "search-engine" },
|
|
452
|
+
{ name: "Applebot-Extended", detect: /Applebot-Extended/, category: "search-engine" },
|
|
453
|
+
{ name: "Applebot", detect: /Applebot/, category: "search-engine" },
|
|
372
454
|
// Social media crawlers
|
|
373
|
-
{ name: "Facebookbot", detect: /(facebookexternalhit|FacebookBot)
|
|
374
|
-
{ name: "Twitterbot", detect: /Twitterbot
|
|
375
|
-
{ name: "LinkedInBot", detect: /LinkedInBot
|
|
376
|
-
{ name: "PinterestBot", detect: /Pinterest
|
|
455
|
+
{ name: "Facebookbot", detect: /(facebookexternalhit|FacebookBot)/, category: "social" },
|
|
456
|
+
{ name: "Twitterbot", detect: /Twitterbot/, category: "social" },
|
|
457
|
+
{ name: "LinkedInBot", detect: /LinkedInBot/, category: "social" },
|
|
458
|
+
{ name: "PinterestBot", detect: /Pinterest/, category: "social" },
|
|
377
459
|
// Messaging link preview bots
|
|
378
|
-
{ name: "Slackbot", detect: /Slackbot
|
|
379
|
-
{ name: "Discordbot", detect: /Discordbot
|
|
380
|
-
{ name: "TelegramBot", detect: /TelegramBot
|
|
381
|
-
{ name: "WhatsApp", detect: /WhatsApp
|
|
460
|
+
{ name: "Slackbot", detect: /Slackbot/, category: "link-preview" },
|
|
461
|
+
{ name: "Discordbot", detect: /Discordbot/, category: "link-preview" },
|
|
462
|
+
{ name: "TelegramBot", detect: /TelegramBot/, category: "link-preview" },
|
|
463
|
+
{ name: "WhatsApp", detect: /WhatsApp/, category: "link-preview" },
|
|
382
464
|
// SEO tools
|
|
383
|
-
{ name: "SemrushBot", detect: /SemrushBot
|
|
384
|
-
{ name: "AhrefsBot", detect: /AhrefsBot
|
|
385
|
-
{ name: "MJ12bot", detect: /MJ12bot
|
|
386
|
-
{ name: "ScreamingFrog", detect: /Screaming Frog
|
|
387
|
-
{ name: "DataForSeoBot", detect: /DataForSeoBot
|
|
465
|
+
{ name: "SemrushBot", detect: /SemrushBot/, category: "seo-tool" },
|
|
466
|
+
{ name: "AhrefsBot", detect: /AhrefsBot/, category: "seo-tool" },
|
|
467
|
+
{ name: "MJ12bot", detect: /MJ12bot/, category: "seo-tool" },
|
|
468
|
+
{ name: "ScreamingFrog", detect: /Screaming Frog/, category: "seo-tool" },
|
|
469
|
+
{ name: "DataForSeoBot", detect: /DataForSeoBot/, category: "seo-tool" },
|
|
388
470
|
// AI / LLM crawlers
|
|
389
|
-
{ name: "GPTBot", detect: /GPTBot
|
|
390
|
-
{ name: "OAI-SearchBot", detect: /OAI-SearchBot
|
|
391
|
-
{ name: "ChatGPT-User", detect: /ChatGPT-User
|
|
392
|
-
{ name: "ClaudeBot", detect: /ClaudeBot
|
|
393
|
-
{ name: "PerplexityBot", detect: /PerplexityBot
|
|
394
|
-
{ name: "CCBot", detect: /CCBot
|
|
395
|
-
{ name: "AdsBot", detect: /AdsBot-Google
|
|
396
|
-
{ name: "Google-Extended", detect: /Google-Extended
|
|
397
|
-
{ name: "Meta-ExternalAgent", detect: /meta-externalagent/i },
|
|
398
|
-
{ name: "Amazonbot", detect: /Amazonbot
|
|
399
|
-
{ name: "Diffbot", detect: /Diffbot
|
|
400
|
-
{ name: "cohere-ai", detect: /cohere-ai
|
|
401
|
-
{ name: "YouBot", detect: /YouBot
|
|
471
|
+
{ name: "GPTBot", detect: /GPTBot/, category: "ai-llm" },
|
|
472
|
+
{ name: "OAI-SearchBot", detect: /OAI-SearchBot/, category: "ai-llm" },
|
|
473
|
+
{ name: "ChatGPT-User", detect: /ChatGPT-User/, category: "ai-llm" },
|
|
474
|
+
{ name: "ClaudeBot", detect: /ClaudeBot/, category: "ai-llm" },
|
|
475
|
+
{ name: "PerplexityBot", detect: /PerplexityBot/, category: "ai-llm" },
|
|
476
|
+
{ name: "CCBot", detect: /CCBot/, category: "ai-llm" },
|
|
477
|
+
{ name: "AdsBot", detect: /AdsBot-Google/, category: "ai-llm" },
|
|
478
|
+
{ name: "Google-Extended", detect: /Google-Extended/, category: "ai-llm" },
|
|
479
|
+
{ name: "Meta-ExternalAgent", detect: /meta-externalagent/i, category: "ai-llm" },
|
|
480
|
+
{ name: "Amazonbot", detect: /Amazonbot/, category: "ai-llm" },
|
|
481
|
+
{ name: "Diffbot", detect: /Diffbot/, category: "ai-llm" },
|
|
482
|
+
{ name: "cohere-ai", detect: /cohere-ai/, category: "ai-llm" },
|
|
483
|
+
{ name: "YouBot", detect: /YouBot/, category: "ai-llm" },
|
|
402
484
|
// Monitoring / archiving
|
|
403
|
-
{ name: "UptimeRobot", detect: /UptimeRobot
|
|
404
|
-
{ name: "ia_archiver", detect: /ia_archiver
|
|
485
|
+
{ name: "UptimeRobot", detect: /UptimeRobot/, category: "monitoring" },
|
|
486
|
+
{ name: "ia_archiver", detect: /ia_archiver/, category: "monitoring" },
|
|
405
487
|
// Generic catch-all (must be last)
|
|
406
|
-
{ name: "GenericBot", detect: /(bot|crawler|spider|crawling|scraper)/i }
|
|
488
|
+
{ name: "GenericBot", detect: /(bot|crawler|spider|crawling|scraper)/i, category: "generic" }
|
|
407
489
|
];
|
|
408
490
|
|
|
409
491
|
// src/detectors/bot.ts
|
|
@@ -411,10 +493,10 @@ function detectBot(ua, customDefs) {
|
|
|
411
493
|
const defs = customDefs ? [...BOT_DEFS.slice(0, -1), ...customDefs, BOT_DEFS[BOT_DEFS.length - 1]] : BOT_DEFS;
|
|
412
494
|
for (const def of defs) {
|
|
413
495
|
if (def.detect.test(ua)) {
|
|
414
|
-
return { isBot: true, botName: def.name };
|
|
496
|
+
return { isBot: true, botName: def.name, botCategory: def.category };
|
|
415
497
|
}
|
|
416
498
|
}
|
|
417
|
-
return { isBot: false, botName: "unknown" };
|
|
499
|
+
return { isBot: false, botName: "unknown", botCategory: "unknown" };
|
|
418
500
|
}
|
|
419
501
|
|
|
420
502
|
// src/constants/arch.ts
|
|
@@ -581,14 +663,15 @@ function parseUA(ua, options = {}) {
|
|
|
581
663
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
|
|
582
664
|
const effectiveNav = (_a = options.ctx) != null ? _a : options.nav;
|
|
583
665
|
const effectiveWindowsVersion = (_c = (_b = options.ctx) == null ? void 0 : _b.windowsVersion) != null ? _c : options.windowsVersion;
|
|
584
|
-
const { browser: rawBrowser, version: rawVersion } = detectBrowser(ua);
|
|
585
|
-
const { os: rawOs, osVersion: rawOsVersion } = detectOs(ua, effectiveWindowsVersion);
|
|
666
|
+
const { browser: rawBrowser, version: rawVersion, browserType } = detectBrowser(ua);
|
|
667
|
+
const { os: rawOs, osVersion: rawOsVersion, osVersionName } = detectOs(ua, effectiveWindowsVersion);
|
|
586
668
|
let os = rawOs;
|
|
587
669
|
let osVersion = rawOsVersion;
|
|
588
670
|
const device = detectDevice(ua, effectiveNav);
|
|
671
|
+
const { vendor, model } = detectVendorModel(ua);
|
|
589
672
|
const arch = detectArch(ua, (_d = options.ctx) != null ? _d : effectiveNav);
|
|
590
673
|
const nav = effectiveNav;
|
|
591
|
-
const { isBot, botName } = detectBot(ua, options.customBotDefs);
|
|
674
|
+
const { isBot, botName, botCategory } = detectBot(ua, options.customBotDefs);
|
|
592
675
|
const isHeadless = detectHeadless(ua);
|
|
593
676
|
const language = options.language || ((nav == null ? void 0 : nav.language) || (nav == null ? void 0 : nav.browserLanguage) ? getLanguage(nav) : "") || languageFromUA(ua);
|
|
594
677
|
const platform = (nav == null ? void 0 : nav.platform) || platformFromUA(ua);
|
|
@@ -685,22 +768,39 @@ function parseUA(ua, options = {}) {
|
|
|
685
768
|
}
|
|
686
769
|
}
|
|
687
770
|
}
|
|
688
|
-
const engine = detectEngine(ua, browser, version);
|
|
771
|
+
const { engine, engineVersion } = detectEngine(ua, browser, version);
|
|
689
772
|
const versionMajor = parseInt((_l = version.split(".")[0]) != null ? _l : "0", 10) || 0;
|
|
690
773
|
const connectionType = (_p = (_o = (_n = (_m = options.ctx) != null ? _m : options.nav) == null ? void 0 : _n.connection) == null ? void 0 : _o.effectiveType) != null ? _p : "unknown";
|
|
774
|
+
const finalOsVersionName = os === "MacOS" || os === "Windows" ? (() => {
|
|
775
|
+
var _a2;
|
|
776
|
+
const map = (_a2 = OS_DEFS.find((d) => d.name === os)) == null ? void 0 : _a2.versionNames;
|
|
777
|
+
if (!map) return "unknown";
|
|
778
|
+
const parts = osVersion.split(".");
|
|
779
|
+
for (let len = parts.length; len >= 1; len--) {
|
|
780
|
+
const key = parts.slice(0, len).join(".");
|
|
781
|
+
if (Object.prototype.hasOwnProperty.call(map, key)) return map[key];
|
|
782
|
+
}
|
|
783
|
+
return "unknown";
|
|
784
|
+
})() : osVersionName;
|
|
691
785
|
return {
|
|
692
786
|
browser,
|
|
693
787
|
version,
|
|
694
788
|
versionMajor,
|
|
789
|
+
browserType: browser === "Brave" ? "browser" : browserType,
|
|
695
790
|
engine,
|
|
791
|
+
engineVersion,
|
|
696
792
|
os,
|
|
697
793
|
osVersion,
|
|
794
|
+
osVersionName: finalOsVersionName,
|
|
698
795
|
device,
|
|
796
|
+
vendor,
|
|
797
|
+
model,
|
|
699
798
|
arch,
|
|
700
799
|
isWebview: isWebview(ua),
|
|
701
800
|
isHeadless,
|
|
702
801
|
isBot,
|
|
703
802
|
botName,
|
|
803
|
+
botCategory,
|
|
704
804
|
language,
|
|
705
805
|
platform,
|
|
706
806
|
connectionType
|
|
@@ -970,6 +1070,7 @@ exports.detectDevice = detectDevice;
|
|
|
970
1070
|
exports.detectEngine = detectEngine;
|
|
971
1071
|
exports.detectHeadless = detectHeadless;
|
|
972
1072
|
exports.detectOS = detectOs;
|
|
1073
|
+
exports.detectVendorModel = detectVendorModel;
|
|
973
1074
|
exports.getEnvContext = getEnvContext;
|
|
974
1075
|
exports.getLanguage = getLanguage;
|
|
975
1076
|
exports.getNavContext = getNavContext;
|