Break some methods in helpers as new submodules: bot-detection, browser-detection, device-detection

`isAIBot()` & `isBot()` => `bot-detection`
`isChromeFamily()`, `isElectron()`, `isFromEU()`, & `isStandalonePWA()` => `browser-detection`
`getDeviceVendor()` & `isAppleSilicon()` => `device-detection`
This commit is contained in:
Faisal Salman
2025-10-14 12:28:36 +07:00
parent 2d8c8fa142
commit a3a7a5e377
14 changed files with 550 additions and 314 deletions

View File

@@ -190,6 +190,21 @@
"import": "./src/main/ua-parser.mjs",
"types": "./src/main/ua-parser.d.ts"
},
"./bot-detection": {
"require": "./src/bot-detection/bot-detection.js",
"import": "./src/bot-detection/bot-detection.mjs",
"types": "./src/bot-detection/bot-detection.d.ts"
},
"./browser-detection": {
"require": "./src/browser-detection/browser-detection.js",
"import": "./src/browser-detection/browser-detection.mjs",
"types": "./src/browser-detection/browser-detection.d.ts"
},
"./device-detection": {
"require": "./src/device-detection/device-detection.js",
"import": "./src/device-detection/device-detection.mjs",
"types": "./src/device-detection/device-detection.d.ts"
},
"./enums": {
"require": "./src/enums/ua-parser-enums.js",
"import": "./src/enums/ua-parser-enums.mjs",

View File

@@ -40,6 +40,24 @@ const files = [
...defaultReplacements.mjs
]
},
{
src : 'src/bot-detection/bot-detection.js',
dest :'src/bot-detection/bot-detection.mjs',
title : 'Generated ESM version of ua-parser-js/bot-detection',
replacements : [...defaultReplacements.mjs]
},
{
src : 'src/browser-detection/browser-detection.js',
dest :'src/browser-detection/browser-detection.mjs',
title : 'Generated ESM version of ua-parser-js/browser-detection',
replacements : [...defaultReplacements.mjs]
},
{
src : 'src/device-detection/device-detection.js',
dest :'src/device-detection/device-detection.mjs',
title : 'Generated ESM version of ua-parser-js/device-detection',
replacements : [...defaultReplacements.mjs]
},
{
src : 'src/enums/ua-parser-enums.js',
dest :'src/enums/ua-parser-enums.mjs',

6
src/bot-detection/bot-detection.d.ts vendored Normal file
View File

@@ -0,0 +1,6 @@
// Type definitions for bot-detection submodule of UAParser.js v2.0.7
// Project: https://github.com/faisalman/ua-parser-js
// Definitions by: Faisal Salman <https://github.com/faisalman>
export function isAICrawler(ua: string): boolean;
export function isBot(ua: string): boolean;

View File

@@ -0,0 +1,125 @@
//////////////////////////////////////////////////
/* bot-detection submodule of UAParser.js v2.0.7
https://github.com/faisalman/ua-parser-js
Author: Faisal Salman <f@faisalman.com>
AGPLv3 License */
/////////////////////////////////////////////////
/*jshint esversion: 6 */
const { UAParser } = require('../main/ua-parser');
const { Extension, BrowserType } = require('../enums/ua-parser-enums');
const { Bots, Crawlers } = require('../extensions/ua-parser-extensions');
const { Crawler } = Extension.BrowserName;
const BotTypesList = [
BrowserType.CLI,
BrowserType.CRAWLER,
BrowserType.FETCHER,
BrowserType.LIBRARY
];
const AICrawlersList = [
// AI2
Crawler.AI2_BOT,
// Amazon
Crawler.AMAZON_BOT,
// Anthropic
Crawler.ANTHROPIC_AI,
Crawler.ANTHROPIC_CLAUDE_BOT,
Crawler.ANTHROPIC_CLAUDE_SEARCHBOT,
Crawler.ANTHROPIC_CLAUDE_WEB,
// Apple
Crawler.APPLE_BOT,
Crawler.APPLE_BOT_EXTENDED,
// Brave
Crawler.BRAVE_BOT,
// ByteDance
Crawler.BYTEDANCE_BYTESPIDER,
Crawler.BYTEDANCE_TIKTOKSPIDER,
// Cohere
Crawler.COHERE_TRAINING_DATA_CRAWLER,
// Common Crawl
Crawler.COMMON_CRAWL_CCBOT,
// Coveo
Crawler.COVEO_BOT,
// DataForSeo
Crawler.DATAFORSEO_BOT,
// DeepSeek
Crawler.DEEPSEEK_BOT,
// Diffbot
Crawler.DIFFBOT,
// Google
Crawler.GOOGLE_EXTENDED,
Crawler.GOOGLE_OTHER,
Crawler.GOOGLE_OTHER_IMAGE,
Crawler.GOOGLE_OTHER_VIDEO,
Crawler.GOOGLE_CLOUDVERTEXBOT,
// Hive AI
Crawler.HIVE_IMAGESIFTBOT,
// Huawei
Crawler.HUAWEI_PETALBOT,
Crawler.HUAWEI_PANGUBOT,
// Hugging Face
Crawler.HUGGINGFACE_BOT,
// Kangaroo
Crawler.KANGAROO_BOT,
// Mendable.ai
Crawler.FIRECRAWL_AGENT,
// Meta
Crawler.META_FACEBOOKBOT,
Crawler.META_EXTERNALAGENT,
// OpenAI
Crawler.OPENAI_GPTBOT,
Crawler.OPENAI_SEARCH_BOT,
// Perplexity
Crawler.PERPLEXITY_BOT,
// Replicate
Crawler.REPLICATE_BOT,
// Runpod
Crawler.RUNPOD_BOT,
// SB Intuitions
Crawler.SB_INTUITIONS_BOT,
// Semrush
Crawler.SEMRUSH_BOT_CONTENTSHAKE,
// Timpi
Crawler.TIMPI_BOT,
// Together AI
Crawler.TOGETHER_BOT,
// Velen.io
Crawler.HUNTER_VELENPUBLICWEBCRAWLER,
// Vercel
Crawler.VERCEL_V0BOT,
// Webz.io
Crawler.WEBZIO_OMGILI,
Crawler.WEBZIO_OMGILI_BOT,
Crawler.WEBZIO_EXTENDED,
// X
Crawler.XAI_BOT,
// You.com
Crawler.YOU_BOT,
// Zhipu AI
Crawler.ZHIPU_CHATGLM_SPIDER
];
const isAICrawler = ua =>
AICrawlersList
.map(s=>s.toLowerCase())
.includes(
(typeof ua === 'string' ?
new UAParser(ua, Crawlers).getBrowser() :
ua.browser
).name?.toLowerCase());
const isBot = ua =>
BotTypesList
.includes(
(typeof ua === 'string' ?
new UAParser(ua, Bots).getBrowser() :
ua.browser
).type);
module.exports = {
isAICrawler,
isBot
}

View File

@@ -0,0 +1,129 @@
// Generated ESM version of ua-parser-js/bot-detection
// DO NOT EDIT THIS FILE!
// Source: /src/bot-detection/bot-detection.js
//////////////////////////////////////////////////
/* bot-detection submodule of UAParser.js v2.0.7
https://github.com/faisalman/ua-parser-js
Author: Faisal Salman <f@faisalman.com>
AGPLv3 License */
/////////////////////////////////////////////////
/*jshint esversion: 6 */
import { UAParser } from '../main/ua-parser.mjs';
import { Extension, BrowserType } from '../enums/ua-parser-enums.mjs';
import { Bots, Crawlers, Fetchers } from '../extensions/ua-parser-extensions.mjs';
const { Crawler } = Extension.BrowserName;
const BotTypesList = [
BrowserType.CLI,
BrowserType.CRAWLER,
BrowserType.FETCHER,
BrowserType.LIBRARY
];
const AICrawlersList = [
// AI2
Crawler.AI2_BOT,
// Amazon
Crawler.AMAZON_BOT,
// Anthropic
Crawler.ANTHROPIC_AI,
Crawler.ANTHROPIC_CLAUDE_BOT,
Crawler.ANTHROPIC_CLAUDE_SEARCHBOT,
Crawler.ANTHROPIC_CLAUDE_WEB,
// Apple
Crawler.APPLE_BOT,
Crawler.APPLE_BOT_EXTENDED,
// Brave
Crawler.BRAVE_BOT,
// ByteDance
Crawler.BYTEDANCE_BYTESPIDER,
Crawler.BYTEDANCE_TIKTOKSPIDER,
// Cohere
Crawler.COHERE_TRAINING_DATA_CRAWLER,
// Common Crawl
Crawler.COMMON_CRAWL_CCBOT,
// Coveo
Crawler.COVEO_BOT,
// DataForSeo
Crawler.DATAFORSEO_BOT,
// DeepSeek
Crawler.DEEPSEEK_BOT,
// Diffbot
Crawler.DIFFBOT,
// Google
Crawler.GOOGLE_EXTENDED,
Crawler.GOOGLE_OTHER,
Crawler.GOOGLE_OTHER_IMAGE,
Crawler.GOOGLE_OTHER_VIDEO,
Crawler.GOOGLE_CLOUDVERTEXBOT,
// Hive AI
Crawler.HIVE_IMAGESIFTBOT,
// Huawei
Crawler.HUAWEI_PETALBOT,
Crawler.HUAWEI_PANGUBOT,
// Hugging Face
Crawler.HUGGINGFACE_BOT,
// Kangaroo
Crawler.KANGAROO_BOT,
// Mendable.ai
Crawler.FIRECRAWL_AGENT,
// Meta
Crawler.META_FACEBOOKBOT,
Crawler.META_EXTERNALAGENT,
// OpenAI
Crawler.OPENAI_GPTBOT,
Crawler.OPENAI_SEARCH_BOT,
// Perplexity
Crawler.PERPLEXITY_BOT,
// Replicate
Crawler.REPLICATE_BOT,
// Runpod
Crawler.RUNPOD_BOT,
// SB Intuitions
Crawler.SB_INTUITIONS_BOT,
// Semrush
Crawler.SEMRUSH_BOT_CONTENTSHAKE,
// Timpi
Crawler.TIMPI_BOT,
// Together AI
Crawler.TOGETHER_BOT,
// Velen.io
Crawler.HUNTER_VELENPUBLICWEBCRAWLER,
// Vercel
Crawler.VERCEL_V0BOT,
// Webz.io
Crawler.WEBZIO_OMGILI,
Crawler.WEBZIO_OMGILI_BOT,
Crawler.WEBZIO_EXTENDED,
// X
Crawler.XAI_BOT,
// You.com
Crawler.YOU_BOT,
// Zhipu AI
Crawler.ZHIPU_CHATGLM_SPIDER
];
const isAICrawler = ua =>
AICrawlersList
.map(s=>s.toLowerCase())
.includes(
(typeof ua === 'string' ?
new UAParser(ua, Crawlers).getBrowser() :
ua.browser
).name?.toLowerCase());
const isBot = ua =>
BotTypesList
.includes(
(typeof ua === 'string' ?
new UAParser(ua, Bots).getBrowser() :
ua.browser
).type);
export {
isAICrawler,
isBot
}

View File

@@ -0,0 +1,10 @@
// Type definitions for browser-detection submodule of UAParser.js v2.0.7
// Project: https://github.com/faisalman/ua-parser-js
// Definitions by: Faisal Salman <https://github.com/faisalman>
import type { IResult } from "../main/ua-parser";
export function isChromeFamily(resultOrUA: IResult | string): boolean;
export function isElectron(): boolean;
export function isFromEU(): boolean;
export function isStandalonePWA(): boolean;

View File

@@ -0,0 +1,28 @@
//////////////////////////////////////////////////////
/* browser-detection submodule of UAParser.js v2.0.7
https://github.com/faisalman/ua-parser-js
Author: Faisal Salman <f@faisalman.com>
AGPLv3 License */
/////////////////////////////////////////////////////
/*jshint esversion: 6 */
const { UAParser } = require('../main/ua-parser');
const { isStandalonePWA } = require('is-standalone-pwa');
const { isFromEU } = require('detect-europe-js');
const isChromeFamily = val => !!(
(typeof val === 'string' ?
new UAParser(val).getEngine() :
val.engine
)?.is(EngineName.BLINK));
const isElectron = () => !!(process?.versions?.hasOwnProperty('electron') || // node.js
/ electron\//i.test(navigator?.userAgent)); // browser
module.exports = {
isChromeFamily,
isElectron,
isFromEU,
isStandalonePWA
}

View File

@@ -0,0 +1,30 @@
// Generated ESM version of ua-parser-js/browser-detection
// DO NOT EDIT THIS FILE!
// Source: /src/browser-detection/browser-detection.js
//////////////////////////////////////////////////////
/* browser-detection submodule of UAParser.js v2.0.7
https://github.com/faisalman/ua-parser-js
Author: Faisal Salman <f@faisalman.com>
AGPLv3 License */
/////////////////////////////////////////////////////
/*jshint esversion: 6 */
import { UAParser } from '../main/ua-parser.mjs';
import { isStandalonePWA } from 'is-standalone-pwa';
const isChromeFamily = val => !!(
(typeof val === 'string' ?
new UAParser(val).getEngine() :
val.engine
)?.is(EngineName.BLINK));
const isElectron = () => !!(process?.versions?.hasOwnProperty('electron') || // node.js
/ electron\//i.test(navigator?.userAgent)); // browser
export {
isChromeFamily,
isElectron,
isStandalonePWA
}

View File

@@ -0,0 +1,8 @@
// Type definitions for device-detection submodule of UAParser.js v2.0.7
// Project: https://github.com/faisalman/ua-parser-js
// Definitions by: Faisal Salman <https://github.com/faisalman>
import type { IResult } from "../main/ua-parser";
export function getDeviceVendor(model: string): string | undefined;
export function isAppleSilicon(resultOrUA: IResult | string): boolean;

View File

@@ -0,0 +1,43 @@
/////////////////////////////////////////////////////
/* device-detection submodule of UAParser.js v2.0.7
https://github.com/faisalman/ua-parser-js
Author: Faisal Salman <f@faisalman.com>
AGPLv3 License */
////////////////////////////////////////////////////
/*jshint esversion: 6 */
const { UAParser } = require('../main/ua-parser');
const { CPUArch, OSName } = require('../enums/ua-parser-enums');
const getDeviceVendor = (model) => new UAParser(`Mozilla/5.0 (Linux; Android 10; ${model}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.0.0 Safari/537.36`).getDevice().vendor;
const isAppleSilicon = (val) => {
const { os, cpu } = typeof val !== 'string' ? val : {
os: new UAParser(val).getOS(),
cpu: new UAParser(val).getCPU()
};
if (os.is(OSName.MACOS)) {
if (cpu.is(CPUArch.ARM)) {
return true;
} else if (typeof window !== 'undefined') {
try {
const canvas = document.createElement('canvas');
const webgl = canvas.getContext('webgl2') ||
canvas.getContext('webgl') ||
canvas.getContext('experimental-webgl');
return webgl
.getParameter(webgl.getExtension('WEBGL_debug_renderer_info').UNMASKED_RENDERER_WEBGL)
.match(/apple m\d/i);
} catch {
return false;
}
}
}
return false;
}
module.exports = {
getDeviceVendor,
isAppleSilicon
}

View File

@@ -0,0 +1,47 @@
// Generated ESM version of ua-parser-js/device-detection
// DO NOT EDIT THIS FILE!
// Source: /src/device-detection/device-detection.js
/////////////////////////////////////////////////////
/* device-detection submodule of UAParser.js v2.0.7
https://github.com/faisalman/ua-parser-js
Author: Faisal Salman <f@faisalman.com>
AGPLv3 License */
////////////////////////////////////////////////////
/*jshint esversion: 6 */
import { UAParser } from '../main/ua-parser.mjs';
import { CPUArch, OSName } from '../enums/ua-parser-enums.mjs';
const getDeviceVendor = (model) => new UAParser(`Mozilla/5.0 (Linux; Android 10; ${model}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.0.0 Safari/537.36`).getDevice().vendor;
const isAppleSilicon = (val) => {
const { os, cpu } = typeof val !== 'string' ? val : {
os: new UAParser(val).getOS(),
cpu: new UAParser(val).getCPU()
};
if (os.is(OSName.MACOS)) {
if (cpu.is(CPUArch.ARM)) {
return true;
} else if (typeof window !== 'undefined') {
try {
const canvas = document.createElement('canvas');
const webgl = canvas.getContext('webgl2') ||
canvas.getContext('webgl') ||
canvas.getContext('experimental-webgl');
return webgl
.getParameter(webgl.getExtension('WEBGL_debug_renderer_info').UNMASKED_RENDERER_WEBGL)
.match(/apple m\d/i);
} catch {
return false;
}
}
}
return false;
}
export {
getDeviceVendor,
isAppleSilicon
}

View File

@@ -4,12 +4,37 @@
import type { IResult } from "../main/ua-parser";
export function getDeviceVendor(model: string): string | undefined;
export function isAppleSilicon(resultOrUA: IResult | string): boolean;
export function isAIBot(resultOrUA: IResult | string): boolean;
export function isBot(resultOrUA: IResult | string): boolean;
export function isChromeFamily(resultOrUA: IResult | string): boolean;
export function isElectron(): boolean;
export function isFromEU(): boolean;
export function isFrozenUA(ua: string): boolean;
export function isStandalonePWA(): boolean;
/**
* @deprecated Moved to `device-detection` submodule
*/
export function getDeviceVendor(model: string): string | undefined;
/**
* @deprecated Moved to `device-detection` submodule
*/
export function isAppleSilicon(resultOrUA: IResult | string): boolean;
/**
* @deprecated Moved to `bot-detection` submodule
*/
export function isAIBot(resultOrUA: IResult | string): boolean;
/**
* @deprecated Moved to `bot-detection` submodule
*/
export function isBot(resultOrUA: IResult | string): boolean;
/**
* @deprecated Moved to `browser-detection` submodule
*/
export function isChromeFamily(resultOrUA: IResult | string): boolean;
/**
* @deprecated Moved to `browser-detection` submodule
*/
export function isElectron(): boolean;
/**
* @deprecated Moved to `browser-detection` submodule
*/
export function isFromEU(): boolean;
/**
* @deprecated Moved to `browser-detection` submodule
*/
export function isStandalonePWA(): boolean;

View File

@@ -8,170 +8,54 @@
/*jshint esversion: 6 */
const { UAParser } = require('../main/ua-parser');
const { CPUArch, OSName, EngineName, Extension, BrowserType } = require('../enums/ua-parser-enums');
const { Bots, Crawlers } = require('../extensions/ua-parser-extensions');
const { isFromEU } = require('detect-europe-js');
const { EngineName } = require('../enums/ua-parser-enums');
const { getDeviceVendor: _getDeviceVendor, isAppleSilicon: _isAppleSilicon } = require('../device-detection/device-detection');
const { isBot: _isBot, isAICrawler } = require('../bot-detection/bot-detection');
const { isStandalonePWA: _isStandalonePWA } = require('../browser-detection/browser-detection');
const { isFromEU: _isFromEU } = require('../browser-detection/browser-detection');
const { isFrozenUA } = require('ua-is-frozen');
const { isStandalonePWA } = require('is-standalone-pwa');
const { Crawler } = Extension.BrowserName;
const toResult = (value, head, ext) => typeof value === 'string' ? UAParser(value, head, ext) : value;
/**
* @deprecated Moved to `device-detection` submodule
*/
const getDeviceVendor = _getDeviceVendor;
const getDeviceVendor = (model) => UAParser(`Mozilla/5.0 (Linux; Android 10; ${model}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.0.0 Safari/537.36`).device.vendor;
/**
* @deprecated Moved to `device-detection` submodule
*/
const isAppleSilicon = _isAppleSilicon;
const isAppleSilicon = (resultOrUA) => {
const res = toResult(resultOrUA);
if (res.os.is(OSName.MACOS)) {
if (res.cpu.is(CPUArch.ARM)) {
return true;
}
if (typeof resultOrUA !== 'string' && typeof window !== 'undefined') {
try {
const canvas = document.createElement('canvas');
const webgl = canvas.getContext('webgl2') || canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
const debug = webgl.getExtension('WEBGL_debug_renderer_info');
const renderer = webgl.getParameter(debug.UNMASKED_RENDERER_WEBGL);
if (renderer.match(/apple m\d/i)) {
return true;
}
} catch {
return false;
}
}
}
return false;
}
/**
* @deprecated Moved to `bot-detection` submodule
*/
const isAIBot = isAICrawler;
const isAIBot = (resultOrUA) => [
/**
* @deprecated Moved to `bot-detection` submodule
*/
const isBot = _isBot;
// AI2
Crawler.AI2_BOT,
// Amazon
Crawler.AMAZON_BOT,
// Anthropic
Crawler.ANTHROPIC_AI,
Crawler.ANTHROPIC_CLAUDE_BOT,
Crawler.ANTHROPIC_CLAUDE_SEARCHBOT,
Crawler.ANTHROPIC_CLAUDE_WEB,
// Apple
Crawler.APPLE_BOT,
Crawler.APPLE_BOT_EXTENDED,
// Brave
Crawler.BRAVE_BOT,
// ByteDance
Crawler.BYTEDANCE_BYTESPIDER,
Crawler.BYTEDANCE_TIKTOKSPIDER,
// Cohere
Crawler.COHERE_TRAINING_DATA_CRAWLER,
// Common Crawl
Crawler.COMMON_CRAWL_CCBOT,
// Coveo
Crawler.COVEO_BOT,
// DataForSeo
Crawler.DATAFORSEO_BOT,
// DeepSeek
Crawler.DEEPSEEK_BOT,
// Diffbot
Crawler.DIFFBOT,
// Google
Crawler.GOOGLE_EXTENDED,
Crawler.GOOGLE_OTHER,
Crawler.GOOGLE_OTHER_IMAGE,
Crawler.GOOGLE_OTHER_VIDEO,
Crawler.GOOGLE_CLOUDVERTEXBOT,
// Hive AI
Crawler.HIVE_IMAGESIFTBOT,
// Huawei
Crawler.HUAWEI_PETALBOT,
Crawler.HUAWEI_PANGUBOT,
// Hugging Face
Crawler.HUGGINGFACE_BOT,
// Kangaroo
Crawler.KANGAROO_BOT,
// Mendable.ai
Crawler.FIRECRAWL_AGENT,
// Meta
Crawler.META_FACEBOOKBOT,
Crawler.META_EXTERNALAGENT,
// OpenAI
Crawler.OPENAI_GPTBOT,
Crawler.OPENAI_SEARCH_BOT,
// Perplexity
Crawler.PERPLEXITY_BOT,
// Replicate
Crawler.REPLICATE_BOT,
// Runpod
Crawler.RUNPOD_BOT,
// SB Intuitions
Crawler.SB_INTUITIONS_BOT,
// Semrush
Crawler.SEMRUSH_BOT_CONTENTSHAKE,
// Timpi
Crawler.TIMPI_BOT,
// Together AI
Crawler.TOGETHER_BOT,
// Velen.io
Crawler.HUNTER_VELENPUBLICWEBCRAWLER,
// Vercel
Crawler.VERCEL_V0BOT,
// Webz.io
Crawler.WEBZIO_OMGILI,
Crawler.WEBZIO_OMGILI_BOT,
Crawler.WEBZIO_EXTENDED,
// X
Crawler.XAI_BOT,
// You.com
Crawler.YOU_BOT,
// Zhipu AI
Crawler.ZHIPU_CHATGLM_SPIDER
]
.map((s) => s.toLowerCase())
.includes(String(toResult(resultOrUA, Crawlers).browser.name).toLowerCase());
const isBot = (resultOrUA) => [
BrowserType.CLI,
BrowserType.CRAWLER,
BrowserType.FETCHER,
BrowserType.LIBRARY
].includes(toResult(resultOrUA, Bots).browser.type);
const isChromeFamily = (resultOrUA) => toResult(resultOrUA).engine.is(EngineName.BLINK);
/**
* @deprecated Moved to `browser-detection` submodule
*/
const isChromeFamily = val => !!((typeof val === 'string' ? new UAParser(val).getEngine() : val.engine)?.is(EngineName.BLINK));
/**
* @deprecated Moved to `browser-detection` submodule
*/
const isElectron = () => !!(process?.versions?.hasOwnProperty('electron') || // node.js
/ electron\//i.test(navigator?.userAgent)); // browser
/**
* @deprecated Moved to `browser-detection` submodule
*/
const isFromEU = _isFromEU;
/**
* @deprecated Moved to `browser-detection` submodule
*/
const isStandalonePWA = _isStandalonePWA;
module.exports = {
getDeviceVendor,
isAppleSilicon,

View File

@@ -12,166 +12,34 @@
/*jshint esversion: 6 */
import { UAParser } from '../main/ua-parser.mjs';
import { CPUArch, OSName, EngineName, Extension, BrowserType } from '../enums/ua-parser-enums.mjs';
import { Bots, Crawlers } from '../extensions/ua-parser-extensions.mjs';
import { EngineName } from '../enums/ua-parser-enums.mjs';
import { getDeviceVendor: _getDeviceVendor, isAppleSilicon: _isAppleSilicon } from '../device-detection/device-detection.mjs';
import { isBot: _isBot, isAICrawler } from '../bot-detection/bot-detection.mjs';
import { isFromEU } from 'detect-europe-js';
import { isFrozenUA } from 'ua-is-frozen';
import { isStandalonePWA } from 'is-standalone-pwa';
const { Crawler } = Extension.BrowserName;
const toResult = (value, head, ext) => typeof value === 'string' ? UAParser(value, head, ext) : value;
/**
* @deprecated Moved to `device-detection` submodule
*/
const getDeviceVendor = _getDeviceVendor;
const getDeviceVendor = (model) => UAParser(`Mozilla/5.0 (Linux; Android 10; ${model}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.0.0 Safari/537.36`).device.vendor;
/**
* @deprecated Moved to `device-detection` submodule
*/
const isAppleSilicon = _isAppleSilicon;
const isAppleSilicon = (resultOrUA) => {
const res = toResult(resultOrUA);
if (res.os.is(OSName.MACOS)) {
if (res.cpu.is(CPUArch.ARM)) {
return true;
}
if (typeof resultOrUA !== 'string' && typeof window !== 'undefined') {
try {
const canvas = document.createElement('canvas');
const webgl = canvas.getContext('webgl2') || canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
const debug = webgl.getExtension('WEBGL_debug_renderer_info');
const renderer = webgl.getParameter(debug.UNMASKED_RENDERER_WEBGL);
if (renderer.match(/apple m\d/i)) {
return true;
}
} catch {
return false;
}
}
}
return false;
}
/**
* @deprecated Moved to `bot-detection` submodule
*/
const isAIBot = isAICrawler;
const isAIBot = (resultOrUA) => [
/**
* @deprecated Moved to `bot-detection` submodule
*/
const isBot = _isBot;
// AI2
Crawler.AI2_BOT,
// Amazon
Crawler.AMAZON_BOT,
// Anthropic
Crawler.ANTHROPIC_AI,
Crawler.ANTHROPIC_CLAUDE_BOT,
Crawler.ANTHROPIC_CLAUDE_SEARCHBOT,
Crawler.ANTHROPIC_CLAUDE_WEB,
// Apple
Crawler.APPLE_BOT,
Crawler.APPLE_BOT_EXTENDED,
// Brave
Crawler.BRAVE_BOT,
// ByteDance
Crawler.BYTEDANCE_BYTESPIDER,
Crawler.BYTEDANCE_TIKTOKSPIDER,
// Cohere
Crawler.COHERE_TRAINING_DATA_CRAWLER,
// Common Crawl
Crawler.COMMON_CRAWL_CCBOT,
// Coveo
Crawler.COVEO_BOT,
// DataForSeo
Crawler.DATAFORSEO_BOT,
// DeepSeek
Crawler.DEEPSEEK_BOT,
// Diffbot
Crawler.DIFFBOT,
// Google
Crawler.GOOGLE_EXTENDED,
Crawler.GOOGLE_OTHER,
Crawler.GOOGLE_OTHER_IMAGE,
Crawler.GOOGLE_OTHER_VIDEO,
Crawler.GOOGLE_CLOUDVERTEXBOT,
// Hive AI
Crawler.HIVE_IMAGESIFTBOT,
// Huawei
Crawler.HUAWEI_PETALBOT,
Crawler.HUAWEI_PANGUBOT,
// Hugging Face
Crawler.HUGGINGFACE_BOT,
// Kangaroo
Crawler.KANGAROO_BOT,
// Mendable.ai
Crawler.FIRECRAWL_AGENT,
// Meta
Crawler.META_FACEBOOKBOT,
Crawler.META_EXTERNALAGENT,
// OpenAI
Crawler.OPENAI_GPTBOT,
Crawler.OPENAI_SEARCH_BOT,
// Perplexity
Crawler.PERPLEXITY_BOT,
// Replicate
Crawler.REPLICATE_BOT,
// Runpod
Crawler.RUNPOD_BOT,
// SB Intuitions
Crawler.SB_INTUITIONS_BOT,
// Semrush
Crawler.SEMRUSH_BOT_CONTENTSHAKE,
// Timpi
Crawler.TIMPI_BOT,
// Together AI
Crawler.TOGETHER_BOT,
// Velen.io
Crawler.HUNTER_VELENPUBLICWEBCRAWLER,
// Vercel
Crawler.VERCEL_V0BOT,
// Webz.io
Crawler.WEBZIO_OMGILI,
Crawler.WEBZIO_OMGILI_BOT,
Crawler.WEBZIO_EXTENDED,
// X
Crawler.XAI_BOT,
// You.com
Crawler.YOU_BOT,
// Zhipu AI
Crawler.ZHIPU_CHATGLM_SPIDER
]
.map((s) => s.toLowerCase())
.includes(String(toResult(resultOrUA, Crawlers).browser.name).toLowerCase());
const isBot = (resultOrUA) => [
BrowserType.CLI,
BrowserType.CRAWLER,
BrowserType.FETCHER,
BrowserType.LIBRARY
].includes(toResult(resultOrUA, Bots).browser.type);
const isChromeFamily = (resultOrUA) => toResult(resultOrUA).engine.is(EngineName.BLINK);
const isChromeFamily = val => !!((typeof val === 'string' ? new UAParser(val).getEngine() : val.engine)?.is(EngineName.BLINK));
const isElectron = () => !!(process?.versions?.hasOwnProperty('electron') || // node.js
/ electron\//i.test(navigator?.userAgent)); // browser