weex-nuke
Version:
基于 Rax 、Weex 的高性能组件体系 ~~
461 lines (439 loc) • 13.1 kB
JavaScript
/**
* 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的判断逻辑、浏览器内核判断逻辑,各种没有听说过的平板判断与系统判断
*/
;
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 };