mirror of
https://github.com/lancedikson/bowser
synced 2025-12-05 06:02:14 +00:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0f51d8bce8 | ||
|
|
1df8838756 | ||
|
|
eef8480944 | ||
|
|
514510d847 | ||
|
|
4a6dacca08 | ||
|
|
be90a00e37 | ||
|
|
f7d2c0693c | ||
|
|
771dfb2dfe | ||
|
|
bd5cb7186c | ||
|
|
2b5ee5de8c | ||
|
|
a4d0b828e4 | ||
|
|
5bfd3e9e6c | ||
|
|
3c25806efe |
129
.github/copilot-instructions.md
vendored
Normal file
129
.github/copilot-instructions.md
vendored
Normal file
@ -0,0 +1,129 @@
|
||||
# Copilot Instructions for Bowser
|
||||
|
||||
## Project Overview
|
||||
|
||||
Bowser is a small, fast, and rich-API browser/platform/engine detector for both browser and Node.js environments. It's designed to parse User-Agent strings and provide detailed information about browsers, operating systems, platforms, and rendering engines.
|
||||
|
||||
## Architecture
|
||||
|
||||
### Core Components
|
||||
|
||||
- **`src/bowser.js`**: Main entry point and public API. Provides static methods `getParser()` and `parse()`.
|
||||
- **`src/parser.js`**: Core parsing engine that orchestrates all parsers and returns structured results.
|
||||
- **`src/parser-browsers.js`**: Browser detection logic using regex patterns.
|
||||
- **`src/parser-os.js`**: Operating system detection logic.
|
||||
- **`src/parser-platforms.js`**: Platform type detection (desktop, tablet, mobile).
|
||||
- **`src/parser-engines.js`**: Rendering engine detection (WebKit, Blink, Gecko, etc.).
|
||||
- **`src/constants.js`**: Centralized constants including browser aliases and mappings.
|
||||
- **`src/utils.js`**: Utility functions for string matching and manipulation.
|
||||
|
||||
### Build Output
|
||||
|
||||
- **`es5.js`**: ES5 transpiled version (default export).
|
||||
- **`bundled.js`**: ES5 version with babel-polyfill included.
|
||||
|
||||
## Development Workflow
|
||||
|
||||
### Setup
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
### Key Commands
|
||||
|
||||
- **Build**: `npm run build` - Compiles source files using Webpack and Babel.
|
||||
- **Test**: `npm test` - Runs unit and acceptance tests using AVA.
|
||||
- **Lint**: `npm run lint:check` - Checks code style using ESLint.
|
||||
- **Lint Fix**: `npm run lint:fix` - Auto-fixes linting issues.
|
||||
- **Watch Mode**: `npm run watch` - Builds on file changes.
|
||||
- **Test Watch**: `npm run test:watch` - Runs tests on file changes.
|
||||
|
||||
### Testing
|
||||
|
||||
- Tests are located in `test/acceptance/` and `test/unit/`.
|
||||
- Acceptance tests use real User-Agent strings from `test/acceptance/useragentstrings.yml`.
|
||||
- Always update `useragentstrings.yml` when adding browser support.
|
||||
- Test framework: AVA with Babel integration.
|
||||
|
||||
## Coding Standards
|
||||
|
||||
### Style Guide
|
||||
|
||||
- **ESLint Config**: Based on Airbnb Base style guide.
|
||||
- **Parser**: Uses `babel-eslint`.
|
||||
- **Exceptions**:
|
||||
- Underscore-dangle allowed for private properties.
|
||||
- `no-void` disabled.
|
||||
- ES6 imports must include `.js` extension.
|
||||
|
||||
### Naming Conventions
|
||||
|
||||
- **Browser Aliases**: Use lowercase letters, replace spaces/dashes with underscores, drop "browser" suffix.
|
||||
- Examples: `Opera Coast` → `opera_coast`, `UC Browser` → `uc`, `SeaMonkey` → `seamonkey`.
|
||||
- **Private Properties**: Prefix with underscore (e.g., `_ua`).
|
||||
- **Constants**: Use `UPPER_SNAKE_CASE` for constant maps and aliases.
|
||||
|
||||
### Code Patterns
|
||||
|
||||
- Use ES6 modules with explicit `.js` extensions.
|
||||
- Prefer static methods in Bowser class.
|
||||
- Use class-based structure for Parser.
|
||||
- Regex patterns should be well-documented and tested.
|
||||
- Keep parsers modular and focused on single responsibility.
|
||||
|
||||
## Adding Browser Support
|
||||
|
||||
When adding support for a new browser:
|
||||
|
||||
1. Add regex pattern to `src/parser-browsers.js`.
|
||||
2. Add browser name to `BROWSER_ALIASES_MAP` in `src/constants.js`.
|
||||
3. Add corresponding entry to `BROWSER_MAP`.
|
||||
4. Add test cases to `test/acceptance/useragentstrings.yml`.
|
||||
5. Run tests to verify: `npm test`.
|
||||
6. Check for duplicates before adding aliases.
|
||||
|
||||
## Branching Strategy
|
||||
|
||||
- **`master`**: Development branch.
|
||||
- **`production`**: Production branch.
|
||||
- **New Features**: Branch from `master`, PR back to `master`.
|
||||
- **Hot-fixes/Browser Support**: Branch from `production`, PR back to `production`.
|
||||
|
||||
## Important Files
|
||||
|
||||
- **`index.d.ts`**: TypeScript definitions.
|
||||
- **`.babelrc`**: Babel configuration for ES5 transpilation.
|
||||
- **`webpack.config.js`**: Build configuration.
|
||||
- **`.eslintrc.yml`**: Linting rules.
|
||||
- **`package.json`**: Dependencies and scripts.
|
||||
|
||||
## API Design Principles
|
||||
|
||||
- Keep the API simple and intuitive.
|
||||
- Bowser class should be stateless and provide factory methods.
|
||||
- Parser class handles instance-specific logic.
|
||||
- Results should be structured and predictable.
|
||||
- Support both immediate parsing and lazy parsing.
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
- Parsers use lazy evaluation where possible.
|
||||
- Regex patterns are optimized for common browsers first.
|
||||
- Optional `skipParsing` parameter for delayed parsing.
|
||||
- Minimal bundle size is a priority (~4.8kB gzipped).
|
||||
|
||||
## Documentation
|
||||
|
||||
- Use JSDoc comments for all public APIs.
|
||||
- Document parameters, return types, and provide examples.
|
||||
- Update README.md for API changes.
|
||||
- Generate docs with: `npm run generate-docs`.
|
||||
|
||||
## Common Pitfalls
|
||||
|
||||
- Always check `BROWSER_ALIASES_MAP` for existing aliases before adding new ones.
|
||||
- User-Agent strings can be complex; test edge cases thoroughly.
|
||||
- Remember to update both the alias map and the reverse map in constants.
|
||||
- Browser versions should be treated as strings, not numbers.
|
||||
- Keep regex patterns readable with comments explaining their purpose.
|
||||
43
.github/workflows/publish.yml
vendored
43
.github/workflows/publish.yml
vendored
@ -4,6 +4,13 @@ on:
|
||||
# This job runs when a new release is published
|
||||
release:
|
||||
types: [published]
|
||||
# Manual trigger with version input
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: "Version to release (e.g., 2.12.1)"
|
||||
required: true
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
release:
|
||||
@ -13,16 +20,44 @@ jobs:
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 12.16.3
|
||||
registry-url: "https://registry.npmjs.org"
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.npm
|
||||
key: ${{ runner.os }}-node-${{ hashFiles('**/package.json') }}
|
||||
# Store the name of the release
|
||||
# See https://stackoverflow.com/questions/58177786/get-the-current-pushed-tag-in-github-actions
|
||||
- run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
|
||||
# Store the release version (from release tag or manual input)
|
||||
- name: Set release version
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
||||
echo "RELEASE_VERSION=${{ github.event.inputs.version }}" >> $GITHUB_ENV
|
||||
echo "Manual release triggered for version: ${{ github.event.inputs.version }}"
|
||||
else
|
||||
echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
|
||||
echo "Release triggered from tag: ${GITHUB_REF#refs/*/}"
|
||||
fi
|
||||
- run: npm ci
|
||||
- run: npm version $RELEASE_VERSION --no-git-tag-version
|
||||
- run: npm run build
|
||||
- run: npm publish --access public
|
||||
- name: Publish to npm with retry
|
||||
run: |
|
||||
max_attempts=5
|
||||
attempt=1
|
||||
while [ $attempt -le $max_attempts ]; do
|
||||
echo "Attempt $attempt of $max_attempts..."
|
||||
if npm publish --access public; then
|
||||
echo "Successfully published!"
|
||||
break
|
||||
else
|
||||
if [ $attempt -eq $max_attempts ]; then
|
||||
echo "Failed to publish after $max_attempts attempts"
|
||||
exit 1
|
||||
fi
|
||||
echo "Publish failed, waiting before retry..."
|
||||
sleep_time=$((attempt * 30))
|
||||
echo "Waiting ${sleep_time} seconds before retry..."
|
||||
sleep $sleep_time
|
||||
attempt=$((attempt + 1))
|
||||
fi
|
||||
done
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.BOWSER_NPM_PUBLISH_TOKEN }}
|
||||
|
||||
@ -6,7 +6,7 @@ A small, fast and rich-API browser/platform/engine detector for both browser and
|
||||
|
||||
Don't hesitate to support the project on Github or [OpenCollective](https://opencollective.com/bowser) if you like it ❤️ Also, contributors are always welcome!
|
||||
|
||||
[](https://opencollective.com/bowser) [](https://travis-ci.org/lancedikson/bowser/) [](https://greenkeeper.io/) [](https://coveralls.io/github/lancedikson/bowser?branch=master) 
|
||||
[](https://opencollective.com/bowser) [](https://travis-ci.org/bowser-js/bowser/) [](https://greenkeeper.io/) [](https://coveralls.io/github/bowser-js/bowser?branch=master) 
|
||||
|
||||
# Contents
|
||||
- [Overview](#overview)
|
||||
@ -20,7 +20,7 @@ The library is made to help to detect what browser your user has and gives you a
|
||||
|
||||
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/lancedikson/bowser/tree/v1.x) branch and install it through `npm install bowser@1.9.4`._
|
||||
_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
|
||||
|
||||
@ -148,7 +148,7 @@ list of aliases can be found in [the file](src/constants.js).
|
||||
### Code Contributors
|
||||
|
||||
This project exists thanks to all the people who contribute. [[Contribute](.github/CONTRIBUTING.md)].
|
||||
<a href="https://github.com/lancedikson/bowser/graphs/contributors"><img src="https://opencollective.com/bowser/contributors.svg?width=890&button=false" /></a>
|
||||
<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
|
||||
|
||||
|
||||
@ -1226,7 +1226,12 @@
|
||||
10.12 - Sierra
|
||||
10.13 - High Sierra
|
||||
10.14 - Mojave
|
||||
10.15 - Catalina</p>
|
||||
10.15 - Catalina
|
||||
11 - Big Sur
|
||||
12 - Monterey
|
||||
13 - Ventura
|
||||
14 - Sonoma
|
||||
15 - Sequoia</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
@ -110,6 +110,11 @@ export default class Utils {
|
||||
* 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'
|
||||
@ -120,8 +125,11 @@ export default class Utils {
|
||||
static getMacOSVersionName(version) {
|
||||
const v = version.split('.').splice(0, 2).map(s => parseInt(s, 10) || 0);
|
||||
v.push(0);
|
||||
if (v[0] !== 10) return undefined;
|
||||
switch (v[1]) {
|
||||
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';
|
||||
@ -137,6 +145,16 @@ export default class Utils {
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
4
index.d.ts
vendored
4
index.d.ts
vendored
@ -1,8 +1,8 @@
|
||||
// Type definitions for Bowser v2
|
||||
// Project: https://github.com/lancedikson/bowser
|
||||
// Project: https://github.com/bowser-js/bowser
|
||||
// Definitions by: Alexander P. Cerutti <https://github.com/alexandercerutti>,
|
||||
|
||||
export default Bowser;
|
||||
export = Bowser;
|
||||
export as namespace Bowser;
|
||||
|
||||
declare namespace Bowser {
|
||||
|
||||
10
package.json
10
package.json
@ -11,12 +11,16 @@
|
||||
"ender",
|
||||
"sniff"
|
||||
],
|
||||
"homepage": "https://github.com/lancedikson/bowser",
|
||||
"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",
|
||||
@ -25,7 +29,7 @@
|
||||
"types": "index.d.ts",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/lancedikson/bowser.git"
|
||||
"url": "git+https://github.com/bowser-js/bowser.git"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.11.6",
|
||||
@ -61,7 +65,7 @@
|
||||
]
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/lancedikson/bowser/issues"
|
||||
"url": "https://github.com/bowser-js/bowser/issues"
|
||||
},
|
||||
"directories": {
|
||||
"test": "test"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/*!
|
||||
* Bowser - a browser detector
|
||||
* https://github.com/lancedikson/bowser
|
||||
* https://github.com/bowser-js/bowser
|
||||
* MIT License | (c) Dustin Diaz 2012-2015
|
||||
* MIT License | (c) Denis Demchenko 2015-2019
|
||||
*/
|
||||
|
||||
@ -1,119 +1,169 @@
|
||||
// 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',
|
||||
BlackBerry: 'blackberry',
|
||||
'ChatGPT-User': 'chatgpt_user',
|
||||
Chrome: 'chrome',
|
||||
ClaudeBot: 'claudebot',
|
||||
Chromium: 'chromium',
|
||||
Diffbot: 'diffbot',
|
||||
DuckDuckBot: 'duckduckbot',
|
||||
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',
|
||||
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',
|
||||
QupZilla: 'qupzilla',
|
||||
QQ: 'qq',
|
||||
QQLite: 'qqlite',
|
||||
QupZilla: 'qupzilla',
|
||||
Roku: 'roku',
|
||||
Safari: 'safari',
|
||||
Sailfish: 'sailfish',
|
||||
'Samsung Internet for Android': 'samsung_internet',
|
||||
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',
|
||||
Roku: 'roku',
|
||||
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',
|
||||
chatgpt_user: 'ChatGPT-User',
|
||||
chrome: 'Chrome',
|
||||
claudebot: 'ClaudeBot',
|
||||
chromium: 'Chromium',
|
||||
diffbot: 'Diffbot',
|
||||
duckduckbot: 'DuckDuckBot',
|
||||
edge: 'Microsoft Edge',
|
||||
electron: 'Electron',
|
||||
epiphany: 'Epiphany',
|
||||
facebookexternalhit: 'FacebookExternalHit',
|
||||
firefox: 'Firefox',
|
||||
focus: 'Focus',
|
||||
generic: 'Generic',
|
||||
googlebot: 'Googlebot',
|
||||
google_search: 'Google Search',
|
||||
googlebot: 'Googlebot',
|
||||
gptbot: 'GPTBot',
|
||||
ie: 'Internet Explorer',
|
||||
internetarchivecrawler: 'InternetArchiveCrawler',
|
||||
k_meleon: 'K-Meleon',
|
||||
librewolf: 'LibreWolf',
|
||||
maxthon: 'Maxthon',
|
||||
edge: 'Microsoft Edge',
|
||||
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',
|
||||
qupzilla: 'QupZilla',
|
||||
qq: 'QQ Browser',
|
||||
qqlite: 'QQ Browser Lite',
|
||||
qupzilla: 'QupZilla',
|
||||
roku: 'Roku',
|
||||
safari: 'Safari',
|
||||
sailfish: 'Sailfish',
|
||||
samsung_internet: 'Samsung Internet for Android',
|
||||
seamonkey: 'SeaMonkey',
|
||||
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 = {
|
||||
tablet: 'tablet',
|
||||
mobile: 'mobile',
|
||||
desktop: 'desktop',
|
||||
tv: 'tv',
|
||||
bot: 'bot',
|
||||
desktop: 'desktop',
|
||||
mobile: 'mobile',
|
||||
tablet: 'tablet',
|
||||
tv: 'tv',
|
||||
};
|
||||
|
||||
export const OS_MAP = {
|
||||
WindowsPhone: 'Windows Phone',
|
||||
Windows: 'Windows',
|
||||
MacOS: 'macOS',
|
||||
iOS: 'iOS',
|
||||
Android: 'Android',
|
||||
WebOS: 'WebOS',
|
||||
BlackBerry: 'BlackBerry',
|
||||
Bada: 'Bada',
|
||||
Tizen: 'Tizen',
|
||||
Linux: 'Linux',
|
||||
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 = {
|
||||
EdgeHTML: 'EdgeHTML',
|
||||
Blink: 'Blink',
|
||||
Trident: 'Trident',
|
||||
Presto: 'Presto',
|
||||
EdgeHTML: 'EdgeHTML',
|
||||
Gecko: 'Gecko',
|
||||
Presto: 'Presto',
|
||||
Trident: 'Trident',
|
||||
WebKit: 'WebKit',
|
||||
};
|
||||
|
||||
@ -28,6 +28,227 @@ import Utils from './utils.js';
|
||||
const commonVersionIdentifier = /version\/(\d+(\.?_?\d+)+)/i;
|
||||
|
||||
const browsersList = [
|
||||
/* GPTBot */
|
||||
{
|
||||
test: [/gptbot/i],
|
||||
describe(ua) {
|
||||
const browser = {
|
||||
name: 'GPTBot',
|
||||
};
|
||||
const version = Utils.getFirstMatch(/gptbot\/(\d+(\.\d+)+)/i, ua) || Utils.getFirstMatch(commonVersionIdentifier, ua);
|
||||
|
||||
if (version) {
|
||||
browser.version = version;
|
||||
}
|
||||
|
||||
return browser;
|
||||
},
|
||||
},
|
||||
|
||||
/* ChatGPT-User */
|
||||
{
|
||||
test: [/chatgpt-user/i],
|
||||
describe(ua) {
|
||||
const browser = {
|
||||
name: 'ChatGPT-User',
|
||||
};
|
||||
const version = Utils.getFirstMatch(/chatgpt-user\/(\d+(\.\d+)+)/i, ua) || Utils.getFirstMatch(commonVersionIdentifier, ua);
|
||||
|
||||
if (version) {
|
||||
browser.version = version;
|
||||
}
|
||||
|
||||
return browser;
|
||||
},
|
||||
},
|
||||
|
||||
/* OAI-SearchBot */
|
||||
{
|
||||
test: [/oai-searchbot/i],
|
||||
describe(ua) {
|
||||
const browser = {
|
||||
name: 'OAI-SearchBot',
|
||||
};
|
||||
const version = Utils.getFirstMatch(/oai-searchbot\/(\d+(\.\d+)+)/i, ua) || Utils.getFirstMatch(commonVersionIdentifier, ua);
|
||||
|
||||
if (version) {
|
||||
browser.version = version;
|
||||
}
|
||||
|
||||
return browser;
|
||||
},
|
||||
},
|
||||
|
||||
/* ClaudeBot */
|
||||
{
|
||||
test: [/claudebot/i, /claude-web/i, /claude-user/i, /claude-searchbot/i],
|
||||
describe(ua) {
|
||||
const browser = {
|
||||
name: 'ClaudeBot',
|
||||
};
|
||||
const version = Utils.getFirstMatch(/(?:claudebot|claude-web|claude-user|claude-searchbot)\/(\d+(\.\d+)+)/i, ua) || Utils.getFirstMatch(commonVersionIdentifier, ua);
|
||||
|
||||
if (version) {
|
||||
browser.version = version;
|
||||
}
|
||||
|
||||
return browser;
|
||||
},
|
||||
},
|
||||
|
||||
/* Omgilibot */
|
||||
{
|
||||
test: [/omgilibot/i, /webzio-extended/i],
|
||||
describe(ua) {
|
||||
const browser = {
|
||||
name: 'Omgilibot',
|
||||
};
|
||||
const version = Utils.getFirstMatch(/(?:omgilibot|webzio-extended)\/(\d+(\.\d+)+)/i, ua) || Utils.getFirstMatch(commonVersionIdentifier, ua);
|
||||
|
||||
if (version) {
|
||||
browser.version = version;
|
||||
}
|
||||
|
||||
return browser;
|
||||
},
|
||||
},
|
||||
|
||||
/* Diffbot */
|
||||
{
|
||||
test: [/diffbot/i],
|
||||
describe(ua) {
|
||||
const browser = {
|
||||
name: 'Diffbot',
|
||||
};
|
||||
const version = Utils.getFirstMatch(/diffbot\/(\d+(\.\d+)+)/i, ua) || Utils.getFirstMatch(commonVersionIdentifier, ua);
|
||||
|
||||
if (version) {
|
||||
browser.version = version;
|
||||
}
|
||||
|
||||
return browser;
|
||||
},
|
||||
},
|
||||
|
||||
/* PerplexityBot */
|
||||
{
|
||||
test: [/perplexitybot/i],
|
||||
describe(ua) {
|
||||
const browser = {
|
||||
name: 'PerplexityBot',
|
||||
};
|
||||
const version = Utils.getFirstMatch(/perplexitybot\/(\d+(\.\d+)+)/i, ua) || Utils.getFirstMatch(commonVersionIdentifier, ua);
|
||||
|
||||
if (version) {
|
||||
browser.version = version;
|
||||
}
|
||||
|
||||
return browser;
|
||||
},
|
||||
},
|
||||
|
||||
/* Perplexity-User */
|
||||
{
|
||||
test: [/perplexity-user/i],
|
||||
describe(ua) {
|
||||
const browser = {
|
||||
name: 'Perplexity-User',
|
||||
};
|
||||
const version = Utils.getFirstMatch(/perplexity-user\/(\d+(\.\d+)+)/i, ua) || Utils.getFirstMatch(commonVersionIdentifier, ua);
|
||||
|
||||
if (version) {
|
||||
browser.version = version;
|
||||
}
|
||||
|
||||
return browser;
|
||||
},
|
||||
},
|
||||
|
||||
/* YouBot */
|
||||
{
|
||||
test: [/youbot/i],
|
||||
describe(ua) {
|
||||
const browser = {
|
||||
name: 'YouBot',
|
||||
};
|
||||
const version = Utils.getFirstMatch(/youbot\/(\d+(\.\d+)+)/i, ua) || Utils.getFirstMatch(commonVersionIdentifier, ua);
|
||||
|
||||
if (version) {
|
||||
browser.version = version;
|
||||
}
|
||||
|
||||
return browser;
|
||||
},
|
||||
},
|
||||
|
||||
/* Meta-WebIndexer */
|
||||
{
|
||||
test: [/meta-webindexer/i],
|
||||
describe(ua) {
|
||||
const browser = {
|
||||
name: 'Meta-WebIndexer',
|
||||
};
|
||||
const version = Utils.getFirstMatch(/meta-webindexer\/(\d+(\.\d+)+)/i, ua) || Utils.getFirstMatch(commonVersionIdentifier, ua);
|
||||
|
||||
if (version) {
|
||||
browser.version = version;
|
||||
}
|
||||
|
||||
return browser;
|
||||
},
|
||||
},
|
||||
|
||||
/* Meta-ExternalAds */
|
||||
{
|
||||
test: [/meta-externalads/i],
|
||||
describe(ua) {
|
||||
const browser = {
|
||||
name: 'Meta-ExternalAds',
|
||||
};
|
||||
const version = Utils.getFirstMatch(/meta-externalads\/(\d+(\.\d+)+)/i, ua) || Utils.getFirstMatch(commonVersionIdentifier, ua);
|
||||
|
||||
if (version) {
|
||||
browser.version = version;
|
||||
}
|
||||
|
||||
return browser;
|
||||
},
|
||||
},
|
||||
|
||||
/* Meta-ExternalAgent */
|
||||
{
|
||||
test: [/meta-externalagent/i],
|
||||
describe(ua) {
|
||||
const browser = {
|
||||
name: 'Meta-ExternalAgent',
|
||||
};
|
||||
const version = Utils.getFirstMatch(/meta-externalagent\/(\d+(\.\d+)+)/i, ua) || Utils.getFirstMatch(commonVersionIdentifier, ua);
|
||||
|
||||
if (version) {
|
||||
browser.version = version;
|
||||
}
|
||||
|
||||
return browser;
|
||||
},
|
||||
},
|
||||
|
||||
/* Meta-ExternalFetcher */
|
||||
{
|
||||
test: [/meta-externalfetcher/i],
|
||||
describe(ua) {
|
||||
const browser = {
|
||||
name: 'Meta-ExternalFetcher',
|
||||
};
|
||||
const version = Utils.getFirstMatch(/meta-externalfetcher\/(\d+(\.\d+)+)/i, ua) || Utils.getFirstMatch(commonVersionIdentifier, ua);
|
||||
|
||||
if (version) {
|
||||
browser.version = version;
|
||||
}
|
||||
|
||||
return browser;
|
||||
},
|
||||
},
|
||||
|
||||
/* Googlebot */
|
||||
{
|
||||
test: [/googlebot/i],
|
||||
@ -45,6 +266,131 @@ const browsersList = [
|
||||
},
|
||||
},
|
||||
|
||||
/* AmazonBot */
|
||||
{
|
||||
test: [/amazonbot/i],
|
||||
describe(ua) {
|
||||
const browser = {
|
||||
name: 'AmazonBot',
|
||||
};
|
||||
const version = Utils.getFirstMatch(/amazonbot\/(\d+(\.\d+)+)/i, ua) || Utils.getFirstMatch(commonVersionIdentifier, ua);
|
||||
|
||||
if (version) {
|
||||
browser.version = version;
|
||||
}
|
||||
|
||||
return browser;
|
||||
},
|
||||
},
|
||||
|
||||
/* BingCrawler */
|
||||
{
|
||||
test: [/bingbot/i],
|
||||
describe(ua) {
|
||||
const browser = {
|
||||
name: 'BingCrawler',
|
||||
};
|
||||
const version = Utils.getFirstMatch(/bingbot\/(\d+(\.\d+)+)/i, ua) || Utils.getFirstMatch(commonVersionIdentifier, ua);
|
||||
|
||||
if (version) {
|
||||
browser.version = version;
|
||||
}
|
||||
|
||||
return browser;
|
||||
},
|
||||
},
|
||||
|
||||
/* BaiduSpider */
|
||||
{
|
||||
test: [/baiduspider/i],
|
||||
describe(ua) {
|
||||
const browser = {
|
||||
name: 'BaiduSpider',
|
||||
};
|
||||
const version = Utils.getFirstMatch(/baiduspider\/(\d+(\.\d+)+)/i, ua) || Utils.getFirstMatch(commonVersionIdentifier, ua);
|
||||
|
||||
if (version) {
|
||||
browser.version = version;
|
||||
}
|
||||
|
||||
return browser;
|
||||
},
|
||||
},
|
||||
|
||||
/* DuckDuckBot */
|
||||
{
|
||||
test: [/duckduckbot/i],
|
||||
describe(ua) {
|
||||
const browser = {
|
||||
name: 'DuckDuckBot',
|
||||
};
|
||||
const version = Utils.getFirstMatch(/duckduckbot\/(\d+(\.\d+)+)/i, ua) || Utils.getFirstMatch(commonVersionIdentifier, ua);
|
||||
|
||||
if (version) {
|
||||
browser.version = version;
|
||||
}
|
||||
|
||||
return browser;
|
||||
},
|
||||
},
|
||||
|
||||
/* InternetArchiveCrawler */
|
||||
{
|
||||
test: [/ia_archiver/i],
|
||||
describe(ua) {
|
||||
const browser = {
|
||||
name: 'InternetArchiveCrawler',
|
||||
};
|
||||
const version = Utils.getFirstMatch(/ia_archiver\/(\d+(\.\d+)+)/i, ua) || Utils.getFirstMatch(commonVersionIdentifier, ua);
|
||||
|
||||
if (version) {
|
||||
browser.version = version;
|
||||
}
|
||||
|
||||
return browser;
|
||||
},
|
||||
},
|
||||
|
||||
/* FacebookExternalHit */
|
||||
{
|
||||
test: [/facebookexternalhit/i, /facebookcatalog/i],
|
||||
describe() {
|
||||
return {
|
||||
name: 'FacebookExternalHit',
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
/* YahooSlurp */
|
||||
{
|
||||
test: [/yahoo!?[\s/]*slurp/i],
|
||||
describe() {
|
||||
return {
|
||||
name: 'YahooSlurp',
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
/* YandexBot */
|
||||
{
|
||||
test: [/yandexbot/i, /yandexmobilebot/i],
|
||||
describe() {
|
||||
return {
|
||||
name: 'YandexBot',
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
/* PingdomBot */
|
||||
{
|
||||
test: [/pingdom/i],
|
||||
describe() {
|
||||
return {
|
||||
name: 'PingdomBot',
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
/* Opera < 13.0 */
|
||||
{
|
||||
test: [/opera/i],
|
||||
@ -546,6 +892,21 @@ const browsersList = [
|
||||
return browser;
|
||||
},
|
||||
},
|
||||
{
|
||||
test: [/librewolf/i],
|
||||
describe(ua) {
|
||||
const browser = {
|
||||
name: 'LibreWolf',
|
||||
};
|
||||
const version = Utils.getFirstMatch(/(?:librewolf)[\s/](\d+(\.?_?\d+)+)/i, ua);
|
||||
|
||||
if (version) {
|
||||
browser.version = version;
|
||||
}
|
||||
|
||||
return browser;
|
||||
},
|
||||
},
|
||||
{
|
||||
test: [/firefox|iceweasel|fxios/i],
|
||||
describe(ua) {
|
||||
@ -576,6 +937,24 @@ const browsersList = [
|
||||
return browser;
|
||||
},
|
||||
},
|
||||
{
|
||||
test: [/sogoumobilebrowser/i, /metasr/i, /se 2\.[x]/i],
|
||||
describe(ua) {
|
||||
const browser = {
|
||||
name: 'Sogou Browser',
|
||||
};
|
||||
const sogouMobileVersion = Utils.getFirstMatch(/(?:sogoumobilebrowser)[\s/](\d+(\.?_?\d+)+)/i, ua);
|
||||
const chromiumVersion = Utils.getFirstMatch(/(?:chrome|crios|crmo)\/(\d+(\.?_?\d+)+)/i, ua);
|
||||
const seVersion = Utils.getFirstMatch(/se ([\d.]+)x/i, ua);
|
||||
const version = sogouMobileVersion || chromiumVersion || seVersion;
|
||||
|
||||
if (version) {
|
||||
browser.version = version;
|
||||
}
|
||||
|
||||
return browser;
|
||||
},
|
||||
},
|
||||
{
|
||||
test: [/MiuiBrowser/i],
|
||||
describe(ua) {
|
||||
|
||||
@ -87,6 +87,18 @@ export default [
|
||||
},
|
||||
},
|
||||
|
||||
/* 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) {
|
||||
|
||||
@ -18,6 +18,248 @@ export default [
|
||||
},
|
||||
},
|
||||
|
||||
/* 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',
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
/* 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],
|
||||
|
||||
22
src/utils.js
22
src/utils.js
@ -66,6 +66,11 @@ export default class Utils {
|
||||
* 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'
|
||||
@ -76,8 +81,11 @@ export default class Utils {
|
||||
static getMacOSVersionName(version) {
|
||||
const v = version.split('.').splice(0, 2).map(s => parseInt(s, 10) || 0);
|
||||
v.push(0);
|
||||
if (v[0] !== 10) return undefined;
|
||||
switch (v[1]) {
|
||||
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';
|
||||
@ -93,6 +101,16 @@ export default class Utils {
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
@ -365,6 +365,20 @@
|
||||
type: "mobile"
|
||||
engine:
|
||||
name: "Blink"
|
||||
-
|
||||
ua: "Mozilla/5.0 (Phone; OpenHarmony 5.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 ArkWeb/4.1.6.1 Mobile HuaweiBrowser/5.1.5.352"
|
||||
spec:
|
||||
browser:
|
||||
name: "Chrome"
|
||||
version: "114.0.0.0"
|
||||
os:
|
||||
name: "HarmonyOS"
|
||||
version: "5.0"
|
||||
platform:
|
||||
type: "mobile"
|
||||
vendor: "Huawei"
|
||||
engine:
|
||||
name: "Blink"
|
||||
Google Search:
|
||||
-
|
||||
ua: "Mozilla/5.0 (iPhone; CPU iPhone OS 12_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) GSA/83.0.268992909 Mobile/15E148 Safari/605.1"
|
||||
@ -905,6 +919,86 @@
|
||||
engine:
|
||||
name: "WebKit"
|
||||
version: "525.28.3"
|
||||
-
|
||||
ua: "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_0) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Safari/605.1.15"
|
||||
spec:
|
||||
browser:
|
||||
name: "Safari"
|
||||
version: "14.0"
|
||||
os:
|
||||
name: "macOS"
|
||||
version: "11.0"
|
||||
versionName: "Big Sur"
|
||||
platform:
|
||||
type: "desktop"
|
||||
vendor: "Apple"
|
||||
engine:
|
||||
name: "WebKit"
|
||||
version: "605.1.15"
|
||||
-
|
||||
ua: "Mozilla/5.0 (Macintosh; Intel Mac OS X 12_3) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.4 Safari/605.1.15"
|
||||
spec:
|
||||
browser:
|
||||
name: "Safari"
|
||||
version: "15.4"
|
||||
os:
|
||||
name: "macOS"
|
||||
version: "12.3"
|
||||
versionName: "Monterey"
|
||||
platform:
|
||||
type: "desktop"
|
||||
vendor: "Apple"
|
||||
engine:
|
||||
name: "WebKit"
|
||||
version: "605.1.15"
|
||||
-
|
||||
ua: "Mozilla/5.0 (Macintosh; Intel Mac OS X 13_2_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.3 Safari/605.1.15"
|
||||
spec:
|
||||
browser:
|
||||
name: "Safari"
|
||||
version: "16.3"
|
||||
os:
|
||||
name: "macOS"
|
||||
version: "13.2.1"
|
||||
versionName: "Ventura"
|
||||
platform:
|
||||
type: "desktop"
|
||||
vendor: "Apple"
|
||||
engine:
|
||||
name: "WebKit"
|
||||
version: "605.1.15"
|
||||
-
|
||||
ua: "Mozilla/5.0 (Macintosh; Intel Mac OS X 14_0) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Safari/605.1.15"
|
||||
spec:
|
||||
browser:
|
||||
name: "Safari"
|
||||
version: "17.0"
|
||||
os:
|
||||
name: "macOS"
|
||||
version: "14.0"
|
||||
versionName: "Sonoma"
|
||||
platform:
|
||||
type: "desktop"
|
||||
vendor: "Apple"
|
||||
engine:
|
||||
name: "WebKit"
|
||||
version: "605.1.15"
|
||||
-
|
||||
ua: "Mozilla/5.0 (Macintosh; Intel Mac OS X 15_0) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Safari/605.1.15"
|
||||
spec:
|
||||
browser:
|
||||
name: "Safari"
|
||||
version: "18.0"
|
||||
os:
|
||||
name: "macOS"
|
||||
version: "15.0"
|
||||
versionName: "Sequoia"
|
||||
platform:
|
||||
type: "desktop"
|
||||
vendor: "Apple"
|
||||
engine:
|
||||
name: "WebKit"
|
||||
version: "605.1.15"
|
||||
-
|
||||
ua: "Mozilla/5.0 (iPhone; CPU iPhone OS 7_0_4 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Mobile/11B554a"
|
||||
spec:
|
||||
@ -1901,6 +1995,20 @@
|
||||
engine:
|
||||
name: "WebKit"
|
||||
version: "605.1.15"
|
||||
LibreWolf:
|
||||
-
|
||||
ua: "Mozilla/5.0 (X11; Linux x86_64; rv:124.0) Gecko/20100101 LibreWolf/124.0.2"
|
||||
spec:
|
||||
browser:
|
||||
name: "LibreWolf"
|
||||
version: "124.0.2"
|
||||
os:
|
||||
name: "Linux"
|
||||
platform:
|
||||
type: "desktop"
|
||||
engine:
|
||||
name: "Gecko"
|
||||
version: "20100101"
|
||||
SeaMonkey:
|
||||
-
|
||||
ua: "Mozilla/5.0 (Windows NT 5.2; rv:10.0.1) Gecko/20100101 Firefox/10.0.1 SeaMonkey/2.7.1"
|
||||
@ -2535,6 +2643,379 @@
|
||||
vendor: "Google"
|
||||
engine:
|
||||
name: "Blink"
|
||||
GPTBot:
|
||||
-
|
||||
ua: "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; GPTBot/1.1; +https://openai.com/gptbot)"
|
||||
spec:
|
||||
browser:
|
||||
name: "GPTBot"
|
||||
version: "1.1"
|
||||
os: {}
|
||||
platform:
|
||||
type: "bot"
|
||||
vendor: "OpenAI"
|
||||
engine:
|
||||
name: "Blink"
|
||||
ChatGPT-User:
|
||||
-
|
||||
ua: "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ChatGPT-User/1.0; +https://openai.com/bot)"
|
||||
spec:
|
||||
browser:
|
||||
name: "ChatGPT-User"
|
||||
version: "1.0"
|
||||
os: {}
|
||||
platform:
|
||||
type: "bot"
|
||||
vendor: "OpenAI"
|
||||
engine:
|
||||
name: "Blink"
|
||||
OAI-SearchBot:
|
||||
-
|
||||
ua: "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; OAI-SearchBot/1.0; +https://openai.com/searchbot)"
|
||||
spec:
|
||||
browser:
|
||||
name: "OAI-SearchBot"
|
||||
version: "1.0"
|
||||
os: {}
|
||||
platform:
|
||||
type: "bot"
|
||||
vendor: "OpenAI"
|
||||
engine:
|
||||
name: "Blink"
|
||||
ClaudeBot:
|
||||
-
|
||||
ua: "Mozilla/5.0 (compatible; ClaudeBot/1.0; +https://www.anthropic.com/claudebot)"
|
||||
spec:
|
||||
browser:
|
||||
name: "ClaudeBot"
|
||||
version: "1.0"
|
||||
os: {}
|
||||
platform:
|
||||
type: "bot"
|
||||
vendor: "Anthropic"
|
||||
engine: {}
|
||||
Omgilibot:
|
||||
-
|
||||
ua: "Mozilla/5.0 (compatible; Omgilibot/1.0; +https://www.omgili.com)"
|
||||
spec:
|
||||
browser:
|
||||
name: "Omgilibot"
|
||||
version: "1.0"
|
||||
os: {}
|
||||
platform:
|
||||
type: "bot"
|
||||
vendor: "Webz.io"
|
||||
engine: {}
|
||||
Meta-WebIndexer:
|
||||
-
|
||||
ua: "meta-webindexer/1.1"
|
||||
spec:
|
||||
browser:
|
||||
name: "Meta-WebIndexer"
|
||||
version: "1.1"
|
||||
os: {}
|
||||
platform:
|
||||
type: "bot"
|
||||
vendor: "Meta"
|
||||
engine: {}
|
||||
-
|
||||
ua: "meta-webindexer/1.1 (+https://developers.facebook.com/docs/sharing/webmasters/crawler)"
|
||||
spec:
|
||||
browser:
|
||||
name: "Meta-WebIndexer"
|
||||
version: "1.1"
|
||||
os: {}
|
||||
platform:
|
||||
type: "bot"
|
||||
vendor: "Meta"
|
||||
engine: {}
|
||||
Meta-ExternalAds:
|
||||
-
|
||||
ua: "meta-externalads/1.1"
|
||||
spec:
|
||||
browser:
|
||||
name: "Meta-ExternalAds"
|
||||
version: "1.1"
|
||||
os: {}
|
||||
platform:
|
||||
type: "bot"
|
||||
vendor: "Meta"
|
||||
engine: {}
|
||||
-
|
||||
ua: "meta-externalads/1.1 (+https://developers.facebook.com/docs/sharing/webmasters/crawler)"
|
||||
spec:
|
||||
browser:
|
||||
name: "Meta-ExternalAds"
|
||||
version: "1.1"
|
||||
os: {}
|
||||
platform:
|
||||
type: "bot"
|
||||
vendor: "Meta"
|
||||
engine: {}
|
||||
Meta-ExternalAgent:
|
||||
-
|
||||
ua: "meta-externalagent/1.1"
|
||||
spec:
|
||||
browser:
|
||||
name: "Meta-ExternalAgent"
|
||||
version: "1.1"
|
||||
os: {}
|
||||
platform:
|
||||
type: "bot"
|
||||
vendor: "Meta"
|
||||
engine: {}
|
||||
-
|
||||
ua: "meta-externalagent/1.1 (+https://developers.facebook.com/docs/sharing/webmasters/crawler)"
|
||||
spec:
|
||||
browser:
|
||||
name: "Meta-ExternalAgent"
|
||||
version: "1.1"
|
||||
os: {}
|
||||
platform:
|
||||
type: "bot"
|
||||
vendor: "Meta"
|
||||
engine: {}
|
||||
Meta-ExternalFetcher:
|
||||
-
|
||||
ua: "meta-externalfetcher/1.1"
|
||||
spec:
|
||||
browser:
|
||||
name: "Meta-ExternalFetcher"
|
||||
version: "1.1"
|
||||
os: {}
|
||||
platform:
|
||||
type: "bot"
|
||||
vendor: "Meta"
|
||||
engine: {}
|
||||
-
|
||||
ua: "meta-externalfetcher/1.1 (+https://developers.facebook.com/docs/sharing/webmasters/crawler)"
|
||||
spec:
|
||||
browser:
|
||||
name: "Meta-ExternalFetcher"
|
||||
version: "1.1"
|
||||
os: {}
|
||||
platform:
|
||||
type: "bot"
|
||||
vendor: "Meta"
|
||||
engine: {}
|
||||
Diffbot:
|
||||
-
|
||||
ua: "Mozilla/5.0 (compatible; Diffbot/3.0; +http://www.diffbot.com)"
|
||||
spec:
|
||||
browser:
|
||||
name: "Diffbot"
|
||||
version: "3.0"
|
||||
os: {}
|
||||
platform:
|
||||
type: "bot"
|
||||
vendor: "Diffbot"
|
||||
engine: {}
|
||||
PerplexityBot:
|
||||
-
|
||||
ua: "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; PerplexityBot/1.0; +https://perplexity.ai/perplexitybot)"
|
||||
spec:
|
||||
browser:
|
||||
name: "PerplexityBot"
|
||||
version: "1.0"
|
||||
os: {}
|
||||
platform:
|
||||
type: "bot"
|
||||
vendor: "Perplexity AI"
|
||||
engine:
|
||||
name: "Blink"
|
||||
Perplexity-User:
|
||||
-
|
||||
ua: "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; Perplexity-User/1.0; +https://perplexity.ai/perplexity-user)"
|
||||
spec:
|
||||
browser:
|
||||
name: "Perplexity-User"
|
||||
version: "1.0"
|
||||
os: {}
|
||||
platform:
|
||||
type: "bot"
|
||||
vendor: "Perplexity AI"
|
||||
engine:
|
||||
name: "Blink"
|
||||
YouBot:
|
||||
-
|
||||
ua: "Mozilla/5.0 (compatible; YouBot/1.0; +https://you.com/bot)"
|
||||
spec:
|
||||
browser:
|
||||
name: "YouBot"
|
||||
version: "1.0"
|
||||
os: {}
|
||||
platform:
|
||||
type: "bot"
|
||||
vendor: "You.com"
|
||||
engine: {}
|
||||
AmazonBot:
|
||||
-
|
||||
ua: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/600.2.5 (KHTML, like Gecko) Version/8.0.2 Safari/600.2.5 (Amazonbot/0.1; +https://developer.amazon.com/support/amazonbot)"
|
||||
spec:
|
||||
browser:
|
||||
name: "AmazonBot"
|
||||
version: "0.1"
|
||||
os:
|
||||
name: "macOS"
|
||||
version: "10.10.1"
|
||||
versionName: "Yosemite"
|
||||
platform:
|
||||
type: "bot"
|
||||
vendor: "Amazon"
|
||||
engine:
|
||||
name: "WebKit"
|
||||
version: "600.2.5"
|
||||
BingCrawler:
|
||||
-
|
||||
ua: "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm) Chrome/"
|
||||
spec:
|
||||
browser:
|
||||
name: "BingCrawler"
|
||||
version: "2.0"
|
||||
os: {}
|
||||
platform:
|
||||
type: "bot"
|
||||
vendor: "Bing"
|
||||
engine:
|
||||
name: "Blink"
|
||||
-
|
||||
ua: "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm) 80.0.345.0 Safari/537.36"
|
||||
spec:
|
||||
browser:
|
||||
name: "BingCrawler"
|
||||
version: "2.0"
|
||||
os: {}
|
||||
platform:
|
||||
type: "bot"
|
||||
vendor: "Bing"
|
||||
engine: {}
|
||||
-
|
||||
ua: "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.345.0 Mobile Safari/537.36 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)"
|
||||
spec:
|
||||
browser:
|
||||
name: "BingCrawler"
|
||||
version: "2.0"
|
||||
os:
|
||||
name: "Android"
|
||||
version: "6.0.1"
|
||||
versionName: "Marshmallow"
|
||||
platform:
|
||||
type: "bot"
|
||||
vendor: "Bing"
|
||||
engine:
|
||||
name: "Blink"
|
||||
BaiduSpider:
|
||||
-
|
||||
ua: "Baiduspider"
|
||||
spec:
|
||||
browser:
|
||||
name: "BaiduSpider"
|
||||
os: {}
|
||||
platform:
|
||||
type: "bot"
|
||||
vendor: "Baidu"
|
||||
engine: {}
|
||||
DuckDuckBot:
|
||||
-
|
||||
ua: "DuckDuckBot/1.1; (+http://duckduckgo.com/duckduckbot.html)"
|
||||
spec:
|
||||
browser:
|
||||
name: "DuckDuckBot"
|
||||
version: "1.1"
|
||||
os: {}
|
||||
platform:
|
||||
type: "bot"
|
||||
vendor: "DuckDuckGo"
|
||||
engine: {}
|
||||
InternetArchiveCrawler:
|
||||
-
|
||||
ua: "ia_archiver"
|
||||
spec:
|
||||
browser:
|
||||
name: "InternetArchiveCrawler"
|
||||
os: {}
|
||||
platform:
|
||||
type: "bot"
|
||||
vendor: "Internet Archive"
|
||||
engine: {}
|
||||
FacebookExternalHit:
|
||||
-
|
||||
ua: "facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)"
|
||||
spec:
|
||||
browser:
|
||||
name: "FacebookExternalHit"
|
||||
os: {}
|
||||
platform:
|
||||
type: "bot"
|
||||
vendor: "Meta"
|
||||
engine: {}
|
||||
-
|
||||
ua: "facebookexternalhit/1.1"
|
||||
spec:
|
||||
browser:
|
||||
name: "FacebookExternalHit"
|
||||
os: {}
|
||||
platform:
|
||||
type: "bot"
|
||||
vendor: "Meta"
|
||||
engine: {}
|
||||
-
|
||||
ua: "facebookcatalog/1.0"
|
||||
spec:
|
||||
browser:
|
||||
name: "FacebookExternalHit"
|
||||
os: {}
|
||||
platform:
|
||||
type: "bot"
|
||||
vendor: "Meta"
|
||||
engine: {}
|
||||
YahooSlurp:
|
||||
-
|
||||
ua: "Mozilla/5.0 (compatible; Yahoo! Slurp; http://help.yahoo.com/help/us/ysearch/slurp)"
|
||||
spec:
|
||||
browser:
|
||||
name: "YahooSlurp"
|
||||
os: {}
|
||||
platform:
|
||||
type: "bot"
|
||||
vendor: "Yahoo"
|
||||
engine: {}
|
||||
YandexBot:
|
||||
-
|
||||
ua: "Mozilla/5.0 (compatible; YandexBot/3.0; +http://yandex.com/bots)"
|
||||
spec:
|
||||
browser:
|
||||
name: "YandexBot"
|
||||
os: {}
|
||||
platform:
|
||||
type: "bot"
|
||||
vendor: "Yandex"
|
||||
engine: {}
|
||||
-
|
||||
ua: "Mozilla/5.0 (iPhone; CPU iPhone OS 8_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12B411 Safari/600.1.4 (compatible; YandexMobileBot/3.0; +http://yandex.com/bots)"
|
||||
spec:
|
||||
browser:
|
||||
name: "YandexBot"
|
||||
os:
|
||||
name: "iOS"
|
||||
version: "8.1"
|
||||
platform:
|
||||
type: "bot"
|
||||
vendor: "Yandex"
|
||||
engine:
|
||||
name: "WebKit"
|
||||
version: "600.1.4"
|
||||
PingdomBot:
|
||||
-
|
||||
ua: "Pingdom.com_bot_version_1.4_(http://www.pingdom.com/)"
|
||||
spec:
|
||||
browser:
|
||||
name: "PingdomBot"
|
||||
os: {}
|
||||
platform:
|
||||
type: "bot"
|
||||
vendor: "Pingdom"
|
||||
engine: {}
|
||||
WeChat:
|
||||
-
|
||||
ua: "Mozilla/5.0 (iPad; U; CPU OS 9 like Mac OS X; en-us; iPad4,4) AppleWebKit/534.46 (KHTML, like Gecko) MicroMessenger/6.5.2.501 U3/1 Safari/7543.48.3"
|
||||
@ -2822,6 +3303,51 @@
|
||||
type: "mobile"
|
||||
engine:
|
||||
name: "Blink"
|
||||
Sogou Browser:
|
||||
-
|
||||
ua: "Mozilla/5.0 (Linux; Android 5.1.1; SM-G9280 Build/LMY47X; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/37.0.0.0 Mobile Safari/537.36 SogouMobileBrowser/3.5.3"
|
||||
spec:
|
||||
browser:
|
||||
name: "Sogou Browser"
|
||||
version: "3.5.3"
|
||||
os:
|
||||
name: "Android"
|
||||
version: "5.1.1"
|
||||
versionName: "Lollipop"
|
||||
platform:
|
||||
type: "mobile"
|
||||
engine:
|
||||
name: "Blink"
|
||||
-
|
||||
ua: "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.221 Safari/537.36 SE 2.X MetaSr 1.0"
|
||||
spec:
|
||||
browser:
|
||||
name: "Sogou Browser"
|
||||
version: "49.0.2623.221"
|
||||
os:
|
||||
name: "Windows"
|
||||
version: "NT 6.1"
|
||||
versionName: "7"
|
||||
platform:
|
||||
type: "desktop"
|
||||
engine:
|
||||
name: "Blink"
|
||||
-
|
||||
ua: "Mozilla/5.0 (iPhone; CPU iPhone OS 12_4_8 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 SogouMobileBrowser/5.22.1"
|
||||
spec:
|
||||
browser:
|
||||
name: "Sogou Browser"
|
||||
version: "5.22.1"
|
||||
os:
|
||||
name: "iOS"
|
||||
version: "12.4.8"
|
||||
platform:
|
||||
type: "mobile"
|
||||
vendor: "Apple"
|
||||
model: "iPhone"
|
||||
engine:
|
||||
name: "WebKit"
|
||||
version: "605.1.15"
|
||||
NAVER Whale Browser:
|
||||
-
|
||||
ua: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Whale/1.0.40.10 Safari/537.36"
|
||||
|
||||
@ -38,6 +38,11 @@ test('getWindowsVersionName', (t) => {
|
||||
test('getMacOSVersionName', (t) => {
|
||||
t.is(getMacOSVersionName('10.14.5'), 'Mojave');
|
||||
t.is(getMacOSVersionName('10.15'), 'Catalina');
|
||||
t.is(getMacOSVersionName('11.0'), 'Big Sur');
|
||||
t.is(getMacOSVersionName('12.3.1'), 'Monterey');
|
||||
t.is(getMacOSVersionName('13.2.1'), 'Ventura');
|
||||
t.is(getMacOSVersionName('14.0'), 'Sonoma');
|
||||
t.is(getMacOSVersionName('15.1'), 'Sequoia');
|
||||
t.is(getMacOSVersionName('10.999999'), void 0);
|
||||
t.is(getMacOSVersionName('XXX'), void 0);
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user