初始化环境文件

This commit is contained in:
CN-JS-HuiBai
2026-04-04 12:49:09 +08:00
parent 07742d2688
commit c607af6fac
5971 changed files with 515160 additions and 18 deletions

39
node_modules/bowser/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,39 @@
Copyright 2015, Dustin Diaz (the "Original Author")
All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
Distributions of all or part of the Software intended to be used
by the recipients as they would use the unmodified Software,
containing modifications that substantially alter, remove, or
disable functionality of the Software, outside of the documented
configuration mechanisms provided by the Software, shall be
modified such that the Original Author's bug reporting email
addresses and urls are either replaced with the contact information
of the parties responsible for the changes, or removed entirely.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
Except where noted, this license applies to any and all software
programs and associated documentation files created by the
Original Author, when distributed with the Software.

246
node_modules/bowser/README.md generated vendored Normal file
View File

@@ -0,0 +1,246 @@
## Bowser
A small, fast and rich-API browser/platform/engine detector for both browser and node.
- **Small.** Use plain ES5-version which is ~4.8kB gzipped.
- **Optimized.** Use only those parsers you need — it doesn't do useless work.
- **Multi-platform.** It's browser- and node-ready, so you can use it in any environment.
Don't hesitate to support the project on Github or [OpenCollective](https://opencollective.com/bowser) if you like it ❤️ Also, contributors are always welcome!
[![Financial Contributors on Open Collective](https://opencollective.com/bowser/all/badge.svg?label=financial+contributors)](https://opencollective.com/bowser) ![Downloads](https://img.shields.io/npm/dm/bowser)
# Contents
- [Overview](#overview)
- [Use cases](#use-cases)
- [Browser props detection](#browser-props-detection)
- [Using User-Agent Client Hints](#using-user-agent-client-hints)
- [Filtering browsers](#filtering-browsers)
# Overview
The library is made to help to detect what browser your user has and gives you a convenient API to filter the users somehow depending on their browsers. Check it out on this page: https://bowser-js.github.io/bowser-online/.
### ⚠️ Version 2.0 breaking changes ⚠️
Version 2.0 has drastically changed the API. All available methods are on the [docs page](https://bowser-js.github.io/bowser/docs/).
_For legacy code, check out the [1.x](https://github.com/bowser-js/bowser/tree/v1.x) branch and install it through `npm install bowser@1.9.4`._
# Use cases
First of all, require the library. This is a UMD Module, so it will work for AMD, TypeScript, ES6, and CommonJS module systems.
```javascript
const Bowser = require("bowser"); // CommonJS
import * as Bowser from "bowser"; // TypeScript
import Bowser from "bowser"; // ES6 (and TypeScript with --esModuleInterop enabled)
```
By default, the exported version is the *ES5 transpiled version*, which **do not** include any polyfills.
In case you don't use your own `babel-polyfill` you may need to have pre-built bundle with all needed polyfills.
So, for you it's suitable to require bowser like this: `require('bowser/bundled')`.
As the result, you get a ES5 version of bowser with `babel-polyfill` bundled together.
You may need to use the source files, so they will be available in the package as well.
## Browser props detection
Often we need to pick users' browser properties such as the name, the version, the rendering engine and so on. Here is an example how to do it with Bowser:
```javascript
const browser = Bowser.getParser(window.navigator.userAgent);
console.log(`The current browser name is "${browser.getBrowserName()}"`);
// The current browser name is "Internet Explorer"
```
### Using User-Agent Client Hints
Modern browsers support [User-Agent Client Hints](https://developer.mozilla.org/en-US/docs/Web/API/User-Agent_Client_Hints_API), which provide a more privacy-friendly and structured way to access browser information. Bowser can use Client Hints data to improve browser detection accuracy.
```javascript
// Pass Client Hints as the second parameter
const browser = Bowser.getParser(
window.navigator.userAgent,
window.navigator.userAgentData
);
console.log(`The current browser name is "${browser.getBrowserName()}"`);
// More accurate detection using Client Hints
```
#### Working with Client Hints
Bowser provides methods to access and query Client Hints data:
```javascript
const browser = Bowser.getParser(
window.navigator.userAgent,
window.navigator.userAgentData
);
// Get the full Client Hints object
const hints = browser.getHints();
// Returns the ClientHints object or null if not provided
// Check if a specific brand exists
if (browser.hasBrand('Google Chrome')) {
console.log('This is Chrome!');
}
// Get the version of a specific brand
const chromeVersion = browser.getBrandVersion('Google Chrome');
console.log(`Chrome version: ${chromeVersion}`);
```
The Client Hints object structure:
```javascript
{
brands: [
{ brand: 'Google Chrome', version: '131' },
{ brand: 'Chromium', version: '131' },
{ brand: 'Not_A Brand', version: '24' }
],
mobile: false,
platform: 'Windows',
platformVersion: '15.0.0',
architecture: 'x86',
model: '',
wow64: false
}
```
**Note:** Client Hints improve detection for browsers like DuckDuckGo and other Chromium-based browsers that may have similar User-Agent strings. When Client Hints are not provided, Bowser falls back to standard User-Agent string parsing.
or
```javascript
const browser = Bowser.getParser(window.navigator.userAgent);
console.log(browser.getBrowser());
// outputs
{
name: "Internet Explorer"
version: "11.0"
}
```
or
```javascript
console.log(Bowser.parse(window.navigator.userAgent));
// outputs
{
browser: {
name: "Internet Explorer"
version: "11.0"
},
os: {
name: "Windows"
version: "NT 6.3"
versionName: "8.1"
},
platform: {
type: "desktop"
},
engine: {
name: "Trident"
version: "7.0"
}
}
```
You can also use `Bowser.parse()` with Client Hints:
```javascript
console.log(Bowser.parse(window.navigator.userAgent, window.navigator.userAgentData));
// Same output structure, but with enhanced detection from Client Hints
```
## Filtering browsers
You could want to filter some particular browsers to provide any special support for them or make any workarounds.
It could look like this:
```javascript
const browser = Bowser.getParser(window.navigator.userAgent);
const isValidBrowser = browser.satisfies({
// declare browsers per OS
windows: {
"internet explorer": ">10",
},
macos: {
safari: ">10.1"
},
// per platform (mobile, desktop or tablet)
mobile: {
safari: '>=9',
'android browser': '>3.10'
},
// or in general
chrome: "~20.1.1432",
firefox: ">31",
opera: ">=22",
// also supports equality operator
chrome: "=20.1.1432", // will match particular build only
// and loose-equality operator
chrome: "~20", // will match any 20.* sub-version
chrome: "~20.1" // will match any 20.1.* sub-version (20.1.19 as well as 20.1.12.42-alpha.1)
});
```
Settings for any particular OS or platform has more priority and redefines settings of standalone browsers.
Thus, you can define OS or platform specific rules and they will have more priority in the end.
More of API and possibilities you will find in the `docs` folder.
### Browser names for `.satisfies()`
By default you are supposed to use the full browser name for `.satisfies`.
But, there's a short way to define a browser using short aliases. The full
list of aliases can be found in [the file](src/constants.js).
## Similar Projects
* [Kong](https://github.com/BigBadBleuCheese/Kong) - A C# port of Bowser.
## Contributors
### Code Contributors
This project exists thanks to all the people who contribute. [[Contribute](.github/CONTRIBUTING.md)].
<a href="https://github.com/bowser-js/bowser/graphs/contributors"><img src="https://opencollective.com/bowser/contributors.svg?width=890&button=false" /></a>
### Financial Contributors
Become a financial contributor and help us sustain our community. [[Contribute](https://opencollective.com/bowser/contribute)]
#### Individuals
<a href="https://opencollective.com/bowser"><img src="https://opencollective.com/bowser/individuals.svg?width=890"></a>
#### Organizations
Support this project with your organization. Your logo will show up here with a link to your website. [[Contribute](https://opencollective.com/bowser/contribute)]
<a href="https://opencollective.com/bowser/organization/0/website"><img src="https://opencollective.com/bowser/organization/0/avatar.svg"></a>
<a href="https://opencollective.com/bowser/organization/1/website"><img src="https://opencollective.com/bowser/organization/1/avatar.svg"></a>
<a href="https://opencollective.com/bowser/organization/2/website"><img src="https://opencollective.com/bowser/organization/2/avatar.svg"></a>
<a href="https://opencollective.com/bowser/organization/3/website"><img src="https://opencollective.com/bowser/organization/3/avatar.svg"></a>
<a href="https://opencollective.com/bowser/organization/4/website"><img src="https://opencollective.com/bowser/organization/4/avatar.svg"></a>
<a href="https://opencollective.com/bowser/organization/5/website"><img src="https://opencollective.com/bowser/organization/5/avatar.svg"></a>
<a href="https://opencollective.com/bowser/organization/6/website"><img src="https://opencollective.com/bowser/organization/6/avatar.svg"></a>
<a href="https://opencollective.com/bowser/organization/7/website"><img src="https://opencollective.com/bowser/organization/7/avatar.svg"></a>
<a href="https://opencollective.com/bowser/organization/8/website"><img src="https://opencollective.com/bowser/organization/8/avatar.svg"></a>
<a href="https://opencollective.com/bowser/organization/9/website"><img src="https://opencollective.com/bowser/organization/9/avatar.svg"></a>
## License
Licensed as MIT. All rights not explicitly granted in the MIT license are reserved. See the included LICENSE file for more details.

1
node_modules/bowser/bundled.js generated vendored Normal file

File diff suppressed because one or more lines are too long

1
node_modules/bowser/es5.js generated vendored Normal file

File diff suppressed because one or more lines are too long

353
node_modules/bowser/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,353 @@
// Type definitions for Bowser v2
// Project: https://github.com/bowser-js/bowser
// Definitions by: Alexander P. Cerutti <https://github.com/alexandercerutti>,
export = Bowser;
export as namespace Bowser;
declare namespace Bowser {
/**
* User-Agent Client Hints data structure
* @see https://developer.mozilla.org/en-US/docs/Web/API/NavigatorUAData
*/
interface ClientHints {
brands?: Array<{ brand: string; version: string }>;
mobile?: boolean;
platform?: string;
platformVersion?: string;
architecture?: string;
model?: string;
wow64?: boolean;
}
/**
* Creates a Parser instance
* @param {string} UA - User agent string
* @param {boolean | ClientHints} skipParsingOrHints - Either skip parsing flag or Client Hints
* @param {ClientHints} clientHints - User-Agent Client Hints data
*/
function getParser(UA: string, skipParsing?: boolean): Parser.Parser;
function getParser(UA: string, clientHints?: ClientHints): Parser.Parser;
function getParser(UA: string, skipParsing?: boolean, clientHints?: ClientHints): Parser.Parser;
/**
* Creates a Parser instance and runs Parser.getResult immediately
* @param UA - User agent string
* @param clientHints - User-Agent Client Hints data
* @returns {Parser.ParsedResult}
*/
function parse(UA: string, clientHints?: ClientHints): Parser.ParsedResult;
/**
* Constants exposed via bowser getters
*/
const BROWSER_MAP: Record<string, string>;
const ENGINE_MAP: Record<string, string>;
const OS_MAP: Record<string, string>;
const PLATFORMS_MAP: Record<string, string>;
namespace Parser {
interface Parser {
constructor(UA: string, skipParsing?: boolean): Parser.Parser;
constructor(UA: string, clientHints?: ClientHints): Parser.Parser;
constructor(UA: string, skipParsing?: boolean, clientHints?: ClientHints): Parser.Parser;
/**
* Get Client Hints data
* @return {ClientHints|null}
*/
getHints(): ClientHints | null;
/**
* Check if a brand exists in Client Hints brands array
* @param {string} brandName The brand name to check for
* @return {boolean}
*/
hasBrand(brandName: string): boolean;
/**
* Get brand version from Client Hints
* @param {string} brandName The brand name to get version for
* @return {string|undefined}
*/
getBrandVersion(brandName: string): string | undefined;
/**
* Check if the version is equals the browser version
* @param version The string to compare with the browser version
* @returns {boolean}
*/
compareVersion(version: string): boolean;
/**
* Get parsed browser object
* @return {BrowserDetails} Browser's details
*/
getBrowser(): BrowserDetails;
/**
* Get browser's name
* @param {Boolean} [toLowerCase] return lower-cased value
* @return {String} Browser's name or an empty string
*/
getBrowserName(toLowerCase?: boolean): string;
/**
* Get browser's version
* @return {String} version of browser
*/
getBrowserVersion(): string | undefined;
/**
* Get OS
* @return {OSDetails} - OS Details
*
* @example
* this.getOS(); // {
* // name: 'macOS',
* // version: '10.11.12',
* // }
*/
getOS(): OSDetails;
/**
* Get OS name
* @param {Boolean} [toLowerCase] return lower-cased value
* @return {String} name of the OS — macOS, Windows, Linux, etc.
*/
getOSName(toLowerCase?: boolean): string;
/**
* Get OS version
* @return {String} full version with dots ('10.11.12', '5.6', etc)
*/
getOSVersion(): string;
/**
* Get parsed platform
* @returns {PlatformDetails}
*/
getPlatform(): PlatformDetails;
/**
* Get platform name
* @param {boolean} toLowerCase
*/
getPlatformType(toLowerCase?: boolean): string;
/**
* Get parsed engine
* @returns {EngineDetails}
*/
getEngine(): EngineDetails;
/**
* Get parsed engine's name
* @returns {String} Engine's name or an empty string
*/
getEngineName(): string;
/**
* Get parsed result
* @return {ParsedResult}
*/
getResult(): ParsedResult;
/**
* Get UserAgent string of current Parser instance
* @return {String} User-Agent String of the current <Parser> object
*/
getUA(): string;
/**
* Is anything? Check if the browser is called "anything",
* the OS called "anything" or the platform called "anything"
* @param {String} anything
* @param [includingAlias=false] The flag showing whether alias will be included into comparison
* @returns {Boolean}
*/
is(anything: any, includingAlias?: boolean): boolean;
/**
* Check if the browser name equals the passed string
* @param browserName The string to compare with the browser name
* @param [includingAlias=false] The flag showing whether alias will be included into comparison
* @returns {boolean}
*/
isBrowser(browserName: string, includingAlias?: boolean): boolean;
/**
* Check if the engine name equals the passed string
* @param engineName The string to compare with the engine name
* @returns {boolean}
*/
isEngine(engineName: string): boolean;
/**
* Check if the OS name equals the passed string
* @param OSName The string to compare with the OS name
* @returns {boolean}
*/
isOS(OSName: string): boolean;
/**
* Check if the platform name equals the passed string
* @param platformName The string to compare with the platform name
* @returns {boolean}
*/
isPlatform(platformName: string): boolean;
/**
* Parse full information about the browser
* @returns {Parser.Parser}
*/
parse(): Parser.Parser;
/**
* Get parsed browser object
* @returns {BrowserDetails}
*/
parseBrowser(): BrowserDetails;
/**
* Get parsed engine
* @returns {EngineDetails}
*/
parseEngine(): EngineDetails;
/**
* Parse OS and save it to this.parsedResult.os
* @returns {OSDetails}
*/
parseOS(): OSDetails;
/**
* Get parsed platform
* @returns {PlatformDetails}
*/
parsePlatform(): PlatformDetails;
/**
* Check if parsed browser matches certain conditions
*
* @param {checkTree} checkTree It's one or two layered object,
* which can include a platform or an OS on the first layer
* and should have browsers specs on the bottom-laying layer
*
* @returns {Boolean|undefined} Whether the browser satisfies the set conditions or not.
* Returns `undefined` when the browser is no described in the checkTree object.
*
* @example
* const browser = new Bowser(UA);
* if (browser.check({chrome: '>118.01.1322' }))
* // or with os
* if (browser.check({windows: { chrome: '>118.01.1322' } }))
* // or with platforms
* if (browser.check({desktop: { chrome: '>118.01.1322' } }))
*/
satisfies(checkTree: checkTree): boolean | undefined;
/**
* Check if the browser name equals the passed string
* @param {string} browserName The string to compare with the browser name
* @param [includingAlias=false] The flag showing whether alias will be included into comparison
* @returns {boolean}
*/
isBrowser(browserName: string, includingAlias?: boolean): boolean;
/**
* Check if the engine name equals the passed string
* @param {string} engineName The string to compare with the engine name
* @returns {boolean}
*/
isEngine(engineName: string): boolean;
/**
* Check if the platform type equals the passed string
* @param {string} platformType The string to compare with the platform type
* @returns {boolean}
*/
isPlatform(platformType: string): boolean;
/**
* Check if the OS name equals the passed string
* @param {string} osName The string to compare with the OS name
* @returns {boolean}
*/
isOS(osName: string): boolean;
/**
* Check if any of the given values satisfies `.is(anything)`
* @param {string[]} anythings
* @returns {boolean} true if at least one condition is satisfied, false otherwise.
*/
some(anythings: string[]): boolean | undefined;
/**
* Test a UA string for a regexp
* @param regex
* @returns {boolean} true if the regex matches the UA, false otherwise.
*/
test(regex: RegExp): boolean;
}
interface ParsedResult {
browser: BrowserDetails;
os: OSDetails;
platform: PlatformDetails;
engine: EngineDetails;
}
interface Details {
name?: string;
version?: string;
}
interface OSDetails extends Details {
versionName?: string;
}
interface PlatformDetails {
type?: string;
vendor?: string;
model?: string;
}
type BrowserDetails = Details;
type EngineDetails = Details;
interface checkTree {
[key: string]: any;
}
}
}

93
node_modules/bowser/package.json generated vendored Normal file
View File

@@ -0,0 +1,93 @@
{
"name": "bowser",
"description": "Lightweight browser detector",
"files": [
"src/",
"es5.js",
"bundled.js",
"index.d.ts"
],
"keywords": [
"browser",
"useragent",
"user-agent",
"parser",
"ua",
"detection",
"ender",
"sniff"
],
"homepage": "https://github.com/bowser-js/bowser",
"author": "Dustin Diaz <dustin@dustindiaz.com> (http://dustindiaz.com)",
"contributors": [
{
"name": "Denis Demchenko",
"url": "http://twitter.com/lancedikson"
},
{
"name": "Naor Peled",
"url": "https://github.com/naorpeled"
}
],
"main": "es5.js",
"browser": "es5.js",
"module": "src/bowser.js",
"types": "index.d.ts",
"repository": {
"type": "git",
"url": "git+https://github.com/bowser-js/bowser.git"
},
"devDependencies": {
"@babel/cli": "^7.11.6",
"@babel/core": "^7.8.0",
"@babel/polyfill": "^7.8.3",
"@babel/preset-env": "^7.8.2",
"@babel/register": "^7.8.3",
"ava": "^3.0.0",
"babel-eslint": "^10.0.3",
"babel-loader": "^8.0.6",
"babel-plugin-add-module-exports": "^1.0.2",
"babel-plugin-istanbul": "^6.0.0",
"compression-webpack-plugin": "^4.0.0",
"coveralls": "^3.0.6",
"docdash": "^1.1.1",
"eslint": "^6.5.1",
"eslint-config-airbnb-base": "^13.2.0",
"eslint-plugin-ava": "^10.0.0",
"eslint-plugin-import": "^2.18.2",
"gh-pages": "^3.0.0",
"jsdoc": "^3.6.3",
"nyc": "^15.0.0",
"sinon": "^9.0.0",
"testem": "^3.0.0",
"webpack": "^4.41.0",
"webpack-bundle-analyzer": "^3.5.2",
"webpack-cli": "^3.3.9",
"yamljs": "^0.3.0"
},
"ava": {
"require": [
"@babel/register"
]
},
"bugs": {
"url": "https://github.com/bowser-js/bowser/issues"
},
"directories": {
"test": "test"
},
"scripts": {
"build": "webpack --config webpack.config.js",
"generate-and-deploy-docs": "npm run generate-docs && gh-pages --dist docs --dest docs",
"watch": "webpack --watch --config webpack.config.js",
"lint:check": "eslint ./src",
"lint:fix": "eslint --fix ./src",
"testem": "testem",
"test": "nyc --reporter=html --reporter=text ava",
"test:watch": "ava --watch",
"coverage": "nyc report --reporter=text-lcov | coveralls",
"generate-docs": "jsdoc -c jsdoc.json"
},
"license": "MIT",
"version": "2.14.1"
}

93
node_modules/bowser/src/bowser.js generated vendored Normal file
View File

@@ -0,0 +1,93 @@
/*!
* Bowser - a browser detector
* https://github.com/bowser-js/bowser
* MIT License | (c) Dustin Diaz 2012-2015
* MIT License | (c) Denis Demchenko 2015-2019
*/
import Parser from './parser.js';
import {
BROWSER_MAP,
ENGINE_MAP,
OS_MAP,
PLATFORMS_MAP,
} from './constants.js';
/**
* Bowser class.
* Keep it simple as much as it can be.
* It's supposed to work with collections of {@link Parser} instances
* rather then solve one-instance problems.
* All the one-instance stuff is located in Parser class.
*
* @class
* @classdesc Bowser is a static object, that provides an API to the Parsers
* @hideconstructor
*/
class Bowser {
/**
* Creates a {@link Parser} instance
*
* @param {String} UA UserAgent string
* @param {Boolean|Object} [skipParsingOrHints=false] Either a boolean to skip parsing,
* or a ClientHints object (navigator.userAgentData)
* @param {Object} [clientHints] User-Agent Client Hints data (navigator.userAgentData)
* @returns {Parser}
* @throws {Error} when UA is not a String
*
* @example
* const parser = Bowser.getParser(window.navigator.userAgent);
* const result = parser.getResult();
*
* @example
* // With User-Agent Client Hints
* const parser = Bowser.getParser(
* window.navigator.userAgent,
* window.navigator.userAgentData
* );
*/
static getParser(UA, skipParsingOrHints = false, clientHints = null) {
if (typeof UA !== 'string') {
throw new Error('UserAgent should be a string');
}
return new Parser(UA, skipParsingOrHints, clientHints);
}
/**
* Creates a {@link Parser} instance and runs {@link Parser.getResult} immediately
*
* @param {String} UA UserAgent string
* @param {Object} [clientHints] User-Agent Client Hints data (navigator.userAgentData)
* @return {ParsedResult}
*
* @example
* const result = Bowser.parse(window.navigator.userAgent);
*
* @example
* // With User-Agent Client Hints
* const result = Bowser.parse(
* window.navigator.userAgent,
* window.navigator.userAgentData
* );
*/
static parse(UA, clientHints = null) {
return (new Parser(UA, clientHints)).getResult();
}
static get BROWSER_MAP() {
return BROWSER_MAP;
}
static get ENGINE_MAP() {
return ENGINE_MAP;
}
static get OS_MAP() {
return OS_MAP;
}
static get PLATFORMS_MAP() {
return PLATFORMS_MAP;
}
}
export default Bowser;

177
node_modules/bowser/src/constants.js generated vendored Normal file
View File

@@ -0,0 +1,177 @@
// NOTE: this list must be up-to-date with browsers listed in
// test/acceptance/useragentstrings.yml
export const BROWSER_ALIASES_MAP = {
AmazonBot: 'amazonbot',
'Amazon Silk': 'amazon_silk',
'Android Browser': 'android',
BaiduSpider: 'baiduspider',
Bada: 'bada',
BingCrawler: 'bingcrawler',
Brave: 'brave',
BlackBerry: 'blackberry',
'ChatGPT-User': 'chatgpt_user',
Chrome: 'chrome',
ClaudeBot: 'claudebot',
Chromium: 'chromium',
Diffbot: 'diffbot',
DuckDuckBot: 'duckduckbot',
DuckDuckGo: 'duckduckgo',
Electron: 'electron',
Epiphany: 'epiphany',
FacebookExternalHit: 'facebookexternalhit',
Firefox: 'firefox',
Focus: 'focus',
Generic: 'generic',
'Google Search': 'google_search',
Googlebot: 'googlebot',
GPTBot: 'gptbot',
'Internet Explorer': 'ie',
InternetArchiveCrawler: 'internetarchivecrawler',
'K-Meleon': 'k_meleon',
LibreWolf: 'librewolf',
Linespider: 'linespider',
Maxthon: 'maxthon',
'Meta-ExternalAds': 'meta_externalads',
'Meta-ExternalAgent': 'meta_externalagent',
'Meta-ExternalFetcher': 'meta_externalfetcher',
'Meta-WebIndexer': 'meta_webindexer',
'Microsoft Edge': 'edge',
'MZ Browser': 'mz',
'NAVER Whale Browser': 'naver',
'OAI-SearchBot': 'oai_searchbot',
Omgilibot: 'omgilibot',
Opera: 'opera',
'Opera Coast': 'opera_coast',
'Pale Moon': 'pale_moon',
PerplexityBot: 'perplexitybot',
'Perplexity-User': 'perplexity_user',
PhantomJS: 'phantomjs',
PingdomBot: 'pingdombot',
Puffin: 'puffin',
QQ: 'qq',
QQLite: 'qqlite',
QupZilla: 'qupzilla',
Roku: 'roku',
Safari: 'safari',
Sailfish: 'sailfish',
'Samsung Internet for Android': 'samsung_internet',
SlackBot: 'slackbot',
SeaMonkey: 'seamonkey',
Sleipnir: 'sleipnir',
'Sogou Browser': 'sogou',
Swing: 'swing',
Tizen: 'tizen',
'UC Browser': 'uc',
Vivaldi: 'vivaldi',
'WebOS Browser': 'webos',
WeChat: 'wechat',
YahooSlurp: 'yahooslurp',
'Yandex Browser': 'yandex',
YandexBot: 'yandexbot',
YouBot: 'youbot',
};
export const BROWSER_MAP = {
amazonbot: 'AmazonBot',
amazon_silk: 'Amazon Silk',
android: 'Android Browser',
baiduspider: 'BaiduSpider',
bada: 'Bada',
bingcrawler: 'BingCrawler',
blackberry: 'BlackBerry',
brave: 'Brave',
chatgpt_user: 'ChatGPT-User',
chrome: 'Chrome',
claudebot: 'ClaudeBot',
chromium: 'Chromium',
diffbot: 'Diffbot',
duckduckbot: 'DuckDuckBot',
duckduckgo: 'DuckDuckGo',
edge: 'Microsoft Edge',
electron: 'Electron',
epiphany: 'Epiphany',
facebookexternalhit: 'FacebookExternalHit',
firefox: 'Firefox',
focus: 'Focus',
generic: 'Generic',
google_search: 'Google Search',
googlebot: 'Googlebot',
gptbot: 'GPTBot',
ie: 'Internet Explorer',
internetarchivecrawler: 'InternetArchiveCrawler',
k_meleon: 'K-Meleon',
librewolf: 'LibreWolf',
linespider: 'Linespider',
maxthon: 'Maxthon',
meta_externalads: 'Meta-ExternalAds',
meta_externalagent: 'Meta-ExternalAgent',
meta_externalfetcher: 'Meta-ExternalFetcher',
meta_webindexer: 'Meta-WebIndexer',
mz: 'MZ Browser',
naver: 'NAVER Whale Browser',
oai_searchbot: 'OAI-SearchBot',
omgilibot: 'Omgilibot',
opera: 'Opera',
opera_coast: 'Opera Coast',
pale_moon: 'Pale Moon',
perplexitybot: 'PerplexityBot',
perplexity_user: 'Perplexity-User',
phantomjs: 'PhantomJS',
pingdombot: 'PingdomBot',
puffin: 'Puffin',
qq: 'QQ Browser',
qqlite: 'QQ Browser Lite',
qupzilla: 'QupZilla',
roku: 'Roku',
safari: 'Safari',
sailfish: 'Sailfish',
samsung_internet: 'Samsung Internet for Android',
seamonkey: 'SeaMonkey',
slackbot: 'SlackBot',
sleipnir: 'Sleipnir',
sogou: 'Sogou Browser',
swing: 'Swing',
tizen: 'Tizen',
uc: 'UC Browser',
vivaldi: 'Vivaldi',
webos: 'WebOS Browser',
wechat: 'WeChat',
yahooslurp: 'YahooSlurp',
yandex: 'Yandex Browser',
yandexbot: 'YandexBot',
youbot: 'YouBot',
};
export const PLATFORMS_MAP = {
bot: 'bot',
desktop: 'desktop',
mobile: 'mobile',
tablet: 'tablet',
tv: 'tv',
};
export const OS_MAP = {
Android: 'Android',
Bada: 'Bada',
BlackBerry: 'BlackBerry',
ChromeOS: 'Chrome OS',
HarmonyOS: 'HarmonyOS',
iOS: 'iOS',
Linux: 'Linux',
MacOS: 'macOS',
PlayStation4: 'PlayStation 4',
Roku: 'Roku',
Tizen: 'Tizen',
WebOS: 'WebOS',
Windows: 'Windows',
WindowsPhone: 'Windows Phone',
};
export const ENGINE_MAP = {
Blink: 'Blink',
EdgeHTML: 'EdgeHTML',
Gecko: 'Gecko',
Presto: 'Presto',
Trident: 'Trident',
WebKit: 'WebKit',
};

1183
node_modules/bowser/src/parser-browsers.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

120
node_modules/bowser/src/parser-engines.js generated vendored Normal file
View File

@@ -0,0 +1,120 @@
import Utils from './utils.js';
import { ENGINE_MAP } from './constants.js';
/*
* More specific goes first
*/
export default [
/* EdgeHTML */
{
test(parser) {
return parser.getBrowserName(true) === 'microsoft edge';
},
describe(ua) {
const isBlinkBased = /\sedg\//i.test(ua);
// return blink if it's blink-based one
if (isBlinkBased) {
return {
name: ENGINE_MAP.Blink,
};
}
// otherwise match the version and return EdgeHTML
const version = Utils.getFirstMatch(/edge\/(\d+(\.?_?\d+)+)/i, ua);
return {
name: ENGINE_MAP.EdgeHTML,
version,
};
},
},
/* Trident */
{
test: [/trident/i],
describe(ua) {
const engine = {
name: ENGINE_MAP.Trident,
};
const version = Utils.getFirstMatch(/trident\/(\d+(\.?_?\d+)+)/i, ua);
if (version) {
engine.version = version;
}
return engine;
},
},
/* Presto */
{
test(parser) {
return parser.test(/presto/i);
},
describe(ua) {
const engine = {
name: ENGINE_MAP.Presto,
};
const version = Utils.getFirstMatch(/presto\/(\d+(\.?_?\d+)+)/i, ua);
if (version) {
engine.version = version;
}
return engine;
},
},
/* Gecko */
{
test(parser) {
const isGecko = parser.test(/gecko/i);
const likeGecko = parser.test(/like gecko/i);
return isGecko && !likeGecko;
},
describe(ua) {
const engine = {
name: ENGINE_MAP.Gecko,
};
const version = Utils.getFirstMatch(/gecko\/(\d+(\.?_?\d+)+)/i, ua);
if (version) {
engine.version = version;
}
return engine;
},
},
/* Blink */
{
test: [/(apple)?webkit\/537\.36/i],
describe() {
return {
name: ENGINE_MAP.Blink,
};
},
},
/* WebKit */
{
test: [/(apple)?webkit/i],
describe(ua) {
const engine = {
name: ENGINE_MAP.WebKit,
};
const version = Utils.getFirstMatch(/webkit\/(\d+(\.?_?\d+)+)/i, ua);
if (version) {
engine.version = version;
}
return engine;
},
},
];

211
node_modules/bowser/src/parser-os.js generated vendored Normal file
View File

@@ -0,0 +1,211 @@
import Utils from './utils.js';
import { OS_MAP } from './constants.js';
export default [
/* Roku */
{
test: [/Roku\/DVP/],
describe(ua) {
const version = Utils.getFirstMatch(/Roku\/DVP-(\d+\.\d+)/i, ua);
return {
name: OS_MAP.Roku,
version,
};
},
},
/* Windows Phone */
{
test: [/windows phone/i],
describe(ua) {
const version = Utils.getFirstMatch(/windows phone (?:os)?\s?(\d+(\.\d+)*)/i, ua);
return {
name: OS_MAP.WindowsPhone,
version,
};
},
},
/* Windows */
{
test: [/windows /i],
describe(ua) {
const version = Utils.getFirstMatch(/Windows ((NT|XP)( \d\d?.\d)?)/i, ua);
const versionName = Utils.getWindowsVersionName(version);
return {
name: OS_MAP.Windows,
version,
versionName,
};
},
},
/* Firefox on iPad */
{
test: [/Macintosh(.*?) FxiOS(.*?)\//],
describe(ua) {
const result = {
name: OS_MAP.iOS,
};
const version = Utils.getSecondMatch(/(Version\/)(\d[\d.]+)/, ua);
if (version) {
result.version = version;
}
return result;
},
},
/* macOS */
{
test: [/macintosh/i],
describe(ua) {
const version = Utils.getFirstMatch(/mac os x (\d+(\.?_?\d+)+)/i, ua).replace(/[_\s]/g, '.');
const versionName = Utils.getMacOSVersionName(version);
const os = {
name: OS_MAP.MacOS,
version,
};
if (versionName) {
os.versionName = versionName;
}
return os;
},
},
/* iOS */
{
test: [/(ipod|iphone|ipad)/i],
describe(ua) {
const version = Utils.getFirstMatch(/os (\d+([_\s]\d+)*) like mac os x/i, ua).replace(/[_\s]/g, '.');
return {
name: OS_MAP.iOS,
version,
};
},
},
/* HarmonyOS */
{
test: [/OpenHarmony/i],
describe(ua) {
const version = Utils.getFirstMatch(/OpenHarmony\s+(\d+(\.\d+)*)/i, ua);
return {
name: OS_MAP.HarmonyOS,
version,
};
},
},
/* Android */
{
test(parser) {
const notLikeAndroid = !parser.test(/like android/i);
const butAndroid = parser.test(/android/i);
return notLikeAndroid && butAndroid;
},
describe(ua) {
const version = Utils.getFirstMatch(/android[\s/-](\d+(\.\d+)*)/i, ua);
const versionName = Utils.getAndroidVersionName(version);
const os = {
name: OS_MAP.Android,
version,
};
if (versionName) {
os.versionName = versionName;
}
return os;
},
},
/* WebOS */
{
test: [/(web|hpw)[o0]s/i],
describe(ua) {
const version = Utils.getFirstMatch(/(?:web|hpw)[o0]s\/(\d+(\.\d+)*)/i, ua);
const os = {
name: OS_MAP.WebOS,
};
if (version && version.length) {
os.version = version;
}
return os;
},
},
/* BlackBerry */
{
test: [/blackberry|\bbb\d+/i, /rim\stablet/i],
describe(ua) {
const version = Utils.getFirstMatch(/rim\stablet\sos\s(\d+(\.\d+)*)/i, ua)
|| Utils.getFirstMatch(/blackberry\d+\/(\d+([_\s]\d+)*)/i, ua)
|| Utils.getFirstMatch(/\bbb(\d+)/i, ua);
return {
name: OS_MAP.BlackBerry,
version,
};
},
},
/* Bada */
{
test: [/bada/i],
describe(ua) {
const version = Utils.getFirstMatch(/bada\/(\d+(\.\d+)*)/i, ua);
return {
name: OS_MAP.Bada,
version,
};
},
},
/* Tizen */
{
test: [/tizen/i],
describe(ua) {
const version = Utils.getFirstMatch(/tizen[/\s](\d+(\.\d+)*)/i, ua);
return {
name: OS_MAP.Tizen,
version,
};
},
},
/* Linux */
{
test: [/linux/i],
describe() {
return {
name: OS_MAP.Linux,
};
},
},
/* Chrome OS */
{
test: [/CrOS/],
describe() {
return {
name: OS_MAP.ChromeOS,
};
},
},
/* Playstation 4 */
{
test: [/PlayStation 4/],
describe(ua) {
const version = Utils.getFirstMatch(/PlayStation 4[/\s](\d+(\.\d+)*)/i, ua);
return {
name: OS_MAP.PlayStation4,
version,
};
},
},
];

566
node_modules/bowser/src/parser-platforms.js generated vendored Normal file
View File

@@ -0,0 +1,566 @@
import Utils from './utils.js';
import { PLATFORMS_MAP } from './constants.js';
/*
* Tablets go first since usually they have more specific
* signs to detect.
*/
export default [
/* Googlebot */
{
test: [/googlebot/i],
describe() {
return {
type: PLATFORMS_MAP.bot,
vendor: 'Google',
};
},
},
/* LineSpider */
{
test: [/linespider/i],
describe() {
return {
type: PLATFORMS_MAP.bot,
vendor: 'Line',
};
},
},
/* AmazonBot */
{
test: [/amazonbot/i],
describe() {
return {
type: PLATFORMS_MAP.bot,
vendor: 'Amazon',
};
},
},
/* GPTBot */
{
test: [/gptbot/i],
describe() {
return {
type: PLATFORMS_MAP.bot,
vendor: 'OpenAI',
};
},
},
/* ChatGPT-User */
{
test: [/chatgpt-user/i],
describe() {
return {
type: PLATFORMS_MAP.bot,
vendor: 'OpenAI',
};
},
},
/* OAI-SearchBot */
{
test: [/oai-searchbot/i],
describe() {
return {
type: PLATFORMS_MAP.bot,
vendor: 'OpenAI',
};
},
},
/* Baidu */
{
test: [/baiduspider/i],
describe() {
return {
type: PLATFORMS_MAP.bot,
vendor: 'Baidu',
};
},
},
/* Bingbot */
{
test: [/bingbot/i],
describe() {
return {
type: PLATFORMS_MAP.bot,
vendor: 'Bing',
};
},
},
/* DuckDuckBot */
{
test: [/duckduckbot/i],
describe() {
return {
type: PLATFORMS_MAP.bot,
vendor: 'DuckDuckGo',
};
},
},
/* ClaudeBot */
{
test: [/claudebot/i, /claude-web/i, /claude-user/i, /claude-searchbot/i],
describe() {
return {
type: PLATFORMS_MAP.bot,
vendor: 'Anthropic',
};
},
},
/* Omgilibot */
{
test: [/omgilibot/i, /webzio-extended/i],
describe() {
return {
type: PLATFORMS_MAP.bot,
vendor: 'Webz.io',
};
},
},
/* Diffbot */
{
test: [/diffbot/i],
describe() {
return {
type: PLATFORMS_MAP.bot,
vendor: 'Diffbot',
};
},
},
/* PerplexityBot */
{
test: [/perplexitybot/i],
describe() {
return {
type: PLATFORMS_MAP.bot,
vendor: 'Perplexity AI',
};
},
},
/* Perplexity-User */
{
test: [/perplexity-user/i],
describe() {
return {
type: PLATFORMS_MAP.bot,
vendor: 'Perplexity AI',
};
},
},
/* YouBot */
{
test: [/youbot/i],
describe() {
return {
type: PLATFORMS_MAP.bot,
vendor: 'You.com',
};
},
},
/* Internet Archive Crawler */
{
test: [/ia_archiver/i],
describe() {
return {
type: PLATFORMS_MAP.bot,
vendor: 'Internet Archive',
};
},
},
/* Meta-WebIndexer */
{
test: [/meta-webindexer/i],
describe() {
return {
type: PLATFORMS_MAP.bot,
vendor: 'Meta',
};
},
},
/* Meta-ExternalAds */
{
test: [/meta-externalads/i],
describe() {
return {
type: PLATFORMS_MAP.bot,
vendor: 'Meta',
};
},
},
/* Meta-ExternalAgent */
{
test: [/meta-externalagent/i],
describe() {
return {
type: PLATFORMS_MAP.bot,
vendor: 'Meta',
};
},
},
/* Meta-ExternalFetcher */
{
test: [/meta-externalfetcher/i],
describe() {
return {
type: PLATFORMS_MAP.bot,
vendor: 'Meta',
};
},
},
/* Meta Web Crawler */
{
test: [/facebookexternalhit/i, /facebookcatalog/i],
describe() {
return {
type: PLATFORMS_MAP.bot,
vendor: 'Meta',
};
},
},
/* SlackBot */
{
test: [/slackbot/i, /slack-imgProxy/i],
describe() {
return {
type: PLATFORMS_MAP.bot,
vendor: 'Slack',
};
},
},
/* Yahoo! Slurp */
{
test: [/yahoo/i],
describe() {
return {
type: PLATFORMS_MAP.bot,
vendor: 'Yahoo',
};
},
},
/* Yandex */
{
test: [/yandexbot/i, /yandexmobilebot/i],
describe() {
return {
type: PLATFORMS_MAP.bot,
vendor: 'Yandex',
};
},
},
/* Pingdom */
{
test: [/pingdom/i],
describe() {
return {
type: PLATFORMS_MAP.bot,
vendor: 'Pingdom',
};
},
},
/* Huawei */
{
test: [/huawei/i],
describe(ua) {
const model = Utils.getFirstMatch(/(can-l01)/i, ua) && 'Nova';
const platform = {
type: PLATFORMS_MAP.mobile,
vendor: 'Huawei',
};
if (model) {
platform.model = model;
}
return platform;
},
},
/* Nexus Tablet */
{
test: [/nexus\s*(?:7|8|9|10).*/i],
describe() {
return {
type: PLATFORMS_MAP.tablet,
vendor: 'Nexus',
};
},
},
/* iPad */
{
test: [/ipad/i],
describe() {
return {
type: PLATFORMS_MAP.tablet,
vendor: 'Apple',
model: 'iPad',
};
},
},
/* Firefox on iPad */
{
test: [/Macintosh(.*?) FxiOS(.*?)\//],
describe() {
return {
type: PLATFORMS_MAP.tablet,
vendor: 'Apple',
model: 'iPad',
};
},
},
/* Amazon Kindle Fire */
{
test: [/kftt build/i],
describe() {
return {
type: PLATFORMS_MAP.tablet,
vendor: 'Amazon',
model: 'Kindle Fire HD 7',
};
},
},
/* Another Amazon Tablet with Silk */
{
test: [/silk/i],
describe() {
return {
type: PLATFORMS_MAP.tablet,
vendor: 'Amazon',
};
},
},
/* Tablet */
{
test: [/tablet(?! pc)/i],
describe() {
return {
type: PLATFORMS_MAP.tablet,
};
},
},
/* iPod/iPhone */
{
test(parser) {
const iDevice = parser.test(/ipod|iphone/i);
const likeIDevice = parser.test(/like (ipod|iphone)/i);
return iDevice && !likeIDevice;
},
describe(ua) {
const model = Utils.getFirstMatch(/(ipod|iphone)/i, ua);
return {
type: PLATFORMS_MAP.mobile,
vendor: 'Apple',
model,
};
},
},
/* Nexus Mobile */
{
test: [/nexus\s*[0-6].*/i, /galaxy nexus/i],
describe() {
return {
type: PLATFORMS_MAP.mobile,
vendor: 'Nexus',
};
},
},
/* Nokia */
{
test: [/Nokia/i],
describe(ua) {
const model = Utils.getFirstMatch(/Nokia\s+([0-9]+(\.[0-9]+)?)/i, ua);
const platform = {
type: PLATFORMS_MAP.mobile,
vendor: 'Nokia',
};
if (model) {
platform.model = model;
}
return platform;
},
},
/* Mobile */
{
test: [/[^-]mobi/i],
describe() {
return {
type: PLATFORMS_MAP.mobile,
};
},
},
/* BlackBerry */
{
test(parser) {
return parser.getBrowserName(true) === 'blackberry';
},
describe() {
return {
type: PLATFORMS_MAP.mobile,
vendor: 'BlackBerry',
};
},
},
/* Bada */
{
test(parser) {
return parser.getBrowserName(true) === 'bada';
},
describe() {
return {
type: PLATFORMS_MAP.mobile,
};
},
},
/* Windows Phone */
{
test(parser) {
return parser.getBrowserName() === 'windows phone';
},
describe() {
return {
type: PLATFORMS_MAP.mobile,
vendor: 'Microsoft',
};
},
},
/* Android Tablet */
{
test(parser) {
const osMajorVersion = Number(String(parser.getOSVersion()).split('.')[0]);
return parser.getOSName(true) === 'android' && (osMajorVersion >= 3);
},
describe() {
return {
type: PLATFORMS_MAP.tablet,
};
},
},
/* Android Mobile */
{
test(parser) {
return parser.getOSName(true) === 'android';
},
describe() {
return {
type: PLATFORMS_MAP.mobile,
};
},
},
/* Smart TV */
{
test: [/smart-?tv|smarttv/i],
describe() {
return {
type: PLATFORMS_MAP.tv,
};
},
},
/* NetCast (LG Smart TV) */
{
test: [/netcast/i],
describe() {
return {
type: PLATFORMS_MAP.tv,
};
},
},
/* desktop */
{
test(parser) {
return parser.getOSName(true) === 'macos';
},
describe() {
return {
type: PLATFORMS_MAP.desktop,
vendor: 'Apple',
};
},
},
/* Windows */
{
test(parser) {
return parser.getOSName(true) === 'windows';
},
describe() {
return {
type: PLATFORMS_MAP.desktop,
};
},
},
/* Linux */
{
test(parser) {
return parser.getOSName(true) === 'linux';
},
describe() {
return {
type: PLATFORMS_MAP.desktop,
};
},
},
/* PlayStation 4 */
{
test(parser) {
return parser.getOSName(true) === 'playstation 4';
},
describe() {
return {
type: PLATFORMS_MAP.tv,
};
},
},
/* Roku */
{
test(parser) {
return parser.getOSName(true) === 'roku';
},
describe() {
return {
type: PLATFORMS_MAP.tv,
};
},
},
];

592
node_modules/bowser/src/parser.js generated vendored Normal file
View File

@@ -0,0 +1,592 @@
import browserParsersList from './parser-browsers.js';
import osParsersList from './parser-os.js';
import platformParsersList from './parser-platforms.js';
import enginesParsersList from './parser-engines.js';
import Utils from './utils.js';
/**
* @typedef {Object} ClientHints
* @property {Array<{brand: string, version: string}>} [brands] Array of brand objects
* @property {boolean} [mobile] Whether the device is mobile
* @property {string} [platform] Platform name (e.g., "Windows", "macOS")
* @property {string} [platformVersion] Platform version
* @property {string} [architecture] CPU architecture
* @property {string} [model] Device model
* @property {boolean} [wow64] Whether running under WoW64
*/
/**
* The main class that arranges the whole parsing process.
*/
class Parser {
/**
* Create instance of Parser
*
* @param {String} UA User-Agent string
* @param {Boolean|ClientHints} [skipParsingOrHints=false] Either a boolean to skip parsing,
* or a ClientHints object containing User-Agent Client Hints data
* @param {ClientHints} [clientHints] User-Agent Client Hints data (navigator.userAgentData)
*
* @throw {Error} in case of empty UA String
*
* @constructor
*/
constructor(UA, skipParsingOrHints = false, clientHints = null) {
if (UA === void (0) || UA === null || UA === '') {
throw new Error("UserAgent parameter can't be empty");
}
this._ua = UA;
// Handle overloaded constructor: (UA, clientHints) or (UA, skipParsing, clientHints)
let skipParsing = false;
if (typeof skipParsingOrHints === 'boolean') {
skipParsing = skipParsingOrHints;
this._hints = clientHints;
} else if (skipParsingOrHints != null && typeof skipParsingOrHints === 'object') {
this._hints = skipParsingOrHints;
} else {
this._hints = null;
}
/**
* @typedef ParsedResult
* @property {Object} browser
* @property {String|undefined} [browser.name]
* Browser name, like `"Chrome"` or `"Internet Explorer"`
* @property {String|undefined} [browser.version] Browser version as a String `"12.01.45334.10"`
* @property {Object} os
* @property {String|undefined} [os.name] OS name, like `"Windows"` or `"macOS"`
* @property {String|undefined} [os.version] OS version, like `"NT 5.1"` or `"10.11.1"`
* @property {String|undefined} [os.versionName] OS name, like `"XP"` or `"High Sierra"`
* @property {Object} platform
* @property {String|undefined} [platform.type]
* platform type, can be either `"desktop"`, `"tablet"` or `"mobile"`
* @property {String|undefined} [platform.vendor] Vendor of the device,
* like `"Apple"` or `"Samsung"`
* @property {String|undefined} [platform.model] Device model,
* like `"iPhone"` or `"Kindle Fire HD 7"`
* @property {Object} engine
* @property {String|undefined} [engine.name]
* Can be any of this: `WebKit`, `Blink`, `Gecko`, `Trident`, `Presto`, `EdgeHTML`
* @property {String|undefined} [engine.version] String version of the engine
*/
this.parsedResult = {};
if (skipParsing !== true) {
this.parse();
}
}
/**
* Get Client Hints data
* @return {ClientHints|null}
*
* @public
* @example
* const parser = Bowser.getParser(UA, clientHints);
* const hints = parser.getHints();
* console.log(hints.platform); // 'Windows'
* console.log(hints.mobile); // false
*/
getHints() {
return this._hints;
}
/**
* Check if a brand exists in Client Hints brands array
* @param {string} brandName The brand name to check for
* @return {boolean}
*
* @public
* @example
* const parser = Bowser.getParser(UA, clientHints);
* if (parser.hasBrand('Google Chrome')) {
* console.log('Chrome detected!');
* }
*/
hasBrand(brandName) {
if (!this._hints || !Array.isArray(this._hints.brands)) {
return false;
}
const brandLower = brandName.toLowerCase();
return this._hints.brands.some(
b => b.brand && b.brand.toLowerCase() === brandLower,
);
}
/**
* Get brand version from Client Hints
* @param {string} brandName The brand name to get version for
* @return {string|undefined}
*
* @public
* @example
* const parser = Bowser.getParser(UA, clientHints);
* const version = parser.getBrandVersion('Google Chrome');
* console.log(version); // '131'
*/
getBrandVersion(brandName) {
if (!this._hints || !Array.isArray(this._hints.brands)) {
return undefined;
}
const brandLower = brandName.toLowerCase();
const brand = this._hints.brands.find(
b => b.brand && b.brand.toLowerCase() === brandLower,
);
return brand ? brand.version : undefined;
}
/**
* Get UserAgent string of current Parser instance
* @return {String} User-Agent String of the current <Parser> object
*
* @public
*/
getUA() {
return this._ua;
}
/**
* Test a UA string for a regexp
* @param {RegExp} regex
* @return {Boolean}
*/
test(regex) {
return regex.test(this._ua);
}
/**
* Get parsed browser object
* @return {Object}
*/
parseBrowser() {
this.parsedResult.browser = {};
const browserDescriptor = Utils.find(browserParsersList, (_browser) => {
if (typeof _browser.test === 'function') {
return _browser.test(this);
}
if (Array.isArray(_browser.test)) {
return _browser.test.some(condition => this.test(condition));
}
throw new Error("Browser's test function is not valid");
});
if (browserDescriptor) {
this.parsedResult.browser = browserDescriptor.describe(this.getUA(), this);
}
return this.parsedResult.browser;
}
/**
* Get parsed browser object
* @return {Object}
*
* @public
*/
getBrowser() {
if (this.parsedResult.browser) {
return this.parsedResult.browser;
}
return this.parseBrowser();
}
/**
* Get browser's name
* @return {String} Browser's name or an empty string
*
* @public
*/
getBrowserName(toLowerCase) {
if (toLowerCase) {
return String(this.getBrowser().name).toLowerCase() || '';
}
return this.getBrowser().name || '';
}
/**
* Get browser's version
* @return {String} version of browser
*
* @public
*/
getBrowserVersion() {
return this.getBrowser().version;
}
/**
* Get OS
* @return {Object}
*
* @example
* this.getOS();
* {
* name: 'macOS',
* version: '10.11.12'
* }
*/
getOS() {
if (this.parsedResult.os) {
return this.parsedResult.os;
}
return this.parseOS();
}
/**
* Parse OS and save it to this.parsedResult.os
* @return {*|{}}
*/
parseOS() {
this.parsedResult.os = {};
const os = Utils.find(osParsersList, (_os) => {
if (typeof _os.test === 'function') {
return _os.test(this);
}
if (Array.isArray(_os.test)) {
return _os.test.some(condition => this.test(condition));
}
throw new Error("Browser's test function is not valid");
});
if (os) {
this.parsedResult.os = os.describe(this.getUA());
}
return this.parsedResult.os;
}
/**
* Get OS name
* @param {Boolean} [toLowerCase] return lower-cased value
* @return {String} name of the OS — macOS, Windows, Linux, etc.
*/
getOSName(toLowerCase) {
const { name } = this.getOS();
if (toLowerCase) {
return String(name).toLowerCase() || '';
}
return name || '';
}
/**
* Get OS version
* @return {String} full version with dots ('10.11.12', '5.6', etc)
*/
getOSVersion() {
return this.getOS().version;
}
/**
* Get parsed platform
* @return {{}}
*/
getPlatform() {
if (this.parsedResult.platform) {
return this.parsedResult.platform;
}
return this.parsePlatform();
}
/**
* Get platform name
* @param {Boolean} [toLowerCase=false]
* @return {*}
*/
getPlatformType(toLowerCase = false) {
const { type } = this.getPlatform();
if (toLowerCase) {
return String(type).toLowerCase() || '';
}
return type || '';
}
/**
* Get parsed platform
* @return {{}}
*/
parsePlatform() {
this.parsedResult.platform = {};
const platform = Utils.find(platformParsersList, (_platform) => {
if (typeof _platform.test === 'function') {
return _platform.test(this);
}
if (Array.isArray(_platform.test)) {
return _platform.test.some(condition => this.test(condition));
}
throw new Error("Browser's test function is not valid");
});
if (platform) {
this.parsedResult.platform = platform.describe(this.getUA());
}
return this.parsedResult.platform;
}
/**
* Get parsed engine
* @return {{}}
*/
getEngine() {
if (this.parsedResult.engine) {
return this.parsedResult.engine;
}
return this.parseEngine();
}
/**
* Get engines's name
* @return {String} Engines's name or an empty string
*
* @public
*/
getEngineName(toLowerCase) {
if (toLowerCase) {
return String(this.getEngine().name).toLowerCase() || '';
}
return this.getEngine().name || '';
}
/**
* Get parsed platform
* @return {{}}
*/
parseEngine() {
this.parsedResult.engine = {};
const engine = Utils.find(enginesParsersList, (_engine) => {
if (typeof _engine.test === 'function') {
return _engine.test(this);
}
if (Array.isArray(_engine.test)) {
return _engine.test.some(condition => this.test(condition));
}
throw new Error("Browser's test function is not valid");
});
if (engine) {
this.parsedResult.engine = engine.describe(this.getUA());
}
return this.parsedResult.engine;
}
/**
* Parse full information about the browser
* @returns {Parser}
*/
parse() {
this.parseBrowser();
this.parseOS();
this.parsePlatform();
this.parseEngine();
return this;
}
/**
* Get parsed result
* @return {ParsedResult}
*/
getResult() {
return Utils.assign({}, this.parsedResult);
}
/**
* Check if parsed browser matches certain conditions
*
* @param {Object} checkTree It's one or two layered object,
* which can include a platform or an OS on the first layer
* and should have browsers specs on the bottom-laying layer
*
* @returns {Boolean|undefined} Whether the browser satisfies the set conditions or not.
* Returns `undefined` when the browser is no described in the checkTree object.
*
* @example
* const browser = Bowser.getParser(window.navigator.userAgent);
* if (browser.satisfies({chrome: '>118.01.1322' }))
* // or with os
* if (browser.satisfies({windows: { chrome: '>118.01.1322' } }))
* // or with platforms
* if (browser.satisfies({desktop: { chrome: '>118.01.1322' } }))
*/
satisfies(checkTree) {
const platformsAndOSes = {};
let platformsAndOSCounter = 0;
const browsers = {};
let browsersCounter = 0;
const allDefinitions = Object.keys(checkTree);
allDefinitions.forEach((key) => {
const currentDefinition = checkTree[key];
if (typeof currentDefinition === 'string') {
browsers[key] = currentDefinition;
browsersCounter += 1;
} else if (typeof currentDefinition === 'object') {
platformsAndOSes[key] = currentDefinition;
platformsAndOSCounter += 1;
}
});
if (platformsAndOSCounter > 0) {
const platformsAndOSNames = Object.keys(platformsAndOSes);
const OSMatchingDefinition = Utils.find(platformsAndOSNames, name => (this.isOS(name)));
if (OSMatchingDefinition) {
const osResult = this.satisfies(platformsAndOSes[OSMatchingDefinition]);
if (osResult !== void 0) {
return osResult;
}
}
const platformMatchingDefinition = Utils.find(
platformsAndOSNames,
name => (this.isPlatform(name)),
);
if (platformMatchingDefinition) {
const platformResult = this.satisfies(platformsAndOSes[platformMatchingDefinition]);
if (platformResult !== void 0) {
return platformResult;
}
}
}
if (browsersCounter > 0) {
const browserNames = Object.keys(browsers);
const matchingDefinition = Utils.find(browserNames, name => (this.isBrowser(name, true)));
if (matchingDefinition !== void 0) {
return this.compareVersion(browsers[matchingDefinition]);
}
}
return undefined;
}
/**
* Check if the browser name equals the passed string
* @param {string} browserName The string to compare with the browser name
* @param [includingAlias=false] The flag showing whether alias will be included into comparison
* @returns {boolean}
*/
isBrowser(browserName, includingAlias = false) {
const defaultBrowserName = this.getBrowserName().toLowerCase();
let browserNameLower = browserName.toLowerCase();
const alias = Utils.getBrowserTypeByAlias(browserNameLower);
if (includingAlias && alias) {
browserNameLower = alias.toLowerCase();
}
return browserNameLower === defaultBrowserName;
}
compareVersion(version) {
let expectedResults = [0];
let comparableVersion = version;
let isLoose = false;
const currentBrowserVersion = this.getBrowserVersion();
if (typeof currentBrowserVersion !== 'string') {
return void 0;
}
if (version[0] === '>' || version[0] === '<') {
comparableVersion = version.substr(1);
if (version[1] === '=') {
isLoose = true;
comparableVersion = version.substr(2);
} else {
expectedResults = [];
}
if (version[0] === '>') {
expectedResults.push(1);
} else {
expectedResults.push(-1);
}
} else if (version[0] === '=') {
comparableVersion = version.substr(1);
} else if (version[0] === '~') {
isLoose = true;
comparableVersion = version.substr(1);
}
return expectedResults.indexOf(
Utils.compareVersions(currentBrowserVersion, comparableVersion, isLoose),
) > -1;
}
/**
* Check if the OS name equals the passed string
* @param {string} osName The string to compare with the OS name
* @returns {boolean}
*/
isOS(osName) {
return this.getOSName(true) === String(osName).toLowerCase();
}
/**
* Check if the platform type equals the passed string
* @param {string} platformType The string to compare with the platform type
* @returns {boolean}
*/
isPlatform(platformType) {
return this.getPlatformType(true) === String(platformType).toLowerCase();
}
/**
* Check if the engine name equals the passed string
* @param {string} engineName The string to compare with the engine name
* @returns {boolean}
*/
isEngine(engineName) {
return this.getEngineName(true) === String(engineName).toLowerCase();
}
/**
* Is anything? Check if the browser is called "anything",
* the OS called "anything" or the platform called "anything"
* @param {String} anything
* @param [includingAlias=false] The flag showing whether alias will be included into comparison
* @returns {Boolean}
*/
is(anything, includingAlias = false) {
return this.isBrowser(anything, includingAlias) || this.isOS(anything)
|| this.isPlatform(anything);
}
/**
* Check if any of the given values satisfies this.is(anything)
* @param {String[]} anythings
* @returns {Boolean}
*/
some(anythings = []) {
return anythings.some(anything => this.is(anything));
}
}
export default Parser;

327
node_modules/bowser/src/utils.js generated vendored Normal file
View File

@@ -0,0 +1,327 @@
import { BROWSER_MAP, BROWSER_ALIASES_MAP } from './constants.js';
export default class Utils {
/**
* Get first matched item for a string
* @param {RegExp} regexp
* @param {String} ua
* @return {Array|{index: number, input: string}|*|boolean|string}
*/
static getFirstMatch(regexp, ua) {
const match = ua.match(regexp);
return (match && match.length > 0 && match[1]) || '';
}
/**
* Get second matched item for a string
* @param regexp
* @param {String} ua
* @return {Array|{index: number, input: string}|*|boolean|string}
*/
static getSecondMatch(regexp, ua) {
const match = ua.match(regexp);
return (match && match.length > 1 && match[2]) || '';
}
/**
* Match a regexp and return a constant or undefined
* @param {RegExp} regexp
* @param {String} ua
* @param {*} _const Any const that will be returned if regexp matches the string
* @return {*}
*/
static matchAndReturnConst(regexp, ua, _const) {
if (regexp.test(ua)) {
return _const;
}
return void (0);
}
static getWindowsVersionName(version) {
switch (version) {
case 'NT': return 'NT';
case 'XP': return 'XP';
case 'NT 5.0': return '2000';
case 'NT 5.1': return 'XP';
case 'NT 5.2': return '2003';
case 'NT 6.0': return 'Vista';
case 'NT 6.1': return '7';
case 'NT 6.2': return '8';
case 'NT 6.3': return '8.1';
case 'NT 10.0': return '10';
default: return undefined;
}
}
/**
* Get macOS version name
* 10.5 - Leopard
* 10.6 - Snow Leopard
* 10.7 - Lion
* 10.8 - Mountain Lion
* 10.9 - Mavericks
* 10.10 - Yosemite
* 10.11 - El Capitan
* 10.12 - Sierra
* 10.13 - High Sierra
* 10.14 - Mojave
* 10.15 - Catalina
* 11 - Big Sur
* 12 - Monterey
* 13 - Ventura
* 14 - Sonoma
* 15 - Sequoia
*
* @example
* getMacOSVersionName("10.14") // 'Mojave'
*
* @param {string} version
* @return {string} versionName
*/
static getMacOSVersionName(version) {
const v = version.split('.').splice(0, 2).map(s => parseInt(s, 10) || 0);
v.push(0);
const major = v[0];
const minor = v[1];
if (major === 10) {
switch (minor) {
case 5: return 'Leopard';
case 6: return 'Snow Leopard';
case 7: return 'Lion';
case 8: return 'Mountain Lion';
case 9: return 'Mavericks';
case 10: return 'Yosemite';
case 11: return 'El Capitan';
case 12: return 'Sierra';
case 13: return 'High Sierra';
case 14: return 'Mojave';
case 15: return 'Catalina';
default: return undefined;
}
}
switch (major) {
case 11: return 'Big Sur';
case 12: return 'Monterey';
case 13: return 'Ventura';
case 14: return 'Sonoma';
case 15: return 'Sequoia';
default: return undefined;
}
}
/**
* Get Android version name
* 1.5 - Cupcake
* 1.6 - Donut
* 2.0 - Eclair
* 2.1 - Eclair
* 2.2 - Froyo
* 2.x - Gingerbread
* 3.x - Honeycomb
* 4.0 - Ice Cream Sandwich
* 4.1 - Jelly Bean
* 4.4 - KitKat
* 5.x - Lollipop
* 6.x - Marshmallow
* 7.x - Nougat
* 8.x - Oreo
* 9.x - Pie
*
* @example
* getAndroidVersionName("7.0") // 'Nougat'
*
* @param {string} version
* @return {string} versionName
*/
static getAndroidVersionName(version) {
const v = version.split('.').splice(0, 2).map(s => parseInt(s, 10) || 0);
v.push(0);
if (v[0] === 1 && v[1] < 5) return undefined;
if (v[0] === 1 && v[1] < 6) return 'Cupcake';
if (v[0] === 1 && v[1] >= 6) return 'Donut';
if (v[0] === 2 && v[1] < 2) return 'Eclair';
if (v[0] === 2 && v[1] === 2) return 'Froyo';
if (v[0] === 2 && v[1] > 2) return 'Gingerbread';
if (v[0] === 3) return 'Honeycomb';
if (v[0] === 4 && v[1] < 1) return 'Ice Cream Sandwich';
if (v[0] === 4 && v[1] < 4) return 'Jelly Bean';
if (v[0] === 4 && v[1] >= 4) return 'KitKat';
if (v[0] === 5) return 'Lollipop';
if (v[0] === 6) return 'Marshmallow';
if (v[0] === 7) return 'Nougat';
if (v[0] === 8) return 'Oreo';
if (v[0] === 9) return 'Pie';
return undefined;
}
/**
* Get version precisions count
*
* @example
* getVersionPrecision("1.10.3") // 3
*
* @param {string} version
* @return {number}
*/
static getVersionPrecision(version) {
return version.split('.').length;
}
/**
* Calculate browser version weight
*
* @example
* compareVersions('1.10.2.1', '1.8.2.1.90') // 1
* compareVersions('1.010.2.1', '1.09.2.1.90'); // 1
* compareVersions('1.10.2.1', '1.10.2.1'); // 0
* compareVersions('1.10.2.1', '1.0800.2'); // -1
* compareVersions('1.10.2.1', '1.10', true); // 0
*
* @param {String} versionA versions versions to compare
* @param {String} versionB versions versions to compare
* @param {boolean} [isLoose] enable loose comparison
* @return {Number} comparison result: -1 when versionA is lower,
* 1 when versionA is bigger, 0 when both equal
*/
/* eslint consistent-return: 1 */
static compareVersions(versionA, versionB, isLoose = false) {
// 1) get common precision for both versions, for example for "10.0" and "9" it should be 2
const versionAPrecision = Utils.getVersionPrecision(versionA);
const versionBPrecision = Utils.getVersionPrecision(versionB);
let precision = Math.max(versionAPrecision, versionBPrecision);
let lastPrecision = 0;
const chunks = Utils.map([versionA, versionB], (version) => {
const delta = precision - Utils.getVersionPrecision(version);
// 2) "9" -> "9.0" (for precision = 2)
const _version = version + new Array(delta + 1).join('.0');
// 3) "9.0" -> ["000000000"", "000000009"]
return Utils.map(_version.split('.'), chunk => new Array(20 - chunk.length).join('0') + chunk).reverse();
});
// adjust precision for loose comparison
if (isLoose) {
lastPrecision = precision - Math.min(versionAPrecision, versionBPrecision);
}
// iterate in reverse order by reversed chunks array
precision -= 1;
while (precision >= lastPrecision) {
// 4) compare: "000000009" > "000000010" = false (but "9" > "10" = true)
if (chunks[0][precision] > chunks[1][precision]) {
return 1;
}
if (chunks[0][precision] === chunks[1][precision]) {
if (precision === lastPrecision) {
// all version chunks are same
return 0;
}
precision -= 1;
} else if (chunks[0][precision] < chunks[1][precision]) {
return -1;
}
}
return undefined;
}
/**
* Array::map polyfill
*
* @param {Array} arr
* @param {Function} iterator
* @return {Array}
*/
static map(arr, iterator) {
const result = [];
let i;
if (Array.prototype.map) {
return Array.prototype.map.call(arr, iterator);
}
for (i = 0; i < arr.length; i += 1) {
result.push(iterator(arr[i]));
}
return result;
}
/**
* Array::find polyfill
*
* @param {Array} arr
* @param {Function} predicate
* @return {Array}
*/
static find(arr, predicate) {
let i;
let l;
if (Array.prototype.find) {
return Array.prototype.find.call(arr, predicate);
}
for (i = 0, l = arr.length; i < l; i += 1) {
const value = arr[i];
if (predicate(value, i)) {
return value;
}
}
return undefined;
}
/**
* Object::assign polyfill
*
* @param {Object} obj
* @param {Object} ...objs
* @return {Object}
*/
static assign(obj, ...assigners) {
const result = obj;
let i;
let l;
if (Object.assign) {
return Object.assign(obj, ...assigners);
}
for (i = 0, l = assigners.length; i < l; i += 1) {
const assigner = assigners[i];
if (typeof assigner === 'object' && assigner !== null) {
const keys = Object.keys(assigner);
keys.forEach((key) => {
result[key] = assigner[key];
});
}
}
return obj;
}
/**
* Get short version/alias for a browser name
*
* @example
* getBrowserAlias('Microsoft Edge') // edge
*
* @param {string} browserName
* @return {string}
*/
static getBrowserAlias(browserName) {
return BROWSER_ALIASES_MAP[browserName];
}
/**
* Get browser name for a short version/alias
*
* @example
* getBrowserTypeByAlias('edge') // Microsoft Edge
*
* @param {string} browserAlias
* @return {string}
*/
static getBrowserTypeByAlias(browserAlias) {
return BROWSER_MAP[browserAlias] || '';
}
}