├── .eslintrc.json ├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── _config.yml ├── index.d.ts ├── index.js ├── index.umd.js ├── karma.conf.js ├── package-lock.json ├── package.json ├── test-main.js └── test ├── .eslintrc.json └── index.js /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "amd": true 4 | }, 5 | "rules": { 6 | "no-extend-native": "off", 7 | "indent": ["error", 4], 8 | "semi": ["error", "always"] 9 | }, 10 | "extends": "standard" 11 | } 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Typescript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | sudo: required 3 | dist: trusty 4 | node_js: lts/* 5 | env: 6 | - BROWSER=ChromeHeadless 7 | addons: 8 | chrome: stable 9 | before_install: 10 | - google-chrome-stable --headless --disable-gpu --remote-debugging-port=9222 http://localhost & 11 | 12 | jobs: 13 | include: 14 | - stage: test 15 | name: 'Linting' 16 | script: npm run lint 17 | - name: 'Unit Test' 18 | script: npm run coveralls 19 | - stage: release 20 | if: branch = master 21 | script: skip 22 | deploy: 23 | provider: script 24 | skip_cleanup: true 25 | script: npx semantic-release 26 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # [1.6.0](https://github.com/searchfe/user-agent/compare/v1.5.0...v1.6.0) (2021-02-09) 2 | 3 | 4 | ### Features 5 | 6 | * 增加百度主线(baidubox)或矩阵产品(bdapp)的版本判断 ([65df4ad](https://github.com/searchfe/user-agent/commit/65df4adda413efa29365e90fd4fc200092c3b846)) 7 | 8 | # [1.5.0](https://github.com/searchfe/user-agent/compare/v1.4.0...v1.5.0) (2021-01-13) 9 | 10 | 11 | ### Features 12 | 13 | * 支持识别百度矩阵产品和百度端内产品 ([89efc11](https://github.com/searchfe/user-agent/commit/89efc110d5986ebbc96db1eff1ad2e008aa31221)) 14 | 15 | # [1.4.0](https://github.com/searchfe/user-agent/compare/v1.3.4...v1.4.0) (2021-01-07) 16 | 17 | 18 | ### Features 19 | 20 | * 支持tomas百度老年版本的识别 ([170f63a](https://github.com/searchfe/user-agent/commit/170f63a157356ecf96af39b5a615b44857711bf3)) 21 | 22 | ## [1.3.4](https://github.com/searchfe/user-agent/compare/v1.3.3...v1.3.4) (2020-10-29) 23 | 24 | 25 | ### Bug Fixes 26 | 27 | * update isGoogleChrome ([ca24e14](https://github.com/searchfe/user-agent/commit/ca24e14e31c801c0785621b99aa61fa30c69d472)) 28 | 29 | ## [1.3.3](https://github.com/searchfe/user-agent/compare/v1.3.2...v1.3.3) (2020-10-27) 30 | 31 | 32 | ### Bug Fixes 33 | 34 | * 修复在oppo自带浏览器下ua不是oppobrowser而是heytapbrowser的问题 ([a4a3b94](https://github.com/searchfe/user-agent/commit/a4a3b94d6aa0d658187367d18b98e70bb9664d0c)) 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 searchfe 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # User Agent 工具 2 | 3 | [![Build Status](https://travis-ci.org/searchfe/user-agent.svg?branch=master)](https://travis-ci.org/searchfe/user-agent) 4 | [![Coverage Status](https://coveralls.io/repos/github/searchfe/user-agent/badge.svg?branch=master)](https://coveralls.io/github/searchfe/user-agent?branch=master) 5 | 6 | 这是一个 User Agent 检测工具。 7 | 8 | ## 安装 9 | 10 | ```bash 11 | apmjs install --save @searchfe/user-agent 12 | ``` 13 | 14 | ## 例子 15 | 16 | ```javascript 17 | var ua = require('@searchfe/user-agent') 18 | if (ua.isIOS()) { 19 | var version = ua.iOSVersion() 20 | console.log('main version': version[0]) 21 | console.log('sub version': version[1]) 22 | } 23 | ``` 24 | 25 | ## UMD 版本引入 26 | ### Rollup 27 | 28 | ```javascript 29 | import path from 'path'; 30 | 31 | export default { 32 | //... 33 | plugins: [{ 34 | resolveId(id) { 35 | if (id.startsWith('@searchfe/user-agent')) { 36 | return path.resolve(`${yourPath}/@searchfe/user-agent/index.umd.js`); 37 | } 38 | return null; 39 | } 40 | }], 41 | //... 42 | } 43 | ``` 44 | 45 | ### Webpack 46 | ```javascript 47 | module.exports = { 48 | //... 49 | resolve: { 50 | alias: { 51 | "@searchfe/user-agent": "@searchfe/user-agent/index.umd.js" 52 | } 53 | } 54 | }; 55 | ``` 56 | 57 | ## 贡献 58 | 59 | 本仓库使用 [semantic release](https://github.com/semantic-release/semantic-release) 自动发布 NPM,因此需要你的 commit 信息符合 [Commitizen](https://github.com/commitizen/cz-cli) 规范。比如: 60 | 61 | - bugfix 例子(自动发 bugfix 版本):`fix: 修复在 XX 情况下的 XX 问题`。 62 | - feature 例子(自动发 minor 版本):`feat: 支持 XX 浏览器的识别`。 63 | - 维护工作(不发版本):`chore: 支持 XX 浏览器的识别`。 64 | - 不兼容变更需要包含一段 `BREAKING CHANGES` 的说明,下次发版递增主版本号。 65 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-architect -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | interface factory { 2 | isAndroid(): boolean; 3 | isIOS(): boolean; 4 | isWinPhone(): boolean; 5 | 6 | iOSVersion(): [number, number] | []; 7 | appleWebkitVersion(): Array; 8 | baiduBoxVersion(): Array | number; 9 | baiduBoxVersionOnArk(): Array | number; 10 | baiduMainVersionOnArk(): Array | number; 11 | baiduLiteVersionOnArk(): Array | number; 12 | baiduBoxOrBdappVersion(): Array | null; 13 | honorVersion(): Array | null; 14 | bdappVersion(): Array| null; 15 | secrVersion(): Array; 16 | getChromeVersion(): Array; 17 | androidVersion(): Array; 18 | vivoBrowserVersion(): Array; 19 | isBaiduboxOrBdapp(): boolean; 20 | isTomas(): boolean; 21 | isKnews(): boolean; 22 | isBDBoxEngine(): boolean; 23 | isBdapp(): boolean; 24 | isBaiduBox(): boolean; 25 | isBaiduHonorBrowser(): boolean; 26 | isBaiduBoxLite(): boolean; 27 | isBaiduBoxJisu(): boolean; 28 | isBaiduBoxVision(): boolean; 29 | isQQ(): boolean; 30 | isQQApp(): boolean; 31 | isWeixinApp(): boolean; 32 | isQQBrowser(): boolean; 33 | isBaiduBrowser(): boolean; 34 | isSearchCraft(): boolean; 35 | isUC(): boolean; 36 | isChromeDesktop(): boolean; 37 | isChromeMobile(): boolean; 38 | isSafariBrowser(): boolean; 39 | isGoogleChrome(): boolean; 40 | isCriOS(): boolean; 41 | isSogouMobile(): boolean; 42 | isMiuiBrowser(): boolean; 43 | isHUAWEIBrowser(): boolean; 44 | isMZBrowser(): boolean; 45 | isOppoBrowser(): boolean; 46 | isWKWebview(): boolean; 47 | isUIWebview(): boolean; 48 | isXcxApp(): boolean; 49 | isVivoBrowser(): boolean; 50 | isArkBrowser(): boolean; 51 | isBaiduBoxOnArk(): boolean; 52 | isBaiduMainOnArk(): boolean; 53 | isBaiduLiteOnArk(): boolean; 54 | use(ua: string): factory 55 | } 56 | 57 | declare const mod: factory; 58 | 59 | export = mod 60 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | define(function () { 2 | function factory (ua) { 3 | var honorMap = [ 4 | [[8, 0, 1, 0], [13, 38, 5, 0]] 5 | ]; 6 | var mod = { 7 | // OS 8 | isAndroid: function () { 9 | return /android/i.test(ua); 10 | }, 11 | isIOS: function () { 12 | return /(iPhone|iPod|iPad)/.test(ua); 13 | }, 14 | isWinPhone: function () { 15 | return /Windows Phone ([\d.]+)/.test(ua); 16 | }, 17 | 18 | // Version 19 | iOSVersion: function () { 20 | var match = /OS (\d+)_(\d+)/.exec(ua); 21 | return match ? [Number(match[1]), Number(match[2])] : []; 22 | }, 23 | appleWebkitVersion: function () { 24 | var match = ua.match(/ applewebkit\/([0-9.]+)/i); 25 | return match ? match[1].split('.').map(parseFloat) : []; 26 | }, 27 | baiduBoxVersion: function () { 28 | // 非手百版本号返回 0 29 | if (!this.isBaiduBox() || mod.isArkWeb()) { 30 | return 0; 31 | } 32 | var version; 33 | var oldReg = /([\d+.]+)_(?:diordna|enohpi)_/i; 34 | var newReg = /baiduboxapp\/([\d+.]+)/; 35 | var honorReg = /bdhonorbrowser\/([\d+.]+)/; 36 | if (oldReg.test(ua)) { 37 | version = ua.match(oldReg)[1].split('.').reverse(); 38 | } else if (newReg.test(ua)) { 39 | version = ua.match(newReg)[1].split('.'); 40 | } else if (honorReg.test(ua)) { 41 | version = ua.match(honorReg)[1].split('.'); 42 | for (var i = 0; i < honorMap.length; i++) { 43 | var map = honorMap[i]; 44 | if ( 45 | version[0] * 10000000 + 46 | version[1] * 100000 + 47 | version[1] * 1000 + 48 | version[1] >= 49 | map[0][0] * 10000000 + 50 | map[0][1] * 100000 + 51 | map[0][2] * 1000 + 52 | map[0][3] 53 | ) { 54 | version = map[1]; 55 | } 56 | } 57 | } 58 | return version ? version.map(parseFloat) : []; 59 | }, 60 | honorVersion: function () { 61 | var honorReg = /bdhonorbrowser\/([\d+.]+)/; 62 | var version; 63 | if (honorReg.test(ua)) { 64 | version = ua.match(honorReg)[1].split('.'); 65 | } 66 | return version ? version.map(parseFloat) : []; 67 | }, 68 | // 百度主线或矩阵产品版本号 69 | baiduBoxOrBdappVersion: function () { 70 | if (this.isBaiduBox()) { 71 | return this.baiduBoxVersion() && this.baiduBoxVersion().length > 0 ? this.baiduBoxVersion() : null; 72 | } 73 | if (this.isBdapp()) return this.bdappVersion(); 74 | return null; 75 | }, 76 | // 矩阵产品版本号 77 | bdappVersion: function () { 78 | if (!this.isBdapp()) return null; 79 | var reg = /bdapp\/[\d+.]+\s\(\w+;\s\w+\)\s\w+\/([\d+.]+)/i; 80 | var result = ua.match(reg); 81 | var version = result ? result[1].split('.') : null; 82 | return version ? version.map(parseFloat) : null; 83 | }, 84 | // 简单搜索版本号 85 | secrVersion: function () { 86 | // 非简单浏览器版本返回 0 87 | if (!this.isSearchCraft()) { 88 | return 0; 89 | } 90 | var match = ua.match(/ SearchCraft\/([0-9]+_)?([0-9.]+)/i); 91 | var version = /(iPhone|iPod|iPad)/.test(ua) ? match[2].split('.') : match[2].split('.'); 92 | return version ? version.map(parseFloat) : []; 93 | }, 94 | // chrome 内核版本 95 | getChromeVersion: function () { 96 | // 非 chrome 内核,chrome 内核版本返回 0 97 | if (!this.isChromeDesktop() && !this.isChromeMobile()) { 98 | return 0; 99 | } 100 | var match = ua.match(/ Chrome\/([0-9]+_)?([0-9.]+)/i); 101 | return match && match[2] ? match[2].split('.').map(parseFloat) : []; 102 | }, 103 | androidVersion: function () { 104 | var match = ua.match(/Android ([0-9.]+);/); 105 | if (!match) { 106 | return []; 107 | } 108 | var version = match[1].split('.').map(parseFloat); 109 | return version; 110 | }, 111 | // 获取vivo浏览器版本 112 | vivoBrowserVersion: function () { 113 | var match = ua.match(/VivoBrowser\/([0-9.]+)/); 114 | if (!match || !match[1]) { 115 | return []; 116 | } 117 | return match[1].split('.').map(parseFloat); 118 | }, 119 | // 是否为百度端内产品 120 | isBaiduboxOrBdapp: function () { 121 | return this.isBaiduBox() || this.isBdapp(); 122 | }, 123 | // 按照新UA规范,是否为百度矩阵产品 124 | isBdapp: function () { 125 | return /bdapp/.test(ua); 126 | }, 127 | // 是否为百度大字版 128 | isTomas: function () { 129 | return /tomas/.test(ua); 130 | }, 131 | // 是否为趣新热APP,其关联厂商小米白牌,属于半个手百矩阵产品 132 | isKnews: function () { 133 | return /knews/.test(ua); 134 | }, 135 | // 是否为百度关怀版 136 | isBaiduboxsenior: function () { 137 | return /baiduboxsenior/.test(ua); 138 | }, 139 | // 是否支持搜索 SDK 140 | isBDBoxEngine: function () { 141 | return /BDBoxEngine/.test(ua); 142 | }, 143 | // 百度app主版和极速版 144 | isBaiduBox: function () { 145 | return !mod.isArkWeb() && (/baiduboxapp/.test(ua) || /bdhonorbrowser/.test(ua)); 146 | }, 147 | isBaiduHonorBrowser: function () { 148 | return /bdhonorbrowser/.test(ua); 149 | }, 150 | // 百度极速版 151 | isBaiduBoxLite: function () { 152 | return !mod.isArkWeb() && /(lite|info) baiduboxapp/.test(ua); 153 | }, 154 | // 百度极速版(遗留接口) 155 | // lite 在 iOS 的标识为 info baiduboxapp 156 | isBaiduBoxJisu: function () { 157 | return mod.isBaiduBoxLite(); 158 | }, 159 | // 百度app视频版 160 | isBaiduBoxVision: function () { 161 | return /baiduboxvision/.test(ua); 162 | }, 163 | // isQQ 会判断是否 QQ 浏览器 164 | // 但 Android 平台的手机内置 QQ 的 UA 没有 QQBrowser 字段 165 | // 所以请使用 isQQApp || isWeixinApp || isQQBrowser 代替此接口 166 | isQQ: function () { 167 | return /QQBrowser/.test(ua); 168 | }, 169 | isQQApp: function () { 170 | return /QQ\/[0-9]+/.test(ua); 171 | }, 172 | isWeixinApp: function () { 173 | return /MicroMessenger/.test(ua); 174 | }, 175 | // isQQBrowser 会判断是否 QQ 浏览器 但不包括 QQ 微信内置 176 | isQQBrowser: function () { 177 | return /QQBrowser/.test(ua) && !(/QQ\//.test(ua) || /MicroMessenger/.test(ua)); 178 | }, 179 | isBaiduBrowser: function () { 180 | return /baidubrowser/.test(ua); 181 | }, 182 | isSearchCraft: function () { 183 | return /SearchCraft/i.test(ua); 184 | }, 185 | isUC: function () { 186 | return /UCBrowser/.test(ua); 187 | }, 188 | isChromeDesktop: function () { 189 | return /Chrome\//.test(ua); 190 | }, 191 | isChromeMobile: function () { 192 | return /Chrome\/(\S*) Mobile/.test(ua); 193 | }, 194 | // ios 上 chrome 不是 chrome 内核 195 | isCriOS: function () { 196 | return /CriOS/.test(ua); 197 | }, 198 | isSogouMobile: function () { 199 | return /SogouMobileBrowser/.test(ua); 200 | }, 201 | isMiuiBrowser: function () { 202 | return /MiuiBrowser\/(\S*)/.test(ua); 203 | }, 204 | // HUAWEI其他浏览器的UA中也有HUAWEI字段,要剔除掉 205 | isHUAWEIBrowser: function () { 206 | return /HUAWEI/i.test(ua) && !(/baiduboxapp/.test(ua) || /QQBrowser/.test(ua) || /UCBrowser/.test(ua) || /MicroMessenger/.test(ua) || /SearchCraft/.test(ua)); 207 | }, 208 | isMZBrowser: function () { 209 | return /MZBrowser/i.test(ua); 210 | }, 211 | // 是否 oppo 浏览器 212 | isOppoBrowser: function () { 213 | return /HeyTapBrowser/.test(ua); 214 | }, 215 | // 判断是否为iphone手机的safari浏览器 216 | isSafariBrowser: function () { 217 | var uaLower = ua.toLowerCase(); 218 | return (uaLower.indexOf('applewebkit') > -1 && uaLower.indexOf('mobile') > -1 && uaLower.indexOf('safari') > -1 && 219 | uaLower.indexOf('linux') === -1 && uaLower.indexOf('android') === -1 && uaLower.indexOf('chrome') === -1 && 220 | uaLower.indexOf('ios') === -1 && uaLower.indexOf('browser') === -1); 221 | }, 222 | /** 223 | * 仅只是chrome浏览器(排除安卓下谷歌内核浏览器) 224 | * @return {boolean} chrome 225 | */ 226 | isGoogleChrome: function () { 227 | var andrChrome = /^Mozilla\/(\d*?(\.\d*?)*?) \(Linux; Android (\d*?(\.\d*?)*?); .*?\) AppleWebKit\/(\d*?(\.\d*?)*?) \(KHTML, like Gecko\) Chrome\/(\d*?(\.\d*?)*?) Mobile Safari\/(\d*?(\.\d*?)*?)$/.test(ua); 228 | var iosChrome = /^Mozilla\/(\d*?(\.\d*?)*?) \(iPhone; CPU iPhone OS (\d*?(_\d*?)*?) like Mac OS X\) AppleWebKit\/(\d*?(\.\d*?)*?) \(KHTML, like Gecko\) CriOS\/(\d*?(\.\d*?)*?) Mobile\/(.*?) Safari\/(\d*?(\.\d*?)*?)$/.test(ua); 229 | return andrChrome || iosChrome; 230 | }, 231 | // kernel 232 | isWKWebview: function () { 233 | var webkitVersion = mod.appleWebkitVersion(); 234 | return mod.isIOS() && webkitVersion[0] && webkitVersion[0] > 600; 235 | }, 236 | isUIWebview: function () { 237 | var webkitVersion = mod.appleWebkitVersion(); 238 | return mod.isIOS() && webkitVersion[0] && webkitVersion[0] <= 600; 239 | }, 240 | isXcxApp: function () { 241 | // 屏蔽的关键字用base64解码代替 242 | var xcx = window.atob('c3dhbg=='); 243 | var reg = new RegExp('(' + xcx + '-baiduboxapp|baiduboxapp-' + xcx + ')'); 244 | return reg.test(ua); 245 | }, 246 | isVivoBrowser: function () { 247 | return /VivoBrowser/.test(ua); 248 | }, 249 | 250 | // 鸿蒙系统 251 | isArkWeb: function () { 252 | return ua.indexOf('ArkWeb') > -1; 253 | }, 254 | // 鸿蒙浏览器 255 | isArkBrowser: function () { 256 | return mod.isArkWeb() && !mod.isBaiduBoxOnArk(); 257 | }, 258 | // 鸿蒙百度app主版和极速版 259 | isBaiduBoxOnArk: function () { 260 | return mod.isBaiduMainOnArk() || mod.isBaiduLiteOnArk(); 261 | }, 262 | // 鸿蒙百度app主版 263 | isBaiduMainOnArk: function () { 264 | // 兼容后端ua,接入层将baiduboxapp替换为baiduarkwebapp 265 | return /ArkWeb.* (baiduboxapp|baiduarkwebapp)/i.test(ua); 266 | }, 267 | // 鸿蒙百度极速版 268 | isBaiduLiteOnArk: function () { 269 | // 兼容后端ua,接入层将baiduboxlite替换为baiduarkweblite 270 | return /ArkWeb.* (baiduboxlite|baiduarkweblite)/i.test(ua); 271 | }, 272 | // 鸿蒙百度app主版和极速版的版本号 273 | baiduBoxVersionOnArk: function () { 274 | return mod.baiduMainVersionOnArk() || mod.baiduLiteVersionOnArk(); 275 | }, 276 | // 鸿蒙百度app的版本号 277 | baiduMainVersionOnArk: function () { 278 | if (mod.isArkWeb()) { 279 | var newReg = /baiduboxapp\/([\d.]+)/; 280 | var result = ua.replace(/baiduarkwebapp/g, 'baiduboxapp').match(newReg); 281 | if (result && result[1]) { 282 | return result[1].split('.').map(parseFloat); 283 | } 284 | } 285 | return 0; 286 | }, 287 | // 鸿蒙百度极速版的版本号 288 | baiduLiteVersionOnArk: function () { 289 | if (mod.isArkWeb()) { 290 | var newReg = /baiduboxlite\/([\d.]+)/; 291 | var result = ua.replace(/baiduarkweblite/g, 'baiduboxlite').match(newReg); 292 | if (result && result[1]) { 293 | return result[1].split('.').map(parseFloat); 294 | } 295 | } 296 | return 0; 297 | }, 298 | 299 | // functionality 300 | use: factory 301 | }; 302 | 303 | // 需要屏蔽swan关键字用base64解码代替 304 | // 兼容非浏览器环境 305 | typeof window === 'object' && (mod[window.atob('aXNTd2FuQXBw')] = function () { 306 | var xcx = window.atob('c3dhbg=='); 307 | var reg = new RegExp('(' + xcx + '-baiduboxapp|baiduboxapp-' + xcx + ')'); 308 | return reg.test(ua); 309 | }); 310 | 311 | return mod; 312 | } 313 | 314 | return factory(navigator.userAgent); 315 | }); 316 | -------------------------------------------------------------------------------- /index.umd.js: -------------------------------------------------------------------------------- 1 | /* globals self */ 2 | (function (root, factory) { 3 | if (typeof define === 'function' && define.amd) { 4 | // AMD. Register as an anonymous module. 5 | define([], factory); 6 | } else if (typeof module === 'object' && module.exports) { 7 | // Node. Does not work with strict CommonJS, but 8 | // only CommonJS-like enviroments that support module.exports, 9 | // like Node. 10 | module.exports = factory(); 11 | } else { 12 | // Browser globals (root is window) 13 | root.myModule = factory(); 14 | } 15 | }(typeof self !== 'undefined' ? self : this, function () { 16 | function factory (ua) { 17 | var honorMap = [ 18 | [[8, 0, 1, 0], [13, 38, 5, 0]] 19 | ]; 20 | var mod = { 21 | // OS 22 | isAndroid: function () { 23 | return /android/i.test(ua); 24 | }, 25 | isIOS: function () { 26 | return /(iPhone|iPod|iPad)/.test(ua); 27 | }, 28 | isWinPhone: function () { 29 | return /Windows Phone ([\d.]+)/.test(ua); 30 | }, 31 | 32 | // Version 33 | iOSVersion: function () { 34 | var match = /OS (\d+)_(\d+)/.exec(ua); 35 | return match ? [Number(match[1]), Number(match[2])] : []; 36 | }, 37 | appleWebkitVersion: function () { 38 | var match = ua.match(/ applewebkit\/([0-9.]+)/i); 39 | return match ? match[1].split('.').map(parseFloat) : []; 40 | }, 41 | baiduBoxVersion: function () { 42 | // 非手百版本号返回 0 43 | if (!this.isBaiduBox() || mod.isArkWeb()) { 44 | return 0; 45 | } 46 | var version; 47 | var oldReg = /([\d+.]+)_(?:diordna|enohpi)_/i; 48 | var newReg = /baiduboxapp\/([\d+.]+)/; 49 | var honorReg = /bdhonorbrowser\/([\d+.]+)/; 50 | if (oldReg.test(ua)) { 51 | version = ua.match(oldReg)[1].split('.').reverse(); 52 | } else if (newReg.test(ua)) { 53 | version = ua.match(newReg)[1].split('.'); 54 | } else if (honorReg.test(ua)) { 55 | version = ua.match(honorReg)[1].split('.'); 56 | for (var i = 0; i < honorMap.length; i++) { 57 | var map = honorMap[i]; 58 | if ( 59 | version[0] * 10000000 + 60 | version[1] * 100000 + 61 | version[1] * 1000 + 62 | version[1] >= 63 | map[0][0] * 10000000 + 64 | map[0][1] * 100000 + 65 | map[0][2] * 1000 + 66 | map[0][3] 67 | ) { 68 | version = map[1]; 69 | } 70 | } 71 | } 72 | return version ? version.map(parseFloat) : []; 73 | }, 74 | honorVersion: function () { 75 | var honorReg = /bdhonorbrowser\/([\d+.]+)/; 76 | var version; 77 | if (honorReg.test(ua)) { 78 | version = ua.match(honorReg)[1].split('.'); 79 | } 80 | return version ? version.map(parseFloat) : []; 81 | }, 82 | // 百度主线或矩阵产品版本号 83 | baiduBoxOrBdappVersion: function () { 84 | if (this.isBaiduBox()) { 85 | return this.baiduBoxVersion() && this.baiduBoxVersion().length > 0 ? this.baiduBoxVersion() : null; 86 | } 87 | if (this.isBdapp()) return this.bdappVersion(); 88 | return null; 89 | }, 90 | // 矩阵产品版本号 91 | bdappVersion: function () { 92 | if (!this.isBdapp()) return null; 93 | var reg = /bdapp\/[\d+.]+\s\(\w+;\s\w+\)\s\w+\/([\d+.]+)/i; 94 | var result = ua.match(reg); 95 | var version = result ? result[1].split('.') : null; 96 | return version ? version.map(parseFloat) : null; 97 | }, 98 | // 简单搜索版本号 99 | secrVersion: function () { 100 | // 非简单浏览器版本返回 0 101 | if (!this.isSearchCraft()) { 102 | return 0; 103 | } 104 | var match = ua.match(/ SearchCraft\/([0-9]+_)?([0-9.]+)/i); 105 | var version = /(iPhone|iPod|iPad)/.test(ua) ? match[2].split('.') : match[2].split('.'); 106 | return version ? version.map(parseFloat) : []; 107 | }, 108 | // chrome 内核版本 109 | getChromeVersion: function () { 110 | // 非 chrome 内核,chrome 内核版本返回 0 111 | if (!this.isChromeDesktop() && !this.isChromeMobile()) { 112 | return 0; 113 | } 114 | var match = ua.match(/ Chrome\/([0-9]+_)?([0-9.]+)/i); 115 | return match && match[2] ? match[2].split('.').map(parseFloat) : []; 116 | }, 117 | androidVersion: function () { 118 | var match = ua.match(/Android ([0-9.]+);/); 119 | if (!match) { 120 | return []; 121 | } 122 | var version = match[1].split('.').map(parseFloat); 123 | return version; 124 | }, 125 | // 获取vivo浏览器版本 126 | vivoBrowserVersion: function () { 127 | var match = ua.match(/VivoBrowser\/([0-9.]+)/); 128 | if (!match || !match[1]) { 129 | return []; 130 | } 131 | return match[1].split('.').map(parseFloat); 132 | }, 133 | // 是否为百度端内产品 134 | isBaiduboxOrBdapp: function () { 135 | return this.isBaiduBox() || this.isBdapp(); 136 | }, 137 | // 按照新UA规范,是否为百度矩阵产品 138 | isBdapp: function () { 139 | return /bdapp/.test(ua); 140 | }, 141 | // 是否为百度大字版 142 | isTomas: function () { 143 | return /tomas/.test(ua); 144 | }, 145 | // 是否为趣新热APP,其关联厂商小米白牌,属于半个手百矩阵产品 146 | isKnews: function () { 147 | return /knews/.test(ua); 148 | }, 149 | // 是否为百度关怀版 150 | isBaiduboxsenior: function () { 151 | return /baiduboxsenior/.test(ua); 152 | }, 153 | // 是否支持搜索 SDK 154 | isBDBoxEngine: function () { 155 | return /BDBoxEngine/.test(ua); 156 | }, 157 | // 百度app主版和极速版 158 | isBaiduBox: function () { 159 | return !mod.isArkWeb() && (/baiduboxapp/.test(ua) || /bdhonorbrowser/.test(ua)); 160 | }, 161 | isBaiduHonorBrowser: function () { 162 | return /bdhonorbrowser/.test(ua); 163 | }, 164 | // 百度极速版 165 | isBaiduBoxLite: function () { 166 | return !mod.isArkWeb() && /(lite|info) baiduboxapp/.test(ua); 167 | }, 168 | // 百度极速版(遗留接口) 169 | // lite 在 iOS 的标识为 info baiduboxapp 170 | isBaiduBoxJisu: function () { 171 | return mod.isBaiduBoxLite(); 172 | }, 173 | // 百度app视频版 174 | isBaiduBoxVision: function () { 175 | return /baiduboxvision/.test(ua); 176 | }, 177 | // isQQ 会判断是否 QQ 浏览器 178 | // 但 Android 平台的手机内置 QQ 的 UA 没有 QQBrowser 字段 179 | // 所以请使用 isQQApp || isWeixinApp || isQQBrowser 代替此接口 180 | isQQ: function () { 181 | return /QQBrowser/.test(ua); 182 | }, 183 | isQQApp: function () { 184 | return /QQ\/[0-9]+/.test(ua); 185 | }, 186 | isWeixinApp: function () { 187 | return /MicroMessenger/.test(ua); 188 | }, 189 | // isQQBrowser 会判断是否 QQ 浏览器 但不包括 QQ 微信内置 190 | isQQBrowser: function () { 191 | return /QQBrowser/.test(ua) && !(/QQ\//.test(ua) || /MicroMessenger/.test(ua)); 192 | }, 193 | isBaiduBrowser: function () { 194 | return /baidubrowser/.test(ua); 195 | }, 196 | isSearchCraft: function () { 197 | return /SearchCraft/i.test(ua); 198 | }, 199 | isUC: function () { 200 | return /UCBrowser/.test(ua); 201 | }, 202 | isChromeDesktop: function () { 203 | return /Chrome\//.test(ua); 204 | }, 205 | isChromeMobile: function () { 206 | return /Chrome\/(\S*) Mobile/.test(ua); 207 | }, 208 | // ios 上 chrome 不是 chrome 内核 209 | isCriOS: function () { 210 | return /CriOS/.test(ua); 211 | }, 212 | isSogouMobile: function () { 213 | return /SogouMobileBrowser/.test(ua); 214 | }, 215 | isMiuiBrowser: function () { 216 | return /MiuiBrowser\/(\S*)/.test(ua); 217 | }, 218 | // HUAWEI其他浏览器的UA中也有HUAWEI字段,要剔除掉 219 | isHUAWEIBrowser: function () { 220 | return /HUAWEI/i.test(ua) && !(/baiduboxapp/.test(ua) || /QQBrowser/.test(ua) || /UCBrowser/.test(ua) || /MicroMessenger/.test(ua) || /SearchCraft/.test(ua)); 221 | }, 222 | isMZBrowser: function () { 223 | return /MZBrowser/i.test(ua); 224 | }, 225 | // 是否 oppo 浏览器 226 | isOppoBrowser: function () { 227 | return /HeyTapBrowser/.test(ua); 228 | }, 229 | // 判断是否为iphone手机的safari浏览器 230 | isSafariBrowser: function () { 231 | var uaLower = ua.toLowerCase(); 232 | return (uaLower.indexOf('applewebkit') > -1 && uaLower.indexOf('mobile') > -1 && uaLower.indexOf('safari') > -1 && 233 | uaLower.indexOf('linux') === -1 && uaLower.indexOf('android') === -1 && uaLower.indexOf('chrome') === -1 && 234 | uaLower.indexOf('ios') === -1 && uaLower.indexOf('browser') === -1); 235 | }, 236 | /** 237 | * 仅只是chrome浏览器(排除安卓下谷歌内核浏览器) 238 | * @return {boolean} chrome 239 | */ 240 | isGoogleChrome: function () { 241 | var andrChrome = /^Mozilla\/(\d*?(\.\d*?)*?) \(Linux; Android (\d*?(\.\d*?)*?); .*?\) AppleWebKit\/(\d*?(\.\d*?)*?) \(KHTML, like Gecko\) Chrome\/(\d*?(\.\d*?)*?) Mobile Safari\/(\d*?(\.\d*?)*?)$/.test(ua); 242 | var iosChrome = /^Mozilla\/(\d*?(\.\d*?)*?) \(iPhone; CPU iPhone OS (\d*?(_\d*?)*?) like Mac OS X\) AppleWebKit\/(\d*?(\.\d*?)*?) \(KHTML, like Gecko\) CriOS\/(\d*?(\.\d*?)*?) Mobile\/(.*?) Safari\/(\d*?(\.\d*?)*?)$/.test(ua); 243 | return andrChrome || iosChrome; 244 | }, 245 | // kernel 246 | isWKWebview: function () { 247 | var webkitVersion = mod.appleWebkitVersion(); 248 | return mod.isIOS() && webkitVersion[0] && webkitVersion[0] > 600; 249 | }, 250 | isUIWebview: function () { 251 | var webkitVersion = mod.appleWebkitVersion(); 252 | return mod.isIOS() && webkitVersion[0] && webkitVersion[0] <= 600; 253 | }, 254 | isXcxApp: function () { 255 | // 屏蔽的关键字用base64解码代替 256 | var xcx = window.atob('c3dhbg=='); 257 | var reg = new RegExp('(' + xcx + '-baiduboxapp|baiduboxapp-' + xcx + ')'); 258 | return reg.test(ua); 259 | }, 260 | isVivoBrowser: function () { 261 | return /VivoBrowser/.test(ua); 262 | }, 263 | 264 | // 鸿蒙系统 265 | isArkWeb: function () { 266 | return ua.indexOf('ArkWeb') > -1; 267 | }, 268 | // 鸿蒙百度app主版和极速版 269 | isBaiduBoxOnArk: function () { 270 | return mod.isBaiduMainOnArk() || mod.isBaiduLiteOnArk(); 271 | }, 272 | // 鸿蒙百度app主版 273 | isBaiduMainOnArk: function () { 274 | // 兼容后端ua,接入层将baiduboxapp替换为baiduarkwebapp 275 | return /ArkWeb.* (baiduboxapp|baiduarkwebapp)/i.test(ua); 276 | }, 277 | // 鸿蒙百度极速版 278 | isBaiduLiteOnArk: function () { 279 | // 兼容后端ua,接入层将baiduboxlite替换为baiduarkweblite 280 | return /ArkWeb.* (baiduboxlite|baiduarkweblite)/i.test(ua); 281 | }, 282 | // 鸿蒙百度app主版和极速版的版本号 283 | baiduBoxVersionOnArk: function () { 284 | return mod.baiduMainVersionOnArk() || mod.baiduLiteVersionOnArk(); 285 | }, 286 | // 鸿蒙百度app的版本号 287 | baiduMainVersionOnArk: function () { 288 | if (mod.isArkWeb()) { 289 | var newReg = /baiduboxapp\/([\d.]+)/; 290 | var result = ua.replace(/baiduarkwebapp/g, 'baiduboxapp').match(newReg); 291 | if (result && result[1]) { 292 | return result[1].split('.').map(parseFloat); 293 | } 294 | } 295 | return 0; 296 | }, 297 | // 鸿蒙百度极速版的版本号 298 | baiduLiteVersionOnArk: function () { 299 | if (mod.isArkWeb()) { 300 | var newReg = /baiduboxlite\/([\d.]+)/; 301 | var result = ua.replace(/baiduarkweblite/g, 'baiduboxlite').match(newReg); 302 | if (result && result[1]) { 303 | return result[1].split('.').map(parseFloat); 304 | } 305 | } 306 | return 0; 307 | }, 308 | 309 | // functionality 310 | use: factory 311 | }; 312 | 313 | // 需要屏蔽swan关键字用base64解码代替 314 | // 兼容非浏览器环境 315 | typeof window === 'object' && (mod[window.atob('aXNTd2FuQXBw')] = function () { 316 | var xcx = window.atob('c3dhbg=='); 317 | var reg = new RegExp('(' + xcx + '-baiduboxapp|baiduboxapp-' + xcx + ')'); 318 | return reg.test(ua); 319 | }); 320 | 321 | return mod; 322 | } 323 | 324 | return factory(navigator.userAgent); 325 | })); 326 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration 2 | // Generated on Wed Apr 04 2018 00:03:37 GMT+0800 (CST) 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | 7 | // base path that will be used to resolve all patterns (eg. files, exclude) 8 | basePath: './', 9 | 10 | // frameworks to use 11 | // available frameworks: https://npmjs.org/browse/keyword/karma-adapter 12 | frameworks: ['mocha', 'requirejs', 'chai-as-promised', 'chai-sinon'], 13 | 14 | // list of files / patterns to load in the browser 15 | files: [ 16 | 'test-main.js', 17 | {pattern: 'index.js', included: false}, 18 | {pattern: 'test/**/*.js', included: false} 19 | ], 20 | 21 | // list of files to exclude 22 | exclude: [ 23 | '**/*.swp' 24 | ], 25 | 26 | // preprocess matching files before serving them to the browser 27 | // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor 28 | preprocessors: { 29 | // source files, that you wanna generate coverage for 30 | // do not include tests or libraries 31 | // (these files will be instrumented by Istanbul) 32 | // 'src/**/*.js': ['coverage'] 33 | './index.js': ['coverage'] 34 | }, 35 | 36 | // test results reporter to use 37 | // possible values: 'dots', 'progress' 38 | // available reporters: https://npmjs.org/browse/keyword/karma-reporter 39 | reporters: ['mocha'], 40 | coverageReporter: { 41 | reporters: [ 42 | { 43 | type: 'text-summary' 44 | }, { 45 | type: 'lcov', 46 | dir: 'coverage/' 47 | } 48 | ] 49 | }, 50 | 51 | // web server port 52 | port: 9876, 53 | 54 | // enable / disable colors in the output (reporters and logs) 55 | colors: true, 56 | 57 | // level of logging 58 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG 59 | logLevel: config.LOG_INFO, 60 | 61 | // enable / disable watching file and executing tests whenever any file changes 62 | autoWatch: true, 63 | 64 | // start these browsers 65 | // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher 66 | browsers: ['ChromeHeadless'], 67 | 68 | // Continuous Integration mode 69 | // if true, Karma captures browsers, runs the tests and exits 70 | singleRun: true, 71 | 72 | // Concurrency level 73 | // how many browser should be started simultaneous 74 | concurrency: Infinity 75 | }); 76 | }; 77 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@searchfe/user-agent", 3 | "version": "1.9.15", 4 | "description": "AMD package for user-agent detection.", 5 | "main": "./index.js", 6 | "scripts": { 7 | "lint": "eslint src test *.js", 8 | "coveralls": "karma start --reporters mocha,coverage,coveralls", 9 | "test": "karma start" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "git+https://github.com/searchfe/user-agent.git" 14 | }, 15 | "author": "pearl", 16 | "license": "MIT", 17 | "bugs": { 18 | "url": "https://github.com/searchfe/user-agent/issues" 19 | }, 20 | "files": [ 21 | "index.js", 22 | "index.umd.js", 23 | "index.d.ts" 24 | ], 25 | "homepage": "https://github.com/searchfe/user-agent#readme", 26 | "devDependencies": { 27 | "@semantic-release/changelog": "^5.0.1", 28 | "@semantic-release/commit-analyzer": "^8.0.1", 29 | "@semantic-release/git": "^9.0.0", 30 | "@semantic-release/npm": "^7.0.6", 31 | "@semantic-release/release-notes-generator": "^9.0.1", 32 | "chai": "^3.5.0", 33 | "chai-as-promised": "^5.3.0", 34 | "eslint": "^4.18.2", 35 | "eslint-config-standard": "^10.2.1", 36 | "eslint-plugin-import": "^2.7.0", 37 | "eslint-plugin-mocha": "^4.9.0", 38 | "eslint-plugin-node": "^6.0.1", 39 | "eslint-plugin-promise": "^3.5.0", 40 | "eslint-plugin-standard": "^3.0.1", 41 | "karma": "^2.0.0", 42 | "karma-chai": "^0.1.0", 43 | "karma-chai-as-promised": "^0.1.2", 44 | "karma-chai-sinon": "^0.1.5", 45 | "karma-chrome-launcher": "^2.2.0", 46 | "karma-coverage": "^1.1.1", 47 | "karma-coveralls": "^1.1.2", 48 | "karma-firefox-launcher": "^1.1.0", 49 | "karma-html-reporter": "^0.2.7", 50 | "karma-mocha": "^1.1.1", 51 | "karma-mocha-reporter": "^2.0.4", 52 | "karma-opera-launcher": "^1.0.0", 53 | "karma-requirejs": "^1.1.0", 54 | "karma-safari-launcher": "^1.0.0", 55 | "mocha": "^3.2.0", 56 | "requirejs": "^2.3.5", 57 | "sinon": "^2.1.0", 58 | "sinon-chai": "^2.8.0" 59 | }, 60 | "release": { 61 | "branch": "master", 62 | "plugins": [ 63 | "@semantic-release/commit-analyzer", 64 | "@semantic-release/release-notes-generator", 65 | "@semantic-release/changelog", 66 | "@semantic-release/npm", 67 | [ 68 | "@semantic-release/git", 69 | { 70 | "assets": [ 71 | "pacakge.json", 72 | "CHANGELOG.md" 73 | ], 74 | "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}" 75 | } 76 | ], 77 | "@semantic-release/github" 78 | ] 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /test-main.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file testMain test entry for karma 3 | * @author harttle 4 | */ 5 | var allTestFiles = []; 6 | var TEST_REGEXP = /test\/.*\.js$/i; 7 | 8 | // Get a list of all the test files to include 9 | Object.keys(window.__karma__.files).forEach(function (file) { 10 | if (TEST_REGEXP.test(file)) { 11 | // Normalize paths to RequireJS module names. 12 | // If you require sub-dependencies of test files to be loaded as-is (requiring file extension) 13 | // then do not normalize the paths 14 | var normalizedTestModule = file.replace(/^\/base\/|\.js$/g, ''); 15 | allTestFiles.push(normalizedTestModule); 16 | } 17 | }); 18 | 19 | require.config({ 20 | // Karma serves files under /base, which is the basePath from your config file 21 | baseUrl: '/base', 22 | 23 | // dynamically load all test files 24 | deps: allTestFiles, 25 | 26 | // external AMD modules 27 | paths: { 28 | '@searchfe/assert': 'amd_modules/@searchfe/assert' 29 | }, 30 | 31 | // we have to kickoff jasmine, as it is asynchronous 32 | callback: window.__karma__.start 33 | }); 34 | -------------------------------------------------------------------------------- /test/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "no-unused-expressions": "off", 4 | "no-new": "off", 5 | "standard/no-callback-literal": "off" 6 | }, 7 | "globals": { 8 | "expect": true, 9 | "sinon": true 10 | }, 11 | "env": { 12 | "mocha": true 13 | }, 14 | "plugins": [ 15 | "mocha" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | define(['../index'], function (UA) { 2 | var qqAndroid = 'Mozilla/5.0 (Linux; U; Android 4.4.4; zh-cn; HUAWEI C8818 Build/HuaweiC8818) AppleWebKit/537.36 (KHTML, like Gecko)Version/4.0 MQQBrowser/5.8 Mobile Safari/537.36'; 3 | var qqIOS = 'Mozilla/5.0 (iPhone 84; CPU iPhone OS 10_3_3 like Mac OS X) AppleWebKit/603.3.8 (KHTML, like Gecko) Version/10.0 MQQBrowser/7.8.0 Mobile/14G60 Safari/8536.25 MttCustomUA/2 QBWebViewType/1 WKType/1'; 4 | var ucAndroid = 'Mozilla/5.0 (Linux; U; Android 7.0; zh-CN; ZUK Z2121 Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/40.0.2214.89 UCBrowser/11.6.8.952 Mobile Safari/537.36'; 5 | var safariIOS = 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.0 Mobile/14E304 Safari/602.1'; 6 | var ucIOS = 'Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X; zh-CN) AppleWebKit/537.51.1 (KHTML, like Gecko) Mobile/16A5288q UCBrowser/12.0.3.1077 Mobile AliApp(TUnionSDK/0.1.20.3)'; 7 | var baiduIOS = 'Mozilla/5.0 (iPhone; CPU iPhone OS 9_3_2 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Mobile/13F69 baiduboxapp/0_8.0.0.9_enohpi_6311_046/2.3.9_2C2%255enohPi/1000306f/C4FF069AC425606E29ACA3E490065B7C5DFD70645OCEANNARPH/1'; 8 | var baiduAndroid = 'Mozilla/5.0 (Linux; U; Android 4.1.1; zh-cn; SCH-N719 Build/JRO03C) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30 baiduboxapp/6.3 (Baidu; P1 4.1.1)'; 9 | var qqApp = 'Mozilla/5.0 (Linux; Android 7.1.1; OS105 Build/NGI77B; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/62.0.3202.84 Mobile Safari/537.36 V1_AND_SQ_7.6.8_872_YYB_D QQ/7.6.8.3615 NetType/WIFI WebP/0.4.1 Pixel/1080'; 10 | var weixinApp = 'Mozilla/5.0 (Linux; Android 7.1.1; OS105 Build/NGI77B; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.132 MQQBrowser/6.2 TBS/044109 Mobile Safari/537.36 MicroMessenger/6.6.7.1320(0x26060739) NetType/WIFI Language/en'; 11 | var searchCraft = 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E216 SearchCraft/2.6.0 (Baidu; P2 11.3)'; 12 | var wrongChrome = 'Mozilla/5.0 (Linux; U; Android 7.0; zh-CN; ZUK Z2121 Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/ UCBrowser/11.6.8.952 Mobile Safari/537.36'; 13 | var chromeMobile = 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_4_1 like Mac OS X) AppleWebKit/604.1.34 (KHTML, like Gecko) CriOS/68.0.3440.83 Mobile/15G77 Safari/604.1'; 14 | var pixel2 = 'Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3555.0 Mobile Safari/537.36'; 15 | var pixel2XL = 'Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3555.0 Mobile Safari/537.36'; 16 | var XiaoMiBrowser = 'Mozilla/5.0 (Linux; U; Android 6.0; zh-cn; Redmi Note 4 Build/MRA58K) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/71.0.3578.141 Mobile Safari/537.36 XiaoMi/MiuiBrowser/12.8.32'; 17 | var galaxyS5 = 'Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3555.0 Mobile Safari/537.36'; 18 | var HUAWEIMeta9 = 'Mozilla/5.0 (Linux; Android 8.0.0; MHA-AL00 Biild/HUAWEIMHA-AL00) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36'; 19 | var HUAWEIChromeBrowser = 'Mozilla/5.0 (Linux; Android 10; VOG-AL00) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.117 Mobile Safari/537.36'; 20 | var MEIZUPRO6 = 'Mozilla/5.0 (Linux; Android 7.1.1; zh-CN; MZ-PRO 6 Biild/MRA58K) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.108 MZBrowser/7.7.2 UWS/2.15.0.2 Mobile Safari/537.36'; 21 | var HUAWEIMeta10baidu = 'Mozilla/5.0 (Linux; Android 8.1.0; ALP-AL00 Build/HUAWEIALP-AL00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/63.0.3239.83 Mobile Safari/537.36 T7/10.13 baiduboxapp/10.13.0.11 (Baidu; P1 8.1.0)'; 22 | var HUAWEIMeta10ProQQ = 'Mozilla/5.0 (Linux; U; Android 8.1.0; zh-cn; BLA-AL00 Build/HUAWEIBLA-AL00) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.132 MQQBrowser/8.9 Mobile Safari/537.36'; 23 | var HUAWEInova3Wechat = 'Mozilla/5.0 (Linux; Android 8.1; PAR-AL00 Build/HUAWEIPAR-AL00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.132 MQQBrowser/6.2 TBS/044304 Mobile Safari/537.36 MicroMessenger/6.7.3.1360(0x26070333) NetType/WIFI Language/zh_CN Process/tools'; 24 | var HUAWEIMeta9UC = 'Mozilla/5.0 (Linux; U; Android 8.0.0; zh-CN; MHA-AL00 Build/HUAWEIMHA-AL00) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.108 UCBrowser/12.1.4.994 Mobile Safari/537.36'; 25 | var HUAWEIP40SearchCraft = 'Mozilla/5.0 (Linux; Android 10; ANA-AN00 Build/HUAWEIANA-AN00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/97.0.4692.98 Mobile Safari/537.36 T7/13.41 ChatSearch/1.0 SearchCraft/5.3.0.1 (Baidu; P1 10)'; 26 | var baiduIOSJisu = 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Mobile/14E277 info baiduboxapp/3.7.6.12 (Baidu; P2 10.3)'; 27 | var baiduAndroidJisu = 'Mozilla/5.0 (Linux; Android 7.1.1; OS105 Build/NGI77B; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/63.0.3239.83 Mobile Safari/537.36 T7/10.13 lite baiduboxapp/3.7.5.11 (Baidu; P1 7.1.1)'; 28 | var swanApp = 'Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 swan/2.4.0 swan-baiduboxapp/11.9.0.1 baiduboxapp/11.9.0.1 (Baidu; P2 12.2)'; 29 | // oppo原生浏览器 30 | var oppoBrowser = 'Mozilla/5.0 (Linux; U; Android 8.1.0; zh-cn; PBBM30 Build/OPM1.171019.026) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/70.0.3538.80 Mobile Safari/537.36 HeyTapBrowser/10.7.4.2'; 31 | var tomasApp = 'Mozilla/5.0 (Linux; Android 10; TAS-AN00 Build/HUAWEITAS-AN00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/76.0.3809.89 Mobile Safari/537.36 T7/12.1 matrixstyle/1 SP-engine/0.0.0 bdapp/1.0 (tomas; tomas) tomas/1.0.0.1 (Baidu; P1 10) NABar/1.0'; 32 | var baiduboxvision = 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 SP-engine/2.24.0 bdapp/1.0 (baiduboxvision; baiduboxvision) baiduboxvision/1.4.0.10 (Baidu; P2 14.0) main/1.0 bdapp/1.0 (baiduboxvision; baiduboxvision) baiduboxvision/1.4.0.10 (Baidu; P2 14.0) NABar/1.0'; 33 | // 关怀版浏览器 34 | var baiduboxsenior = 'Mozilla/5.0 (Linux; Android 8.1.0; ONEPLUS A5000 Build/OPM1.171019.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/63.0.3239.83 Mobile Safari/537.36 T7/10.13 bdapp/1.0 (baiduboxsenior; baiduboxsenior) baiduboxsenior/1.0.0.0 (Baidu; P1 8.1.0)'; 35 | // 趣新热 APP 即厂商小米白牌 36 | var knewsApp = 'Mozilla/5.0 (Linux; Android 10; TAS-AN00 Build/HUAWEITAS-AN00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/76.0.3809.89 Mobile Safari/537.36 T7/12.13.0 SP-engine/0.0.0 bdapp/1.0 (knews; knews) knews/2.0.0.1 (Baidu; P1 10) NABar/1.0'; 37 | // 搜索 SDK 38 | var BDBoxEngine = 'Mozilla/5.0 (Linux; U; Android 10; zh-cn; Mi 10 Build/QKQ1.191117.002) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/70.0.3538.80 Mobile Safari/537.36 HeyTapBrowser/7.30.0 BDBoxEngine/1.0.1'; 39 | var vivo = 'Mozilla/5.0 (Linux; Android 10; V1829A; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/87.0.4280.141 Mobile Safari/537.36 VivoBrowser/13.7.60.0'; 40 | // ipad 手百ua 存在 BaiduBoxApp 及 baiduboxapp 41 | var ipadBd = 'Mozilla/5.0 (iPad; CPU OS 12_0_1 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) BaiduBoxApp/12.6.0 Mobile/16A404 Safari/602.1 SP-engine/2.66.0 main%2F1.0 baiduboxapp/13.28.0.10 (Baidu; P2 12.0.1) NABar/1.0 webCore=0x13ab8bb10'; 42 | // 鸿蒙浏览器 43 | var arkBrowser = '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'; 44 | // 鸿蒙百度app 45 | var baiduboxOnArk = '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 bdapp/1.0 (baiduboxapp; baiduboxapp) baiduboxapp/13.64.0.0 (Baidu; P5 5.0.0.25)'; 46 | // 鸿蒙百度极速版 47 | var baiduLiteOnArk = '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 bdapp/1.0 (baiduboxlite; baiduboxlite) baiduboxlite/6.0.0.0 (Baidu; P5 5.0.0.25)'; 48 | 49 | var bdhonor = 'okhttp/3.11.0 SP-engine/2.73.0 Dalvik/2.1.0 (Linux; U; Android 13; IN2010 Build/RKQ1.211119.001) bdapp/1.0 (bdhonorbrowser; bdhonorbrowser) bdhonorbrowser/8.0.1.10 (Baidu; P1 13)'; 50 | var bdhonor2 = 'okhttp/3.11.0 SP-engine/2.73.0 Dalvik/2.1.0 (Linux; U; Android 13; IN2010 Build/RKQ1.211119.001) bdapp/1.0 (bdhonorbrowser; bdhonorbrowser) bdhonorbrowser/8.0.2.13 (Baidu; P1 13)'; 51 | var bdhonor3 = 'okhttp/3.11.0 SP-engine/2.73.0 Dalvik/2.1.0 (Linux; U; Android 13; IN2010 Build/RKQ1.211119.001) bdapp/1.0 (bdhonorbrowser; bdhonorbrowser) bdhonorbrowser/9.0.0.2 (Baidu; P1 13)'; 52 | 53 | describe('UA', function () { 54 | it('should detect chrome', function () { 55 | expect(UA.isChromeDesktop()).to.equal(true); 56 | expect(UA.isQQ()).to.equal(false); 57 | expect(UA.isUC()).to.equal(false); 58 | expect(UA.use(wrongChrome).isChromeMobile()).to.equal(false); 59 | }); 60 | it('should detect QQ browser', function () { 61 | expect(UA.use(qqAndroid).isQQ()).to.equal(true); 62 | expect(UA.use(qqIOS).isQQ()).to.equal(true); 63 | expect(UA.use(qqAndroid).isQQBrowser()).to.equal(true); 64 | expect(UA.use(qqIOS).isQQBrowser()).to.equal(true); 65 | }); 66 | it('should detect QQ app', function () { 67 | expect(UA.use(qqApp).isQQApp()).to.equal(true); 68 | expect(UA.use(qqApp).isQQBrowser()).to.equal(false); 69 | }); 70 | it('should detect weixin', function () { 71 | expect(UA.use(weixinApp).isWeixinApp()).to.equal(true); 72 | expect(UA.use(weixinApp).isQQBrowser()).to.equal(false); 73 | }); 74 | it('should detect UC browser', function () { 75 | expect(UA.use(ucAndroid).isUC()).to.equal(true); 76 | }); 77 | it('should detect iOS version', function () { 78 | expect(UA.use(qqIOS).isIOS()).to.equal(true); 79 | expect(UA.use(qqIOS).iOSVersion()).to.deep.equal([10, 3]); 80 | }); 81 | it('should detect BaiduBox version', function () { 82 | expect(UA.use(baiduIOS).isBaiduBox()).to.equal(true); 83 | expect(UA.use(baiduAndroid).isBaiduBox()).to.equal(true); 84 | expect(UA.use(baiduIOS).baiduBoxVersion()).to.deep.equal([9, 0, 0, 8]); 85 | expect(UA.use(baiduAndroid).baiduBoxVersion()).to.deep.equal([6, 3]); 86 | }); 87 | it('should detect BaiduHonorBrowser version', function () { 88 | expect(UA.use(bdhonor).isBaiduBox()).to.equal(true); 89 | expect(UA.use(bdhonor).isBaiduHonorBrowser()).to.equal(true); 90 | expect(UA.use(bdhonor).honorVersion()).to.deep.equal([8, 0, 1, 10]); 91 | expect(UA.use(bdhonor).baiduBoxVersion()).to.deep.equal([13, 38, 5, 0]); 92 | expect(UA.use(bdhonor2).baiduBoxVersion()).to.deep.equal([13, 38, 5, 0]); 93 | expect(UA.use(bdhonor3).baiduBoxVersion()).to.deep.equal([13, 38, 5, 0]); 94 | }); 95 | 96 | it('should detect AppleWebkit version', function () { 97 | expect(UA.use(safariIOS).appleWebkitVersion()).to.deep.equal([603, 1, 30]); 98 | }); 99 | it('should detect safari browser', function () { 100 | expect(UA.use(safariIOS).isSafariBrowser()).to.equal(true); 101 | expect(UA.use(qqIOS).isSafariBrowser()).to.equal(false); 102 | expect(UA.use(chromeMobile).isSafariBrowser()).to.equal(false); 103 | }); 104 | it('should detect only chrome browser', function () { 105 | expect(UA.use(chromeMobile).isGoogleChrome()).to.equal(true); 106 | expect(UA.use(HUAWEIChromeBrowser).isGoogleChrome()).to.equal(true); 107 | expect(UA.use(HUAWEIMeta9).isGoogleChrome()).to.equal(false); 108 | expect(UA.use(HUAWEIMeta9UC).isGoogleChrome()).to.equal(false); 109 | expect(UA.use(XiaoMiBrowser).isGoogleChrome()).to.equal(false); 110 | expect(UA.use(MEIZUPRO6).isGoogleChrome()).to.equal(false); 111 | expect(UA.use(oppoBrowser).isGoogleChrome()).to.equal(false); 112 | }); 113 | it('should detect UIWebview', function () { 114 | expect(UA.use(qqIOS).isUIWebview()).to.equal(false); 115 | expect(UA.use(ucIOS).isUIWebview()).to.equal(true); 116 | expect(UA.use(ucAndroid).isUIWebview()).to.equal(false); 117 | }); 118 | it('should detect WKWebview', function () { 119 | expect(UA.use(qqIOS).isWKWebview()).to.equal(true); 120 | expect(UA.use(ucIOS).isWKWebview()).to.equal(false); 121 | expect(UA.use(ucAndroid).isWKWebview()).to.equal(false); 122 | }); 123 | it('should detect searchCraft', function () { 124 | expect(UA.use(searchCraft).isSearchCraft()).to.equal(true); 125 | expect(UA.use(ucIOS).isWKWebview()).to.equal(false); 126 | expect(UA.use(ucAndroid).isWKWebview()).to.equal(false); 127 | }); 128 | it('should detect CriOS', function () { 129 | expect(UA.use(chromeMobile).isCriOS()).to.equal(true); 130 | expect(UA.use(ucIOS).isCriOS()).to.equal(false); 131 | expect(UA.use(ucAndroid).isCriOS()).to.equal(false); 132 | }); 133 | it('should detect HUAWEIBrowser', function () { 134 | expect(UA.use(HUAWEIMeta9).isHUAWEIBrowser()).to.equal(true); 135 | expect(UA.use(HUAWEIMeta10baidu).isHUAWEIBrowser()).to.equal(false); 136 | expect(UA.use(HUAWEIMeta10ProQQ).isHUAWEIBrowser()).to.equal(false); 137 | expect(UA.use(HUAWEInova3Wechat).isHUAWEIBrowser()).to.equal(false); 138 | expect(UA.use(HUAWEIMeta9UC).isHUAWEIBrowser()).to.equal(false); 139 | expect(UA.use(HUAWEIP40SearchCraft).isHUAWEIBrowser()).to.equal(false); 140 | }); 141 | it('should detect MZBrowser', function () { 142 | expect(UA.use(MEIZUPRO6).isMZBrowser()).to.equal(true); 143 | }); 144 | it('should detect baiduBoxJisu', function () { 145 | expect(UA.use(baiduAndroidJisu).isBaiduBoxJisu()).to.equal(true); 146 | }); 147 | it('should detect baiduBoxJisu', function () { 148 | expect(UA.use(baiduIOSJisu).isBaiduBoxJisu()).to.equal(true); 149 | }); 150 | it('should detect swanApp', function () { 151 | expect(UA.use(swanApp).isXcxApp()).to.equal(true); 152 | }); 153 | it('should detect baiduboxvision', function () { 154 | expect(UA.use(baiduboxvision).isBaiduBoxVision()).to.equal(true); 155 | }); 156 | it('should detect baiduboxvision is bdapp', function () { 157 | expect(UA.use(baiduboxvision).isBdapp()).to.equal(true); 158 | }); 159 | it('should detect baiduboxvision is baiduboxOrBdapp', function () { 160 | expect(UA.use(baiduboxvision).isBaiduboxOrBdapp()).to.equal(true); 161 | }); 162 | it('should detect tomas', function () { 163 | expect(UA.use(tomasApp).isTomas()).to.equal(true); 164 | }); 165 | it('should detect tomas is bdapp', function () { 166 | expect(UA.use(tomasApp).isBdapp()).to.equal(true); 167 | }); 168 | it('should detect tomas is baiduboxOrBdapp', function () { 169 | expect(UA.use(tomasApp).isBaiduboxOrBdapp()).to.equal(true); 170 | }); 171 | 172 | it('should detect knews', function () { 173 | expect(UA.use(knewsApp).isKnews()).to.equal(true); 174 | }); 175 | 176 | it('should detect knews is bdapp', function () { 177 | expect(UA.use(knewsApp).isBdapp()).to.equal(true); 178 | }); 179 | 180 | it('should detect knews is baiduboxOrBdapp', function () { 181 | expect(UA.use(knewsApp).isBaiduboxOrBdapp()).to.equal(true); 182 | }); 183 | 184 | it('should detect BDBoxEngine', function () { 185 | expect(UA.use(BDBoxEngine).isBDBoxEngine()).to.equal(true); 186 | }); 187 | 188 | it('should detect BDBoxEngine is not isBaiduBox', function () { 189 | expect(UA.use(BDBoxEngine).isBaiduBox()).to.equal(false); 190 | }); 191 | 192 | it('should detect BDBoxEngine is not bdapp', function () { 193 | expect(UA.use(BDBoxEngine).isBdapp()).to.equal(false); 194 | }); 195 | 196 | it('should detect BDBoxEngine is not baiduboxOrBdapp', function () { 197 | expect(UA.use(BDBoxEngine).isBaiduboxOrBdapp()).to.equal(false); 198 | }); 199 | 200 | it('should detect baiduboxsenior', function () { 201 | expect(UA.use(baiduboxsenior).isBaiduboxsenior()).to.equal(true); 202 | expect(UA.use(baiduboxsenior).isTomas()).to.equal(false); 203 | expect(UA.use(baiduboxsenior).isBdapp()).to.equal(true); 204 | expect(UA.use(baiduboxsenior).isBaiduboxOrBdapp()).to.equal(true); 205 | expect(UA.use(baiduboxsenior).isBaiduBox()).to.equal(false); 206 | expect(UA.use(tomasApp).isBaiduboxsenior()).to.equal(false); 207 | expect(UA.use(knewsApp).isBaiduboxsenior()).to.equal(false); 208 | expect(UA.use(baiduboxvision).isBaiduboxsenior()).to.equal(false); 209 | expect(UA.use(baiduAndroidJisu).isBaiduboxsenior()).to.equal(false); 210 | expect(UA.use(baiduIOSJisu).isBaiduboxsenior()).to.equal(false); 211 | expect(UA.use(baiduIOS).isBaiduboxsenior()).to.equal(false); 212 | expect(UA.use(baiduAndroid).isBaiduboxsenior()).to.equal(false); 213 | }); 214 | 215 | it('should detect vivo browser', function () { 216 | expect(UA.use(vivo).isVivoBrowser()).to.equal(true); 217 | }); 218 | 219 | it('should detect oppo browser', function () { 220 | expect(UA.use(oppoBrowser).isOppoBrowser()).to.equal(true); 221 | }); 222 | 223 | it('should detect arkweb browser', function () { 224 | expect(UA.use(arkBrowser).isArkBrowser()).to.equal(true); 225 | }); 226 | 227 | it('should detect arkweb baibubox', function () { 228 | expect(UA.use(baiduboxOnArk).isBaiduBox()).to.equal(false); 229 | expect(UA.use(baiduboxOnArk).isBaiduBoxOnArk()).to.equal(true); 230 | expect(UA.use(baiduboxOnArk).isBaiduMainOnArk()).to.equal(true); 231 | expect(UA.use(baiduLiteOnArk).isBaiduBox()).to.equal(false); 232 | expect(UA.use(baiduLiteOnArk).isBaiduBoxOnArk()).to.equal(true); 233 | expect(UA.use(baiduLiteOnArk).isBaiduMainOnArk()).to.equal(false); 234 | expect(UA.use(baiduLiteOnArk).isBaiduLiteOnArk()).to.equal(true); 235 | }); 236 | }); 237 | 238 | describe('version', function () { 239 | it('should get baiduBox version', function () { 240 | expect(UA.use(baiduAndroid).baiduBoxVersion()).to.deep.equal([6, 3]); 241 | expect(UA.use(baiduboxsenior).baiduBoxVersion()).to.deep.equal(0); 242 | expect(UA.use(ipadBd).baiduBoxVersion()).to.deep.equal([13, 28, 0, 10]); 243 | }); 244 | it('should get searchCraft version', function () { 245 | expect(UA.use(searchCraft).secrVersion()).to.deep.equal([2, 6, 0]); 246 | }); 247 | it('should get Chrome version', function () { 248 | expect(UA.use(ucAndroid).getChromeVersion()).to.deep.equal([40, 0, 2214, 89]); 249 | }); 250 | it('should not get baiduBox version', function () { 251 | expect(UA.use(ucAndroid).baiduBoxVersion()).to.equal(0); 252 | expect(UA.use(searchCraft).baiduBoxVersion()).to.equal(0); 253 | expect(UA.use(baiduboxsenior).baiduBoxVersion()).to.deep.equal(0); 254 | }); 255 | it('should not get searchCraft version', function () { 256 | expect(UA.use(ucAndroid).secrVersion()).to.equal(0); 257 | expect(UA.use(baiduIOS).secrVersion()).to.equal(0); 258 | expect(UA.use(baiduboxsenior).secrVersion()).to.equal(0); 259 | }); 260 | it('should not get Chrome version', function () { 261 | expect(UA.use(qqAndroid).getChromeVersion()).to.equal(0); 262 | expect(UA.use(wrongChrome).getChromeVersion()).to.deep.equal([]); 263 | }); 264 | it('should get android version', function () { 265 | expect(UA.use(galaxyS5).androidVersion()).to.deep.equal([5, 0]); 266 | expect(UA.use(pixel2).androidVersion()).to.deep.equal([8, 0]); 267 | expect(UA.use(pixel2XL).androidVersion()).to.deep.equal([8, 0, 0]); 268 | expect(UA.use(qqIOS).androidVersion()).to.deep.equal([]); 269 | }); 270 | it('should get vivo version', function () { 271 | expect(UA.use(vivo).vivoBrowserVersion()).to.deep.equal([13, 7, 60, 0]); 272 | }); 273 | it('should not get vivo version', function () { 274 | expect(UA.use(ucAndroid).vivoBrowserVersion()).to.deep.equal([]); 275 | }); 276 | it('should not get baiduBox version on arkweb', function () { 277 | expect(UA.use(baiduboxOnArk).baiduBoxVersion()).to.deep.equal(0); 278 | }); 279 | it('should get baiduBox version on arkweb', function () { 280 | expect(UA.use(arkBrowser).baiduBoxVersionOnArk()).to.deep.equal(0); 281 | expect(UA.use(baiduAndroid).baiduBoxVersionOnArk()).to.deep.equal(0); 282 | expect(UA.use(baiduboxOnArk).baiduBoxVersionOnArk()).to.deep.equal([13, 64, 0, 0]); 283 | expect(UA.use(baiduboxOnArk).baiduMainVersionOnArk()).to.deep.equal([13, 64, 0, 0]); 284 | expect(UA.use(baiduLiteOnArk).baiduBoxVersionOnArk()).to.deep.equal([6, 0, 0, 0]); 285 | expect(UA.use(baiduLiteOnArk).baiduMainVersionOnArk()).to.equal(0); 286 | expect(UA.use(baiduLiteOnArk).baiduLiteVersionOnArk()).to.deep.equal([6, 0, 0, 0]); 287 | }); 288 | }); 289 | describe('baiduBoxOrbdappVersion', function () { 290 | var testBdappUa = 'Mobile/15E148 SP-engine/2.24.0 bdapp/1.0 (test) test (Baidu; P2 14.0) main/1.0 bdapp/1.0 (Baidu; P2 14.0) NABar/1.0'; 291 | var btestBaiduboxappUa = '(KHTML, like Gecko) Mobile/13F69 baiduboxapp /1000306f/C4FF069AC425606E29ACA3E490065B7C5DFD70645OCEANNARPH/1'; 292 | it('should detect baiduBoxOrBdapp version', function () { 293 | expect(UA.use(btestBaiduboxappUa).baiduBoxOrBdappVersion()).to.deep.equal(null); 294 | expect(UA.use(baiduIOS).baiduBoxOrBdappVersion()).to.deep.equal([9, 0, 0, 8]); 295 | expect(UA.use(baiduAndroid).baiduBoxOrBdappVersion()).to.deep.equal([6, 3]); 296 | expect(UA.use(baiduIOSJisu).baiduBoxOrBdappVersion()).to.deep.equal([3, 7, 6, 12]); 297 | expect(UA.use(baiduAndroidJisu).baiduBoxOrBdappVersion()).to.deep.equal([3, 7, 5, 11]); 298 | expect(UA.use(testBdappUa).baiduBoxOrBdappVersion()).to.deep.equal(null); 299 | expect(UA.use(tomasApp).baiduBoxOrBdappVersion()).to.deep.equal([1, 0, 0, 1]); 300 | expect(UA.use(knewsApp).baiduBoxOrBdappVersion()).to.deep.equal([2, 0, 0, 1]); 301 | expect(UA.use(baiduboxvision).baiduBoxOrBdappVersion()).to.deep.equal([1, 4, 0, 10]); 302 | expect(UA.use(qqApp).baiduBoxOrBdappVersion()).to.deep.equal(null); 303 | expect(UA.use(weixinApp).baiduBoxOrBdappVersion()).to.deep.equal(null); 304 | expect(UA.use(baiduboxsenior).baiduBoxOrBdappVersion()).to.deep.equal([1, 0, 0, 0]); 305 | }); 306 | it('should detect bdapp version', function () { 307 | expect(UA.use(testBdappUa).bdappVersion()).to.deep.equal(null); 308 | expect(UA.use(btestBaiduboxappUa).bdappVersion()).to.deep.equal(null); 309 | expect(UA.use(tomasApp).bdappVersion()).to.deep.equal([1, 0, 0, 1]); 310 | expect(UA.use(knewsApp).bdappVersion()).to.deep.equal([2, 0, 0, 1]); 311 | expect(UA.use(baiduboxvision).bdappVersion()).to.deep.equal([1, 4, 0, 10]); 312 | expect(UA.use(qqApp).bdappVersion()).to.deep.equal(null); 313 | expect(UA.use(weixinApp).bdappVersion()).to.deep.equal(null); 314 | expect(UA.use(baiduboxsenior).bdappVersion()).to.deep.equal([1, 0, 0, 0]); 315 | }); 316 | }); 317 | }); 318 | --------------------------------------------------------------------------------