UNPKG

weex-nuke

Version:

基于 Rax 、Weex 的高性能组件体系 ~~

461 lines (439 loc) 13.1 kB
/** * UAParser.js v0.7.17 * Lightweight JavaScript-based User-Agent string parser * https://github.com/faisalman/ua-parser-js * * Copyright © 2012-2016 Faisal Salman <fyzlman@gmail.com> * Dual licensed under GPLv2 or MIT * 2018-04-24 modified by dubu * @description reduce size of ua judge * 移除对windows平台、amazon的判断逻辑、浏览器内核判断逻辑,各种没有听说过的平板判断与系统判断 */ 'use strict'; const LIBVERSION = '0.7.17'; const EMPTY = ''; const UNKNOWN = '?'; const MAJOR = 'major'; // deprecated const MODEL = 'model'; const NAME = 'name'; const TYPE = 'type'; const VENDOR = 'vendor'; const VERSION = 'version'; const CONSOLE = 'console'; const MOBILE = 'mobile'; const TABLET = 'tablet'; const SMARTTV = 'smarttv'; const WEARABLE = 'wearable'; const EMBEDDED = 'embedded'; const util = { extend(regexes, extensions) { const margedRegexes = {}; for (const i in regexes) { if (extensions[i] && extensions[i].length % 2 === 0) { margedRegexes[i] = extensions[i].concat(regexes[i]); } else { margedRegexes[i] = regexes[i]; } } return margedRegexes; }, has(str1, str2) { if (typeof str1 === 'string') { return str2.toLowerCase().indexOf(str1.toLowerCase()) !== -1; } return false; }, lowerize(str) { return str.toLowerCase(); }, major(version) { return typeof version === 'string' ? version.replace(/[^\d.]/g, '').split('.')[0] : undefined; }, trim(str) { return str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ''); }, }; const mapper = { rgx(ua, arrays) { // var result = {}, let i = 0; let j; let k; let p; let q; let matches; let match; // , args = arguments; while (i < arrays.length && !matches) { const regex = arrays[i]; // even sequence (0,2,4,..) const props = arrays[i + 1]; // odd sequence (1,3,5,..) j = k = 0; // try matching uastring with regexes while (j < regex.length && !matches) { matches = regex[j++].exec(ua); if (matches && typeof props !== 'undefined') { for (p = 0; p < props.length; p++) { match = matches[++k]; q = props[p]; // check if given property is actually array if (typeof q === 'object' && q.length > 0) { if (q.length == 2) { if (typeof q[1] === 'function') { // assign modified match this[q[0]] = q[1].call(this, match); } else { // assign given value, ignore regex match this[q[0]] = q[1]; } } else if (q.length == 3) { // check whether function or regex if (typeof q[1] === 'function' && !(q[1].exec && q[1].test)) { // call function (usually string mapper) this[q[0]] = match ? q[1].call(this, match, q[2]) : undefined; } else { // sanitize match using given regex this[q[0]] = match ? match.replace(q[1], q[2]) : undefined; } } else if (q.length === 4) { this[q[0]] = match ? q[3].call(this, match.replace(q[1], q[2])) : undefined; } } else { this[q] = match || undefined; } } } } i += 2; } // console.log(this); // return this; }, str(str, map) { for (const i in map) { // check if array if (typeof map[i] === 'object' && map[i].length > 0) { for (let j = 0; j < map[i].length; j++) { if (util.has(map[i][j], str)) { return i === UNKNOWN ? undefined : i; } } } else if (util.has(map[i], str)) { return i === UNKNOWN ? undefined : i; } } return str; }, }; const regexes = { browser: [ [ // Presto based /(opera\smini)\/([\w.-]+)/i, // Opera Mini /(opera\s[mobiletab]+).+version\/([\w.-]+)/i, // Opera Mobi/Tablet /(opera).+version\/([\w.]+)/i, // Opera > 9.80 /(opera)[/\s]+([\w.]+)/i, // Opera < 9.80 ], [NAME, VERSION], [ /(opios)[/\s]+([\w.]+)/i, // Opera mini on iphone >= 8.0 ], [[NAME, 'Opera Mini'], VERSION], [ /\s(opr)\/([\w.]+)/i, // Opera Webkit ], [[NAME, 'Opera'], VERSION], [ /((?:[\s\/])uc?\s?browser|(?:juc.+)ucweb)[\/\s]?([\w\.]+)/i, // UCBrowser ], [[NAME, 'UCBrowser'], VERSION], [ /(micromessenger)\/([\w\.]+)/i, // WeChat ], [[NAME, 'WeChat'], VERSION], [ /(QQ)\/([\d\.]+)/i, // QQ, aka ShouQ ], [NAME, VERSION], [ /m?(qqbrowser)[\/\s]?([\w\.]+)/i, // QQBrowser ], [NAME, VERSION], [ /xiaomi\/miuibrowser\/([\w\.]+)/i, // MIUI Browser ], [VERSION, [NAME, 'MIUI Browser']], [ /;fbav\/([\w\.]+);/i, // Facebook App for iOS & Android ], [VERSION, [NAME, 'Facebook']], [ /headlesschrome(?:\/([\w\.]+)|\s)/i, // Chrome Headless ], [VERSION, [NAME, 'Chrome Headless']], [ /\swv\).+(chrome)\/([\w\.]+)/i, // Chrome WebView ], [[NAME, /(.+)/, '$1 WebView'], VERSION], [/((?:oculus|samsung)browser)\/([\w\.]+)/i], [[NAME, /(.+(?:g|us))(.+)/, '$1 $2'], VERSION], [ // Oculus / Samsung Browser /android.+version\/([\w\.]+)\s+(?:mobile\s?safari|safari)*/i, // Android Browser ], [VERSION, [NAME, 'Android Browser']], [ /(chrome|omniweb|arora|[tizenoka]{5}\s?browser)\/v?([\w\.]+)/i, // Chrome/OmniWeb/Arora/Tizen/Nokia ], [[NAME, 'Dolphin'], VERSION], [ /(dolfin)\/([\w\.]+)/i, // Dolphin ], [[NAME, 'Chrome'], VERSION], [ /((?:android.+)crmo|crios)\/([\w\.]+)/i, // Chrome for Android/iOS ], [[NAME, 'Opera Coast'], VERSION], [ /(coast)\/([\w\.]+)/i, // Opera Coast ], [VERSION, [NAME, 'Firefox']], [ /fxios\/([\w\.-]+)/i, // Firefox for iOS ], [VERSION, [NAME, 'Mobile Safari']], [ /version\/([\w\.]+).+?mobile\/\w+\s(safari)/i, // Mobile Safari ], [VERSION, NAME], [ /version\/([\w\.]+).+?(mobile\s?safari|safari)/i, // Safari & Safari Mobile ], [[NAME, 'GSA'], VERSION], [ /webkit.+?(gsa)\/([\w\.]+).+?(mobile\s?safari|safari)(\/[\w\.]+)/i, // Google Search Appliance on iOS ], [[NAME, 'Netscape'], VERSION], [ // Gecko based /(navigator|netscape)\/([\w\.-]+)/i, // Netscape ], [NAME, VERSION], [ /(mozilla)\/([\w\.]+).+rv\:.+gecko\/\d+/i, // Mozilla ], ], device: [ [ /\((ipad|playbook);[\w\s\);-]+(rim|apple)/i, // iPad/PlayBook ], [MODEL, VENDOR, [TYPE, TABLET]], [ /applecoremedia\/[\w\.]+ \((ipad)/, // iPad ], [MODEL, [VENDOR, 'Apple'], [TYPE, TABLET]], [ /\((ip[honed|\s\w*]+);.+(apple)/i, // iPod/iPhone ], [MODEL, VENDOR, [TYPE, MOBILE]], [ /\((ip[honed|\s\w*]+);/i, // iPod/iPhone ], [MODEL, [VENDOR, 'Apple'], [TYPE, MOBILE]], [ /(sony)\s(tablet\s[ps])\sbuild\//i, // Sony /(sony)?(?:sgp.+)\sbuild\//i, ], [[VENDOR, 'Sony'], [MODEL, 'Xperia Tablet'], [TYPE, TABLET]], [/android.+\s([c-g]\d{4}|so[-l]\w+)\sbuild\//i], [MODEL, [VENDOR, 'Sony'], [TYPE, CONSOLE]], [ /(lenovo)\s?(S(?:5000|6000)+(?:[-][\w+]))/i, // Lenovo tablets ], [VENDOR, MODEL, [TYPE, TABLET]], [ /(htc)[;_\s-]+([\w\s]+(?=\))|\w+)*/i, // HTC /(zte)-(\w+)*/i, // ZTE /(alcatel|geeksphone|lenovo|nexian|panasonic|(?=;\s)sony)[_\s-]?([\w-]+)*/i, // Alcatel/GeeksPhone/Lenovo/Nexian/Panasonic/Sony ], [VENDOR, [MODEL, /_/g, ' '], [TYPE, MOBILE]], [ /(nexus\s9)/i, // HTC Nexus 9 ], [MODEL, [VENDOR, 'HTC'], [TYPE, TABLET]], [ /d\/huawei([\w\s-]+)[;\)]/i, /(nexus\s6p)/i, // Huawei ], [MODEL, [VENDOR, 'Huawei'], [TYPE, MOBILE]], [ /(microsoft);\s(lumia[\s\w]+)/i, // Microsoft Lumia ], [VENDOR, MODEL, [TYPE, MOBILE]], [/android.+\s(mz60\d|xoom[\s2]{0,2})\sbuild\//i], [[VENDOR, util.trim], [MODEL, util.trim], [TYPE, SMARTTV]], [ /\(dtv[\);].+(aquos)/i, // Sharp ], [MODEL, [VENDOR, 'Sharp'], [TYPE, SMARTTV]], [/android.+((sch-i[89]0\d|shw-m380s|gt-p\d{4}|gt-n\d+|sgh-t8[56]9|nexus 10))/i, /((SM-T\w+))/i], [[VENDOR, 'Samsung'], MODEL, [TYPE, TABLET]], [ // Samsung /smart-tv.+(samsung)/i, ], [VENDOR, [TYPE, SMARTTV], MODEL], [/((s[cgp]h-\w+|gt-\w+|galaxy\snexus|sm-\w[\w\d]+))/i, /(sam[sung]*)[\s-]*(\w+-?[\w-]*)*/i, /sec-((sgh\w+))/i], [[VENDOR, 'Samsung'], MODEL, [TYPE, MOBILE]], [ /(maemo|nokia).*(n900|lumia\s\d+)/i, // Nokia /(nokia)[\s_-]?([\w-]+)*/i, ], [[VENDOR, 'Nokia'], MODEL, [TYPE, MOBILE]], [ /(nexus\s[45])/i, // LG /lg[e;\s\/-]+(\w+)*/i, /android.+lg(\-?[\d\w]+)\s+build/i, ], [MODEL, [VENDOR, 'LG'], [TYPE, MOBILE]], [ /android.+(ideatab[a-z0-9\-\s]+)/i, // Lenovo ], [MODEL, [VENDOR, 'Lenovo'], [TYPE, TABLET]], [ /android.+;\s(oppo)\s?([\w\s]+)\sbuild/i, // OPPO ], [VENDOR, MODEL, [TYPE, MOBILE]], [ /crkey/i, // Google Chromecast ], [[MODEL, 'Chromecast'], [VENDOR, 'Google']], [ /android.+(\w+)\s+build\/hm\1/i, // Xiaomi Hongmi 'numeric' models /android.+(hm[\s\-_]*note?[\s_]*(?:\d\w)?)\s+build/i, // Xiaomi Hongmi /android.+(mi[\s\-_]*(?:one|one[\s_]plus|note lte)?[\s_]*(?:\d\w?)?[\s_]*(?:plus)?)\s+build/i, // Xiaomi Mi /android.+(redmi[\s\-_]*(?:note)?(?:[\s_]*[\w\s]+)?)\s+build/i, // Redmi Phones ], [[MODEL, /_/g, ' '], [VENDOR, 'Xiaomi'], [TYPE, MOBILE]], [ /android.+(mi[\s\-_]*(?:pad)(?:[\s_]*[\w\s]+)?)\s+build/i, // Mi Pad tablets ], [[MODEL, /_/g, ' '], [VENDOR, 'Xiaomi'], [TYPE, TABLET]], [ /android.+;\s(m[1-5]\snote)\sbuild/i, // Meizu Tablet ], [MODEL, [VENDOR, 'Meizu'], [TYPE, TABLET]], [ /android.+a000(1)\s+build/i, // OnePlus /android.+oneplus\s(a\d{4})\s+build/i, ], [MODEL, [VENDOR, 'OnePlus'], [TYPE, MOBILE]], [ /android.+[;\/]\s*(zte)?.+(k\d{2})\s+build/i, // ZTE K Series Tablet ], [[VENDOR, 'ZTE'], MODEL, [TYPE, TABLET]], [ /\s(tablet|tab)[;\/]/i, // Unidentifiable Tablet /\s(mobile)(?:[;\/]|\ssafari)/i, // Unidentifiable Mobile ], [[TYPE, util.lowerize], VENDOR, MODEL], ], os: [ [ /(android|webos|palm\sos|qnx|bada|rim\stablet\sos|meego|contiki)[\/\s-]?([\w\.]+)*/i, // Android/WebOS/Palm/QNX/Bada/RIM/MeeGo/Contiki ], [NAME, VERSION], [ /(cros)\s[\w]+\s([\w\.]+\w)/i, // Chromium OS ], [[NAME, 'Chromium OS'], VERSION], [ /cfnetwork\/.+darwin/i, /ip[honead]+(?:.*os\s([\w]+)\slike\smac|;\sopera)/i, // iOS ], [[VERSION, /_/g, '.'], [NAME, 'iOS']], [ /(mac\sos\sx)\s?([\w\s\.]+\w)*/i, /(macintosh|mac(?=_powerpc)\s)/i, // Mac OS ], [NAME], [ /mozilla.+\(mobile;.+gecko.+firefox/i, // Firefox OS ], [[NAME, 'Mac OS'], [VERSION, /_/g, '.']], ], }; const UAParser = function (uastring, extensions) { if (typeof uastring === 'object') { extensions = uastring; uastring = undefined; } if (!(this instanceof UAParser)) { return new UAParser(uastring, extensions).getResult(); } let ua = uastring || (window && window.navigator && window.navigator.userAgent ? window.navigator.userAgent : EMPTY); const rgxmap = extensions ? util.extend(regexes, extensions) : regexes; // var browser = new Browser(); // var device = new Device(); // var os = new OS(); this.getBrowser = function () { const browser = { name: undefined, version: undefined }; mapper.rgx.call(browser, ua, rgxmap.browser); browser.major = util.major(browser.version); // deprecated return browser; }; this.getDevice = function () { const device = { vendor: undefined, model: undefined, type: undefined }; mapper.rgx.call(device, ua, rgxmap.device); return device; }; this.getOS = function () { const os = { name: undefined, version: undefined }; mapper.rgx.call(os, ua, rgxmap.os); return os; }; this.getResult = function () { return { ua: this.getUA(), browser: this.getBrowser(), os: this.getOS(), device: this.getDevice(), }; }; this.getUA = function () { return ua; }; this.setUA = function (uastring) { ua = uastring; // browser = new Browser(); // device = new Device(); // os = new OS(); return this; }; return this; }; UAParser.VERSION = LIBVERSION; UAParser.BROWSER = { NAME, MAJOR, // deprecated VERSION, }; UAParser.DEVICE = { MODEL, VENDOR, TYPE, CONSOLE, MOBILE, SMARTTV, TABLET, WEARABLE, EMBEDDED, }; UAParser.OS = { NAME, VERSION, }; // UAParser.Utils = util; export { UAParser };