From 31f94f3a51b2a04a7d4bb7bb8039ab51d178ca17 Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Sat, 18 Mar 2023 17:04:43 +0700 Subject: [PATCH] Fix #441 #591 - Generate ESM version of main CJS file at build time --- dist/ua-parser.mjs | 1219 ++++++++++++++++++++++++++++++++++++++++++++ package.json | 10 +- readme.md | 6 + 3 files changed, 1233 insertions(+), 2 deletions(-) create mode 100644 dist/ua-parser.mjs diff --git a/dist/ua-parser.mjs b/dist/ua-parser.mjs new file mode 100644 index 00000000..7d3aafd1 --- /dev/null +++ b/dist/ua-parser.mjs @@ -0,0 +1,1219 @@ +// Generated ESM version of UAParser.js +// Source file: /src/ua-parser.js + +///////////////////////////////////////////////////////////////////////////////// +/* UAParser.js v1.1.34 + Copyright © 2012-2023 Faisal Salman + MIT License *//* + Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data. + Supports browser & node.js environment. + Demo : https://faisalman.github.io/ua-parser-js + Source : https://github.com/faisalman/ua-parser-js */ +///////////////////////////////////////////////////////////////////////////////// + +const window = undefined; + + ////////////// + // Constants + ///////////// + + + var LIBVERSION = '1.1.34', + EMPTY = '', + UNKNOWN = '?', + FUNC_TYPE = 'function', + UNDEF_TYPE = 'undefined', + OBJ_TYPE = 'object', + STR_TYPE = 'string', + MAJOR = 'major', + MODEL = 'model', + NAME = 'name', + TYPE = 'type', + VENDOR = 'vendor', + VERSION = 'version', + ARCHITECTURE= 'architecture', + CONSOLE = 'console', + MOBILE = 'mobile', + TABLET = 'tablet', + SMARTTV = 'smarttv', + WEARABLE = 'wearable', + EMBEDDED = 'embedded', + USER_AGENT = 'user-agent', + UA_MAX_LENGTH = 350, + BRANDS = 'brands', + FULLVERLIST = 'fullVersionList', + PLATFORM = 'platform', + PLATFORMVER = 'platformVersion', + BITNESS = 'bitness', + CH_HEADER = 'sec-ch-ua', + CH_HEADER_FULL_VER_LIST = CH_HEADER + '-full-version-list', + CH_HEADER_ARCH = CH_HEADER + '-arch', + CH_HEADER_BITNESS = CH_HEADER + '-bitness', + CH_HEADER_MOBILE = CH_HEADER + '-mobile', + CH_HEADER_MODEL = CH_HEADER + '-model', + CH_HEADER_PLATFORM = CH_HEADER + '-platform', + CH_HEADER_PLATFORM_VER = CH_HEADER_PLATFORM + '-version', + CH_ALL_VALUES = ['brands', 'fullVersionList', MOBILE, MODEL, 'platform', 'platformVersion', ARCHITECTURE, 'bitness'], + UA_BROWSER = 'browser', + UA_CPU = 'cpu', + UA_DEVICE = 'device', + UA_ENGINE = 'engine', + UA_OS = 'os', + UA_RESULT = 'result'; + + var AMAZON = 'Amazon', + APPLE = 'Apple', + ASUS = 'ASUS', + BLACKBERRY = 'BlackBerry', + GOOGLE = 'Google', + HUAWEI = 'Huawei', + LG = 'LG', + MICROSOFT = 'Microsoft', + MOTOROLA = 'Motorola', + SAMSUNG = 'Samsung', + SHARP = 'Sharp', + SONY = 'Sony', + SWISS = 'Swiss', + XIAOMI = 'Xiaomi', + ZEBRA = 'Zebra', + ZTE = 'ZTE', + + BROWSER = 'Browser', + CHROME = 'Chrome', + EDGE = 'Edge', + FIREFOX = 'Firefox', + OPERA = 'Opera', + FACEBOOK = 'Facebook', + + WINDOWS = 'Windows'; + + var NAVIGATOR = (typeof window !== UNDEF_TYPE && window.navigator) ? + window.navigator : + undefined, + NAVIGATOR_UADATA = (NAVIGATOR && NAVIGATOR.userAgentData) ? + NAVIGATOR.userAgentData : + undefined; + + /////////// + // Helper + ////////// + + var extend = function (regexes, extensions) { + var mergedRegexes = {}; + for (var i in regexes) { + mergedRegexes[i] = extensions[i] && extensions[i].length % 2 === 0 ? extensions[i].concat(regexes[i]) : regexes[i]; + } + return mergedRegexes; + }, + enumerize = function (arr) { + var enums = {}; + for (var i=0; i 0) { + if (q.length === 2) { + if (typeof q[1] == FUNC_TYPE) { + // 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] === FUNC_TYPE && !(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 ? match : undefined; + } + } + } + } + i += 2; + } + }, + + strMapper = function (str, map) { + + for (var i in map) { + // check if current value is array + if (typeof map[i] === OBJ_TYPE && map[i].length > 0) { + for (var j = 0; j < map[i].length; j++) { + if (has(map[i][j], str)) { + return (i === UNKNOWN) ? undefined : i; + } + } + } else if (has(map[i], str)) { + return (i === UNKNOWN) ? undefined : i; + } + } + return str; + }; + + /////////////// + // String map + ////////////// + + // Safari < 3.0 + var oldSafariMap = { + '1.0' : '/8', + '1.2' : '/1', + '1.3' : '/3', + '2.0' : '/412', + '2.0.2' : '/416', + '2.0.3' : '/417', + '2.0.4' : '/419', + '?' : '/' + }, + windowsVersionMap = { + 'ME' : '4.90', + 'NT 3.11' : 'NT3.51', + 'NT 4.0' : 'NT4.0', + '2000' : 'NT 5.0', + 'XP' : ['NT 5.1', 'NT 5.2'], + 'Vista' : 'NT 6.0', + '7' : 'NT 6.1', + '8' : 'NT 6.2', + '8.1' : 'NT 6.3', + '10' : ['NT 6.4', 'NT 10.0'], + 'RT' : 'ARM' + }, + archEquivalenceMap = { + 'amd64' : ['x86-64', 'x64'], + 'ia32' : ['x86'] + }; + + ////////////// + // Regex map + ///////////// + + var regexes = { + + browser : [[ + + /\b(?:crmo|crios)\/([\w\.]+)/i // Chrome for Android/iOS + ], [VERSION, [NAME, 'Chrome']], [ + /edg(?:e|ios|a)?\/([\w\.]+)/i // Microsoft Edge + ], [VERSION, [NAME, 'Edge']], [ + + // Presto based + /(opera mini)\/([-\w\.]+)/i, // Opera Mini + /(opera [mobiletab]{3,6})\b.+version\/([-\w\.]+)/i, // Opera Mobi/Tablet + /(opera)(?:.+version\/|[\/ ]+)([\w\.]+)/i // Opera + ], [NAME, VERSION], [ + /opios[\/ ]+([\w\.]+)/i // Opera mini on iphone >= 8.0 + ], [VERSION, [NAME, OPERA+' Mini']], [ + /\bopr\/([\w\.]+)/i // Opera Webkit + ], [VERSION, [NAME, OPERA]], [ + + // Mixed + /(kindle)\/([\w\.]+)/i, // Kindle + /(lunascape|maxthon|netfront|jasmine|blazer)[\/ ]?([\w\.]*)/i, // Lunascape/Maxthon/Netfront/Jasmine/Blazer + // Trident based + /(avant |iemobile|slim)(?:browser)?[\/ ]?([\w\.]*)/i, // Avant/IEMobile/SlimBrowser + /(ba?idubrowser)[\/ ]?([\w\.]+)/i, // Baidu Browser + /(?:ms|\()(ie) ([\w\.]+)/i, // Internet Explorer + + // Webkit/KHTML based // Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS/Bowser/QupZilla/Falkon + /(flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi|iridium|phantomjs|bowser|quark|qupzilla|falkon|rekonq|puffin|brave|whale(?!.+naver)|qqbrowserlite|qq|duckduckgo)\/([-\w\.]+)/i, + // Rekonq/Puffin/Brave/Whale/QQBrowserLite/QQ, aka ShouQ + /(weibo)__([\d\.]+)/i // Weibo + ], [NAME, VERSION], [ + /(?:\buc? ?browser|(?:juc.+)ucweb)[\/ ]?([\w\.]+)/i // UCBrowser + ], [VERSION, [NAME, 'UC'+BROWSER]], [ + /microm.+\bqbcore\/([\w\.]+)/i, // WeChat Desktop for Windows Built-in Browser + /\bqbcore\/([\w\.]+).+microm/i + ], [VERSION, [NAME, 'WeChat(Win) Desktop']], [ + /micromessenger\/([\w\.]+)/i // WeChat + ], [VERSION, [NAME, 'WeChat']], [ + /konqueror\/([\w\.]+)/i // Konqueror + ], [VERSION, [NAME, 'Konqueror']], [ + /trident.+rv[: ]([\w\.]{1,9})\b.+like gecko/i // IE11 + ], [VERSION, [NAME, 'IE']], [ + /yabrowser\/([\w\.]+)/i // Yandex + ], [VERSION, [NAME, 'Yandex']], [ + /(avast|avg)\/([\w\.]+)/i // Avast/AVG Secure Browser + ], [[NAME, /(.+)/, '$1 Secure '+BROWSER], VERSION], [ + /\bfocus\/([\w\.]+)/i // Firefox Focus + ], [VERSION, [NAME, FIREFOX+' Focus']], [ + /\bopt\/([\w\.]+)/i // Opera Touch + ], [VERSION, [NAME, OPERA+' Touch']], [ + /coc_coc\w+\/([\w\.]+)/i // Coc Coc Browser + ], [VERSION, [NAME, 'Coc Coc']], [ + /dolfin\/([\w\.]+)/i // Dolphin + ], [VERSION, [NAME, 'Dolphin']], [ + /coast\/([\w\.]+)/i // Opera Coast + ], [VERSION, [NAME, OPERA+' Coast']], [ + /miuibrowser\/([\w\.]+)/i // MIUI Browser + ], [VERSION, [NAME, 'MIUI '+BROWSER]], [ + /fxios\/([-\w\.]+)/i // Firefox for iOS + ], [VERSION, [NAME, FIREFOX]], [ + /\bqihu|(qi?ho?o?|360)browser/i // 360 + ], [[NAME, '360 '+BROWSER]], [ + /(oculus|samsung|sailfish|huawei)browser\/([\w\.]+)/i + ], [[NAME, /(.+)/, '$1 '+BROWSER], VERSION], [ // Oculus/Samsung/Sailfish/Huawei Browser + /(comodo_dragon)\/([\w\.]+)/i // Comodo Dragon + ], [[NAME, /_/g, ' '], VERSION], [ + /(electron)\/([\w\.]+) safari/i, // Electron-based App + /(tesla)(?: qtcarbrowser|\/(20\d\d\.[-\w\.]+))/i, // Tesla + /m?(qqbrowser|baiduboxapp|2345Explorer)[\/ ]?([\w\.]+)/i // QQBrowser/Baidu App/2345 Browser + ], [NAME, VERSION], [ + /(metasr)[\/ ]?([\w\.]+)/i, // SouGouBrowser + /(lbbrowser)/i, // LieBao Browser + /\[(linkedin)app\]/i // LinkedIn App for iOS & Android + ], [NAME], [ + + // WebView + /((?:fban\/fbios|fb_iab\/fb4a)(?!.+fbav)|;fbav\/([\w\.]+);)/i // Facebook App for iOS & Android + ], [[NAME, FACEBOOK], VERSION], [ + /(kakao(?:talk|story))[\/ ]([\w\.]+)/i, // Kakao App + /(naver)\(.*?(\d+\.[\w\.]+).*\)/i, // Naver InApp + /safari (line)\/([\w\.]+)/i, // Line App for iOS + /\b(line)\/([\w\.]+)\/iab/i, // Line App for Android + /(chromium|instagram)[\/ ]([-\w\.]+)/i // Chromium/Instagram + ], [NAME, VERSION], [ + /\bgsa\/([\w\.]+) .*safari\//i // Google Search Appliance on iOS + ], [VERSION, [NAME, 'GSA']], [ + + /headlesschrome(?:\/([\w\.]+)| )/i // Chrome Headless + ], [VERSION, [NAME, CHROME+' Headless']], [ + + / wv\).+(chrome)\/([\w\.]+)/i // Chrome WebView + ], [[NAME, CHROME+' WebView'], VERSION], [ + + /droid.+ version\/([\w\.]+)\b.+(?:mobile safari|safari)/i // Android Browser + ], [VERSION, [NAME, 'Android '+BROWSER]], [ + + /(chrome|omniweb|arora|[tizenoka]{5} ?browser)\/v?([\w\.]+)/i // Chrome/OmniWeb/Arora/Tizen/Nokia + ], [NAME, VERSION], [ + + /version\/([\w\.\,]+) .*mobile\/\w+ (safari)/i // Mobile Safari + ], [VERSION, [NAME, 'Mobile Safari']], [ + /version\/([\w(\.|\,)]+) .*(mobile ?safari|safari)/i // Safari & Safari Mobile + ], [VERSION, NAME], [ + /webkit.+?(mobile ?safari|safari)(\/[\w\.]+)/i // Safari < 3.0 + ], [NAME, [VERSION, strMapper, oldSafariMap]], [ + + /(webkit|khtml)\/([\w\.]+)/i + ], [NAME, VERSION], [ + + // Gecko based + /(navigator|netscape\d?)\/([-\w\.]+)/i // Netscape + ], [[NAME, 'Netscape'], VERSION], [ + /mobile vr; rv:([\w\.]+)\).+firefox/i // Firefox Reality + ], [VERSION, [NAME, FIREFOX+' Reality']], [ + /ekiohf.+(flow)\/([\w\.]+)/i, // Flow + /(swiftfox)/i, // Swiftfox + /(icedragon|iceweasel|camino|chimera|fennec|maemo browser|minimo|conkeror|klar)[\/ ]?([\w\.\+]+)/i, + // IceDragon/Iceweasel/Camino/Chimera/Fennec/Maemo/Minimo/Conkeror/Klar + /(seamonkey|k-meleon|icecat|iceape|firebird|phoenix|palemoon|basilisk|waterfox)\/([-\w\.]+)$/i, + // Firefox/SeaMonkey/K-Meleon/IceCat/IceApe/Firebird/Phoenix + /(firefox)\/([\w\.]+)/i, // Other Firefox-based + /(mozilla)\/([\w\.]+) .+rv\:.+gecko\/\d+/i, // Mozilla + + // Other + /(polaris|lynx|dillo|icab|doris|amaya|w3m|netsurf|sleipnir|obigo|mosaic|(?:go|ice|up)[\. ]?browser)[-\/ ]?v?([\w\.]+)/i, + // Polaris/Lynx/Dillo/iCab/Doris/Amaya/w3m/NetSurf/Sleipnir/Obigo/Mosaic/Go/ICE/UP.Browser + /(links) \(([\w\.]+)/i, // Links + /panasonic;(viera)/i // Panasonic Viera + ], [NAME, VERSION], [ + + /(cobalt)\/([\w\.]+)/i // Cobalt + ], [NAME, [VERSION, /[^\d\.]+./, EMPTY]] + ], + + cpu : [[ + + /\b(?:(amd|x|x86[-_]?|wow|win)64)\b/i // AMD64 (x64) + ], [[ARCHITECTURE, 'amd64']], [ + + /(ia32(?=;))/i, // IA32 (quicktime) + /((?:i[346]|x)86)[;\)]/i // IA32 (x86) + ], [[ARCHITECTURE, 'ia32']], [ + + /\b(aarch64|arm(v?8e?l?|_?64))\b/i // ARM64 + ], [[ARCHITECTURE, 'arm64']], [ + + /\b(arm(?:v[67])?ht?n?[fl]p?)\b/i // ARMHF + ], [[ARCHITECTURE, 'armhf']], [ + + // PocketPC mistakenly identified as PowerPC + /windows (ce|mobile); ppc;/i + ], [[ARCHITECTURE, 'arm']], [ + + /((?:ppc|powerpc)(?:64)?)(?: mac|;|\))/i // PowerPC + ], [[ARCHITECTURE, /ower/, EMPTY, lowerize]], [ + + /(sun4\w)[;\)]/i // SPARC + ], [[ARCHITECTURE, 'sparc']], [ + + /((?:avr32|ia64(?=;))|68k(?=\))|\barm(?=v(?:[1-7]|[5-7]1)l?|;|eabi)|(?=atmel )avr|(?:irix|mips|sparc)(?:64)?\b|pa-risc)/i + // IA64, 68K, ARM/64, AVR/32, IRIX/64, MIPS/64, SPARC/64, PA-RISC + ], [[ARCHITECTURE, lowerize]] + ], + + device : [[ + + ////////////////////////// + // MOBILES & TABLETS + ///////////////////////// + + // Samsung + /\b(sch-i[89]0\d|shw-m380s|sm-[ptx]\w{2,4}|gt-[pn]\d{2,4}|sgh-t8[56]9|nexus 10)/i + ], [MODEL, [VENDOR, SAMSUNG], [TYPE, TABLET]], [ + /\b((?:s[cgp]h|gt|sm)-\w+|sc[g-]?[\d]+a?|galaxy nexus)/i, + /samsung[- ]([-\w]+)/i, + /sec-(sgh\w+)/i + ], [MODEL, [VENDOR, SAMSUNG], [TYPE, MOBILE]], [ + + // Apple + /\((ip(?:hone|od)[\w ]*);/i // iPod/iPhone + ], [MODEL, [VENDOR, APPLE], [TYPE, MOBILE]], [ + /\((ipad);[-\w\),; ]+apple/i, // iPad + /applecoremedia\/[\w\.]+ \((ipad)/i, + /\b(ipad)\d\d?,\d\d?[;\]].+ios/i + ], [MODEL, [VENDOR, APPLE], [TYPE, TABLET]], [ + /(macintosh);/i + ], [MODEL, [VENDOR, APPLE]], [ + + // Sharp + /\b(sh-?[altvz]?\d\d[a-ekm]?)/i + ], [MODEL, [VENDOR, SHARP], [TYPE, MOBILE]], [ + + // Huawei + /\b((?:ag[rs][23]?|bah2?|sht?|btv)-a?[lw]\d{2})\b(?!.+d\/s)/i + ], [MODEL, [VENDOR, HUAWEI], [TYPE, TABLET]], [ + /(?:huawei|honor)([-\w ]+)[;\)]/i, + /\b(nexus 6p|\w{2,4}e?-[atu]?[ln][\dx][012359c][adn]?)\b(?!.+d\/s)/i + ], [MODEL, [VENDOR, HUAWEI], [TYPE, MOBILE]], [ + + // Xiaomi + /\b(poco[\w ]+)(?: bui|\))/i, // Xiaomi POCO + /\b; (\w+) build\/hm\1/i, // Xiaomi Hongmi 'numeric' models + /\b(hm[-_ ]?note?[_ ]?(?:\d\w)?) bui/i, // Xiaomi Hongmi + /\b(redmi[\-_ ]?(?:note|k)?[\w_ ]+)(?: bui|\))/i, // Xiaomi Redmi + /\b(mi[-_ ]?(?:a\d|one|one[_ ]plus|note lte|max|cc)?[_ ]?(?:\d?\w?)[_ ]?(?:plus|se|lite)?)(?: bui|\))/i // Xiaomi Mi + ], [[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, MOBILE]], [ + /\b(mi[-_ ]?(?:pad)(?:[\w_ ]+))(?: bui|\))/i // Mi Pad tablets + ],[[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, TABLET]], [ + + // OPPO + /; (\w+) bui.+ oppo/i, + /\b(cph[12]\d{3}|p(?:af|c[al]|d\w|e[ar])[mt]\d0|x9007|a101op)\b/i + ], [MODEL, [VENDOR, 'OPPO'], [TYPE, MOBILE]], [ + + // Vivo + /vivo (\w+)(?: bui|\))/i, + /\b(v[12]\d{3}\w?[at])(?: bui|;)/i + ], [MODEL, [VENDOR, 'Vivo'], [TYPE, MOBILE]], [ + + // Realme + /\b(rmx[12]\d{3})(?: bui|;|\))/i + ], [MODEL, [VENDOR, 'Realme'], [TYPE, MOBILE]], [ + + // Motorola + /\b(milestone|droid(?:[2-4x]| (?:bionic|x2|pro|razr))?:?( 4g)?)\b[\w ]+build\//i, + /\bmot(?:orola)?[- ](\w*)/i, + /((?:moto[\w\(\) ]+|xt\d{3,4}|nexus 6)(?= bui|\)))/i + ], [MODEL, [VENDOR, MOTOROLA], [TYPE, MOBILE]], [ + /\b(mz60\d|xoom[2 ]{0,2}) build\//i + ], [MODEL, [VENDOR, MOTOROLA], [TYPE, TABLET]], [ + + // LG + /((?=lg)?[vl]k\-?\d{3}) bui| 3\.[-\w; ]{10}lg?-([06cv9]{3,4})/i + ], [MODEL, [VENDOR, LG], [TYPE, TABLET]], [ + /(lm(?:-?f100[nv]?|-[\w\.]+)(?= bui|\))|nexus [45])/i, + /\blg[-e;\/ ]+((?!browser|netcast|android tv)\w+)/i, + /\blg-?([\d\w]+) bui/i + ], [MODEL, [VENDOR, LG], [TYPE, MOBILE]], [ + + // Lenovo + /(ideatab[-\w ]+)/i, + /lenovo ?(s[56]000[-\w]+|tab(?:[\w ]+)|yt[-\d\w]{6}|tb[-\d\w]{6})/i + ], [MODEL, [VENDOR, 'Lenovo'], [TYPE, TABLET]], [ + + // Nokia + /(?:maemo|nokia).*(n900|lumia \d+)/i, + /nokia[-_ ]?([-\w\.]*)/i + ], [[MODEL, /_/g, ' '], [VENDOR, 'Nokia'], [TYPE, MOBILE]], [ + + // Google + /(pixel c)\b/i // Google Pixel C + ], [MODEL, [VENDOR, GOOGLE], [TYPE, TABLET]], [ + /droid.+; (pixel[\daxl ]{0,6})(?: bui|\))/i // Google Pixel + ], [MODEL, [VENDOR, GOOGLE], [TYPE, MOBILE]], [ + + // Sony + /droid.+ (a?\d[0-2]{2}so|[c-g]\d{4}|so[-gl]\w+|xq-a\w[4-7][12])(?= bui|\).+chrome\/(?![1-6]{0,1}\d\.))/i + ], [MODEL, [VENDOR, SONY], [TYPE, MOBILE]], [ + /sony tablet [ps]/i, + /\b(?:sony)?sgp\w+(?: bui|\))/i + ], [[MODEL, 'Xperia Tablet'], [VENDOR, SONY], [TYPE, TABLET]], [ + + // OnePlus + / (kb2005|in20[12]5|be20[12][59])\b/i, + /(?:one)?(?:plus)? (a\d0\d\d)(?: b|\))/i + ], [MODEL, [VENDOR, 'OnePlus'], [TYPE, MOBILE]], [ + + // Amazon + /(alexa)webm/i, + /(kf[a-z]{2}wi)( bui|\))/i, // Kindle Fire without Silk + /(kf[a-z]+)( bui|\)).+silk\//i // Kindle Fire HD + ], [MODEL, [VENDOR, AMAZON], [TYPE, TABLET]], [ + /((?:sd|kf)[0349hijorstuw]+)( bui|\)).+silk\//i // Fire Phone + ], [[MODEL, /(.+)/g, 'Fire Phone $1'], [VENDOR, AMAZON], [TYPE, MOBILE]], [ + + // BlackBerry + /(playbook);[-\w\),; ]+(rim)/i // BlackBerry PlayBook + ], [MODEL, VENDOR, [TYPE, TABLET]], [ + /\b((?:bb[a-f]|st[hv])100-\d)/i, + /\(bb10; (\w+)/i // BlackBerry 10 + ], [MODEL, [VENDOR, BLACKBERRY], [TYPE, MOBILE]], [ + + // Asus + /(?:\b|asus_)(transfo[prime ]{4,10} \w+|eeepc|slider \w+|nexus 7|padfone|p00[cj])/i + ], [MODEL, [VENDOR, ASUS], [TYPE, TABLET]], [ + / (z[bes]6[027][012][km][ls]|zenfone \d\w?)\b/i + ], [MODEL, [VENDOR, ASUS], [TYPE, MOBILE]], [ + + // HTC + /(nexus 9)/i // HTC Nexus 9 + ], [MODEL, [VENDOR, 'HTC'], [TYPE, TABLET]], [ + /(htc)[-;_ ]{1,2}([\w ]+(?=\)| bui)|\w+)/i, // HTC + + // ZTE + /(zte)[- ]([\w ]+?)(?: bui|\/|\))/i, + /(alcatel|geeksphone|nexian|panasonic(?!(?:;|\.))|sony(?!-bra))[-_ ]?([-\w]*)/i // Alcatel/GeeksPhone/Nexian/Panasonic/Sony + ], [VENDOR, [MODEL, /_/g, ' '], [TYPE, MOBILE]], [ + + // Acer + /droid.+; ([ab][1-7]-?[0178a]\d\d?)/i + ], [MODEL, [VENDOR, 'Acer'], [TYPE, TABLET]], [ + + // Meizu + /droid.+; (m[1-5] note) bui/i, + /\bmz-([-\w]{2,})/i + ], [MODEL, [VENDOR, 'Meizu'], [TYPE, MOBILE]], [ + + // MIXED + /(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus|dell|meizu|motorola|polytron)[-_ ]?([-\w]*)/i, + // BlackBerry/BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron + /(hp) ([\w ]+\w)/i, // HP iPAQ + /(asus)-?(\w+)/i, // Asus + /(microsoft); (lumia[\w ]+)/i, // Microsoft Lumia + /(lenovo)[-_ ]?([-\w]+)/i, // Lenovo + /(jolla)/i, // Jolla + /(oppo) ?([\w ]+) bui/i // OPPO + ], [VENDOR, MODEL, [TYPE, MOBILE]], [ + + /(kobo)\s(ereader|touch)/i, // Kobo + /(archos) (gamepad2?)/i, // Archos + /(hp).+(touchpad(?!.+tablet)|tablet)/i, // HP TouchPad + /(kindle)\/([\w\.]+)/i, // Kindle + /(nook)[\w ]+build\/(\w+)/i, // Nook + /(dell) (strea[kpr\d ]*[\dko])/i, // Dell Streak + /(le[- ]+pan)[- ]+(\w{1,9}) bui/i, // Le Pan Tablets + /(trinity)[- ]*(t\d{3}) bui/i, // Trinity Tablets + /(gigaset)[- ]+(q\w{1,9}) bui/i, // Gigaset Tablets + /(vodafone) ([\w ]+)(?:\)| bui)/i // Vodafone + ], [VENDOR, MODEL, [TYPE, TABLET]], [ + + /(surface duo)/i // Surface Duo + ], [MODEL, [VENDOR, MICROSOFT], [TYPE, TABLET]], [ + /droid [\d\.]+; (fp\du?)(?: b|\))/i // Fairphone + ], [MODEL, [VENDOR, 'Fairphone'], [TYPE, MOBILE]], [ + /(u304aa)/i // AT&T + ], [MODEL, [VENDOR, 'AT&T'], [TYPE, MOBILE]], [ + /\bsie-(\w*)/i // Siemens + ], [MODEL, [VENDOR, 'Siemens'], [TYPE, MOBILE]], [ + /\b(rct\w+) b/i // RCA Tablets + ], [MODEL, [VENDOR, 'RCA'], [TYPE, TABLET]], [ + /\b(venue[\d ]{2,7}) b/i // Dell Venue Tablets + ], [MODEL, [VENDOR, 'Dell'], [TYPE, TABLET]], [ + /\b(q(?:mv|ta)\w+) b/i // Verizon Tablet + ], [MODEL, [VENDOR, 'Verizon'], [TYPE, TABLET]], [ + /\b(?:barnes[& ]+noble |bn[rt])([\w\+ ]*) b/i // Barnes & Noble Tablet + ], [MODEL, [VENDOR, 'Barnes & Noble'], [TYPE, TABLET]], [ + /\b(tm\d{3}\w+) b/i + ], [MODEL, [VENDOR, 'NuVision'], [TYPE, TABLET]], [ + /\b(k88) b/i // ZTE K Series Tablet + ], [MODEL, [VENDOR, ZTE], [TYPE, TABLET]], [ + /\b(nx\d{3}j) b/i // ZTE Nubia + ], [MODEL, [VENDOR, ZTE], [TYPE, MOBILE]], [ + /\b(gen\d{3}) b.+49h/i // Swiss GEN Mobile + ], [MODEL, [VENDOR, SWISS], [TYPE, MOBILE]], [ + /\b(zur\d{3}) b/i // Swiss ZUR Tablet + ], [MODEL, [VENDOR, SWISS], [TYPE, TABLET]], [ + /\b((zeki)?tb.*\b) b/i // Zeki Tablets + ], [MODEL, [VENDOR, 'Zeki'], [TYPE, TABLET]], [ + /\b([yr]\d{2}) b/i, + /\b(dragon[- ]+touch |dt)(\w{5}) b/i // Dragon Touch Tablet + ], [[VENDOR, 'Dragon Touch'], MODEL, [TYPE, TABLET]], [ + /\b(ns-?\w{0,9}) b/i // Insignia Tablets + ], [MODEL, [VENDOR, 'Insignia'], [TYPE, TABLET]], [ + /\b((nxa|next)-?\w{0,9}) b/i // NextBook Tablets + ], [MODEL, [VENDOR, 'NextBook'], [TYPE, TABLET]], [ + /\b(xtreme\_)?(v(1[045]|2[015]|[3469]0|7[05])) b/i // Voice Xtreme Phones + ], [[VENDOR, 'Voice'], MODEL, [TYPE, MOBILE]], [ + /\b(lvtel\-)?(v1[12]) b/i // LvTel Phones + ], [[VENDOR, 'LvTel'], MODEL, [TYPE, MOBILE]], [ + /\b(ph-1) /i // Essential PH-1 + ], [MODEL, [VENDOR, 'Essential'], [TYPE, MOBILE]], [ + /\b(v(100md|700na|7011|917g).*\b) b/i // Envizen Tablets + ], [MODEL, [VENDOR, 'Envizen'], [TYPE, TABLET]], [ + /\b(trio[-\w\. ]+) b/i // MachSpeed Tablets + ], [MODEL, [VENDOR, 'MachSpeed'], [TYPE, TABLET]], [ + /\btu_(1491) b/i // Rotor Tablets + ], [MODEL, [VENDOR, 'Rotor'], [TYPE, TABLET]], [ + /(shield[\w ]+) b/i // Nvidia Shield Tablets + ], [MODEL, [VENDOR, 'Nvidia'], [TYPE, TABLET]], [ + /(sprint) (\w+)/i // Sprint Phones + ], [VENDOR, MODEL, [TYPE, MOBILE]], [ + /(kin\.[onetw]{3})/i // Microsoft Kin + ], [[MODEL, /\./g, ' '], [VENDOR, MICROSOFT], [TYPE, MOBILE]], [ + /droid.+; ([c6]+|et5[16]|mc[239][23]x?|vc8[03]x?)\)/i // Zebra + ], [MODEL, [VENDOR, ZEBRA], [TYPE, TABLET]], [ + /droid.+; (ec30|ps20|tc[2-8]\d[kx])\)/i + ], [MODEL, [VENDOR, ZEBRA], [TYPE, MOBILE]], [ + + /////////////////// + // SMARTTVS + /////////////////// + + /smart-tv.+(samsung)/i // Samsung + ], [VENDOR, [TYPE, SMARTTV]], [ + /hbbtv.+maple;(\d+)/i + ], [[MODEL, /^/, 'SmartTV'], [VENDOR, SAMSUNG], [TYPE, SMARTTV]], [ + /(nux; netcast.+smarttv|lg (netcast\.tv-201\d|android tv))/i // LG SmartTV + ], [[VENDOR, LG], [TYPE, SMARTTV]], [ + /(apple) ?tv/i // Apple TV + ], [VENDOR, [MODEL, APPLE+' TV'], [TYPE, SMARTTV]], [ + /crkey/i // Google Chromecast + ], [[MODEL, CHROME+'cast'], [VENDOR, GOOGLE], [TYPE, SMARTTV]], [ + /droid.+aft(\w)( bui|\))/i // Fire TV + ], [MODEL, [VENDOR, AMAZON], [TYPE, SMARTTV]], [ + /\(dtv[\);].+(aquos)/i, + /(aquos-tv[\w ]+)\)/i // Sharp + ], [MODEL, [VENDOR, SHARP], [TYPE, SMARTTV]],[ + /(bravia[\w ]+)( bui|\))/i // Sony + ], [MODEL, [VENDOR, SONY], [TYPE, SMARTTV]], [ + /(mitv-\w{5}) bui/i // Xiaomi + ], [MODEL, [VENDOR, XIAOMI], [TYPE, SMARTTV]], [ + /Hbbtv.*(technisat) (.*);/i // TechniSAT + ], [VENDOR, MODEL, [TYPE, SMARTTV]], [ + /\b(roku)[\dx]*[\)\/]((?:dvp-)?[\d\.]*)/i, // Roku + /hbbtv\/\d+\.\d+\.\d+ +\([\w\+ ]*; *([\w\d][^;]*);([^;]*)/i // HbbTV devices + ], [[VENDOR, trim], [MODEL, trim], [TYPE, SMARTTV]], [ + /\b(android tv|smart[- ]?tv|opera tv|tv; rv:)\b/i // SmartTV from Unidentified Vendors + ], [[TYPE, SMARTTV]], [ + + /////////////////// + // CONSOLES + /////////////////// + + /(ouya)/i, // Ouya + /(nintendo) (\w+)/i // Nintendo + ], [VENDOR, MODEL, [TYPE, CONSOLE]], [ + /droid.+; (shield) bui/i // Nvidia + ], [MODEL, [VENDOR, 'Nvidia'], [TYPE, CONSOLE]], [ + /(playstation \w+)/i // Playstation + ], [MODEL, [VENDOR, SONY], [TYPE, CONSOLE]], [ + /\b(xbox(?: one)?(?!; xbox))[\); ]/i // Microsoft Xbox + ], [MODEL, [VENDOR, MICROSOFT], [TYPE, CONSOLE]], [ + + /////////////////// + // WEARABLES + /////////////////// + + /((pebble))app/i // Pebble + ], [VENDOR, MODEL, [TYPE, WEARABLE]], [ + /(watch)(?: ?os[,\/]|\d,\d\/)[\d\.]+/i // Apple Watch + ], [MODEL, [VENDOR, APPLE], [TYPE, WEARABLE]], [ + /droid.+; (glass) \d/i // Google Glass + ], [MODEL, [VENDOR, GOOGLE], [TYPE, WEARABLE]], [ + /droid.+; (wt63?0{2,3})\)/i + ], [MODEL, [VENDOR, ZEBRA], [TYPE, WEARABLE]], [ + /(quest( 2| pro)?)/i // Oculus Quest + ], [MODEL, [VENDOR, FACEBOOK], [TYPE, WEARABLE]], [ + + /////////////////// + // EMBEDDED + /////////////////// + + /(tesla)(?: qtcarbrowser|\/[-\w\.]+)/i // Tesla + ], [VENDOR, [TYPE, EMBEDDED]], [ + + //////////////////// + // MIXED (GENERIC) + /////////////////// + + /droid .+?; ([^;]+?)(?: bui|\) applew).+? mobile safari/i // Android Phones from Unidentified Vendors + ], [MODEL, [TYPE, MOBILE]], [ + /droid .+?; ([^;]+?)(?: bui|\) applew).+?(?! mobile) safari/i // Android Tablets from Unidentified Vendors + ], [MODEL, [TYPE, TABLET]], [ + /\b((tablet|tab)[;\/]|focus\/\d(?!.+mobile))/i // Unidentifiable Tablet + ], [[TYPE, TABLET]], [ + /(phone|mobile(?:[;\/]| [ \w\/\.]*safari)|pda(?=.+windows ce))/i // Unidentifiable Mobile + ], [[TYPE, MOBILE]], [ + /(android[-\w\. ]{0,9});.+buil/i // Generic Android Device + ], [MODEL, [VENDOR, 'Generic']] + ], + + engine : [[ + + /windows.+ edge\/([\w\.]+)/i // EdgeHTML + ], [VERSION, [NAME, EDGE+'HTML']], [ + + /webkit\/537\.36.+chrome\/(?!27)([\w\.]+)/i // Blink + ], [VERSION, [NAME, 'Blink']], [ + + /(presto)\/([\w\.]+)/i, // Presto + /(webkit|trident|netfront|netsurf|amaya|lynx|w3m|goanna)\/([\w\.]+)/i, // WebKit/Trident/NetFront/NetSurf/Amaya/Lynx/w3m/Goanna + /ekioh(flow)\/([\w\.]+)/i, // Flow + /(khtml|tasman|links)[\/ ]\(?([\w\.]+)/i, // KHTML/Tasman/Links + /(icab)[\/ ]([23]\.[\d\.]+)/i // iCab + ], [NAME, VERSION], [ + + /rv\:([\w\.]{1,9})\b.+(gecko)/i // Gecko + ], [VERSION, NAME] + ], + + os : [[ + + // Windows + /microsoft (windows) (vista|xp)/i // Windows (iTunes) + ], [NAME, VERSION], [ + /(windows) nt 6\.2; (arm)/i, // Windows RT + /(windows (?:phone(?: os)?|mobile))[\/ ]?([\d\.\w ]*)/i, // Windows Phone + /(windows)[\/ ]?([ntce\d\. ]+\w)(?!.+xbox)/i + ], [NAME, [VERSION, strMapper, windowsVersionMap]], [ + /(win(?=3|9|n)|win 9x )([nt\d\.]+)/i + ], [[NAME, WINDOWS], [VERSION, strMapper, windowsVersionMap]], [ + + // iOS/macOS + /ip[honead]{2,4}\b(?:.*os ([\w]+) like mac|; opera)/i, // iOS + /cfnetwork\/.+darwin/i + ], [[VERSION, /_/g, '.'], [NAME, 'iOS']], [ + /(mac os x) ?([\w\. ]*)/i, + /(macintosh|mac_powerpc\b)(?!.+haiku)/i // Mac OS + ], [[NAME, 'macOS'], [VERSION, /_/g, '.']], [ + + // Mobile OSes + /droid ([\w\.]+)\b.+(android[- ]x86|harmonyos)/i // Android-x86/HarmonyOS + ], [VERSION, NAME], [ // Android/WebOS/QNX/Bada/RIM/Maemo/MeeGo/Sailfish OS + /(android|webos|qnx|bada|rim tablet os|maemo|meego|sailfish)[-\/ ]?([\w\.]*)/i, + /(blackberry)\w*\/([\w\.]*)/i, // Blackberry + /(tizen|kaios)[\/ ]([\w\.]+)/i, // Tizen/KaiOS + /\((series40);/i // Series 40 + ], [NAME, VERSION], [ + /\(bb(10);/i // BlackBerry 10 + ], [VERSION, [NAME, BLACKBERRY]], [ + /(?:symbian ?os|symbos|s60(?=;)|series60)[-\/ ]?([\w\.]*)/i // Symbian + ], [VERSION, [NAME, 'Symbian']], [ + /mozilla\/[\d\.]+ \((?:mobile|tablet|tv|mobile; [\w ]+); rv:.+ gecko\/([\w\.]+)/i // Firefox OS + ], [VERSION, [NAME, FIREFOX+' OS']], [ + /web0s;.+rt(tv)/i, + /\b(?:hp)?wos(?:browser)?\/([\w\.]+)/i // WebOS + ], [VERSION, [NAME, 'webOS']], [ + /watch(?: ?os[,\/]|\d,\d\/)([\d\.]+)/i // watchOS + ], [VERSION, [NAME, 'watchOS']], [ + + // Google Chromecast + /crkey\/([\d\.]+)/i // Google Chromecast + ], [VERSION, [NAME, CHROME+'cast']], [ + /(cros) [\w]+(?:\)| ([\w\.]+)\b)/i // Chromium OS + ], [[NAME, "Chrome OS"], VERSION],[ + + // Smart TVs + /panasonic;(viera)/i, // Panasonic Viera + /(netrange)mmh/i, // Netrange + /(nettv)\/(\d+\.[\w\.]+)/i, // NetTV + + // Console + /(nintendo|playstation) (\w+)/i, // Nintendo/Playstation + /(xbox); +xbox ([^\);]+)/i, // Microsoft Xbox (360, One, X, S, Series X, Series S) + + // Other + /\b(joli|palm)\b ?(?:os)?\/?([\w\.]*)/i, // Joli/Palm + /(mint)[\/\(\) ]?(\w*)/i, // Mint + /(mageia|vectorlinux)[; ]/i, // Mageia/VectorLinux + /([kxln]?ubuntu|debian|suse|opensuse|gentoo|arch(?= linux)|slackware|fedora|mandriva|centos|pclinuxos|red ?hat|zenwalk|linpus|raspbian|plan 9|minix|risc os|contiki|deepin|manjaro|elementary os|sabayon|linspire)(?: gnu\/linux)?(?: enterprise)?(?:[- ]linux)?(?:-gnu)?[-\/ ]?(?!chrom|package)([-\w\.]*)/i, + // Ubuntu/Debian/SUSE/Gentoo/Arch/Slackware/Fedora/Mandriva/CentOS/PCLinuxOS/RedHat/Zenwalk/Linpus/Raspbian/Plan9/Minix/RISCOS/Contiki/Deepin/Manjaro/elementary/Sabayon/Linspire + /(hurd|linux) ?([\w\.]*)/i, // Hurd/Linux + /(gnu) ?([\w\.]*)/i, // GNU + /\b([-frentopcghs]{0,5}bsd|dragonfly)[\/ ]?(?!amd|[ix346]{1,2}86)([\w\.]*)/i, // FreeBSD/NetBSD/OpenBSD/PC-BSD/GhostBSD/DragonFly + /(haiku) (\w+)/i // Haiku + ], [NAME, VERSION], [ + /(sunos) ?([\w\.\d]*)/i // Solaris + ], [[NAME, 'Solaris'], VERSION], [ + /((?:open)?solaris)[-\/ ]?([\w\.]*)/i, // Solaris + /(aix) ((\d)(?=\.|\)| )[\w\.])*/i, // AIX + /\b(beos|os\/2|amigaos|morphos|openvms|fuchsia|hp-ux)/i, // BeOS/OS2/AmigaOS/MorphOS/OpenVMS/Fuchsia/HP-UX + /(unix) ?([\w\.]*)/i // UNIX + ], [NAME, VERSION] + ] + }; + + ///////////////// + // Constructor + //////////////// + + function UAParserDataCH (uach, isHTTP_UACH) { + uach = uach || {}; + initialize.call(this, CH_ALL_VALUES); + if (isHTTP_UACH) { + initialize.call(this, [ + [BRANDS, itemListToArray(uach[CH_HEADER])], + [FULLVERLIST, itemListToArray(uach[CH_HEADER_FULL_VER_LIST])], + [BRANDS, itemListToArray(uach[CH_HEADER])], + [MOBILE, /\?1/.test(uach[CH_HEADER_MOBILE])], + [MODEL, stripQuotes(uach[CH_HEADER_MODEL])], + [PLATFORM, stripQuotes(uach[CH_HEADER_PLATFORM])], + [PLATFORMVER, stripQuotes(uach[CH_HEADER_PLATFORM_VER])], + [ARCHITECTURE, stripQuotes(uach[CH_HEADER_ARCH])], + [BITNESS, stripQuotes(uach[CH_HEADER_BITNESS])] + ]); + } else { + for (var prop in uach) { + if(this.hasOwnProperty(prop) && uach[prop]) this[prop] = stripQuotes(uach[prop]); + } + } + return this; + } + + function UAParserItem (data) { + if (!data) return; + this.ua = data[0]; + this.uaCH = data[1]; + this.rgxMap = data[3]; + this.data = (function (data) { + var ua = data[0], + uaCH = data[1], + itemType = data[2], + rgxMap = data[3], + init_props = data[4], + is_ignoreProps = data[5], + is_ignoreRgx = data[6], + toString_props = data[7]; + + function UAParserData () { + initialize.call(this, init_props); + } + UAParserData.prototype.withClientHints = function () { + + // nodejs / non-client-hints browsers + if (!NAVIGATOR_UADATA) { + + var HTTP_UACH = uaCH; + switch (itemType) { + case UA_BROWSER: + return new UAParserBrowser(ua, rgxMap, HTTP_UACH).parseCH().get(); + case UA_CPU: + return new UAParserCPU(ua, rgxMap, HTTP_UACH).parseCH().get(); + case UA_DEVICE: + return new UAParserDevice(ua, rgxMap, HTTP_UACH).parseCH().get(); + case UA_ENGINE: + return new UAParserEngine(ua, rgxMap).get(); + case UA_OS: + return new UAParserOS(ua, rgxMap, HTTP_UACH).parseCH().get(); + default : + return new UAParserResult(ua, rgxMap, HTTP_UACH) + .set('ua', ua) + .set('ua_ch', uaCH) + .set(UA_BROWSER, new UAParserBrowser(ua, rgxMap[UA_BROWSER], HTTP_UACH).parseCH().get()) + .set(UA_CPU, new UAParserCPU(ua, rgxMap[UA_CPU], HTTP_UACH).parseCH().get()) + .set(UA_DEVICE, new UAParserDevice(ua, rgxMap[UA_DEVICE], HTTP_UACH).parseCH().get()) + .set(UA_ENGINE, new UAParserEngine(ua, rgxMap[UA_ENGINE]).get()) + .set(UA_OS, new UAParserOS(ua, rgxMap[UA_OS], HTTP_UACH).parseCH().get()) + .get(); + } + } + + // browsers based on chromium 85+ + return NAVIGATOR_UADATA + .getHighEntropyValues(CH_ALL_VALUES) + .then(function (res) { + + var JS_UACH = new UAParserDataCH(res, false); + switch (itemType) { + case UA_BROWSER: + return UAParserBrowser(ua, rgxMap, JS_UACH).parseCH().get(); + case UA_CPU: + return new UAParserCPU(ua, rgxMap, JS_UACH).parseCH().get(); + case UA_DEVICE: + return new UAParserDevice(ua, rgxMap, JS_UACH).parseCH().get(); + case UA_ENGINE: + return new UAParserEngine(ua, rgxMap).get(); + case UA_OS: + return new UAParserOS(ua, rgxMap, JS_UACH).parseCH().get(); + default : + return new UAParserResult(ua, rgxMap, JS_UACH) + .set('ua', ua) + .set('ua_ch', JS_UACH) + .set(UA_BROWSER, new UAParserBrowser(ua, rgxMap[UA_BROWSER], JS_UACH).parseCH().get()) + .set(UA_CPU, new UAParserCPU(ua, rgxMap[UA_CPU], JS_UACH).parseCH().get()) + .set(UA_DEVICE, new UAParserDevice(ua, rgxMap[UA_DEVICE], JS_UACH).parseCH().get()) + .set(UA_ENGINE, new UAParserEngine(ua, rgxMap[UA_ENGINE]).get()) + .set(UA_OS, new UAParserOS(ua, rgxMap[UA_OS], JS_UACH).parseCH().get()) + .get(); + } + }); + }; + if(itemType != UA_RESULT) { + UAParserData.prototype.is = function (strToCheck) { + var is = false; + for (var i in this) { + if (this.hasOwnProperty(i) && !is_ignoreProps[i] && lowerize(this[i], is_ignoreRgx) === lowerize(strToCheck, is_ignoreRgx)) { + is = true; + if (strToCheck != UNDEF_TYPE) break; + } else if (strToCheck == UNDEF_TYPE && is) { + is = !is; + break; + } + } + return is; + }; + UAParserData.prototype.toString = function () { + var str = EMPTY; + for (var i in toString_props) { + if (typeof(this[toString_props[i]]) !== UNDEF_TYPE) { + str += (str ? ' ' : EMPTY) + this[toString_props[i]]; + } + } + return str ? str : UNDEF_TYPE; + }; + } + if (!NAVIGATOR_UADATA) { + UAParserData.prototype.then = function (cb) { + cb(this); + return this; + }; + } + return new UAParserData(); + })(data); + } + UAParserItem.prototype.get = function (prop) { + if (!prop) return this.data; + return this.data.hasOwnProperty(prop) ? this.data[prop] : undefined; + }; + UAParserItem.prototype.parse = function () { + rgxMapper.call(this.data, this.ua, this.rgxMap); + return this; + }; + UAParserItem.prototype.set = function (prop, val) { + this.data[prop] = val; + return this; + }; + + function UAParserBrowser (ua, browserMap, uach) { + UAParserItem.call(this, [ + ua, + uach, + UA_BROWSER, + browserMap, + [NAME, VERSION, MAJOR], + [VERSION, MAJOR], + ' ?browser$', + [NAME, VERSION] + ]); + this.parse(); + // Brave-specific detection + if (NAVIGATOR && NAVIGATOR.brave && typeof NAVIGATOR.brave.isBrave == FUNC_TYPE) { + this.set(NAME, 'Brave'); + } + this.set(MAJOR, majorize(this.get(VERSION))); + } + UAParserBrowser.prototype = new UAParserItem(); + UAParserBrowser.prototype.parseCH = function () { + var brands = this.uaCH[FULLVERLIST] || this.uaCH[BRANDS]; + if (brands) { + for (var i in brands) { + var brandName = brands[i].brand, + brandVersion = brands[i].version; + if (!/not.a.brand/i.test(brandName) || /chromi/i.test(this.get(NAME))) { + this.set(NAME, strip(GOOGLE+' ', brandName)) + .set(VERSION, brandVersion) + .set(MAJOR, majorize(brandVersion)); + } + } + } + return this; + }; + + function UAParserCPU (ua, cpuMap, uach) { + UAParserItem.call(this, [ + ua, + uach, + UA_CPU, + cpuMap, + [ARCHITECTURE], + [], + null, + [ARCHITECTURE] + ]); + this.parse(); + } + UAParserCPU.prototype = new UAParserItem(); + UAParserCPU.prototype.parseCH = function () { + var archName = this.uaCH[ARCHITECTURE]; + if (archName) { + archName += (archName && this.uaCH[BITNESS] == '64') ? '64' : EMPTY; + rgxMapper.call(this.data, archName, this.rgxMap); + } + return this; + }; + + function UAParserDevice (ua, deviceMap, uach) { + UAParserItem.call(this, [ + ua, + uach, + UA_DEVICE, + deviceMap, + [TYPE, MODEL, VENDOR], + [], + null, + [VENDOR, MODEL] + ]); + this.parse(); + if (!this.get(TYPE) && NAVIGATOR_UADATA && NAVIGATOR_UADATA[MOBILE]) { + this.set(TYPE, MOBILE); + } + // iPadOS-specific detection: identified as Mac, but has some iOS-only properties + if (this.get(NAME) == 'Macintosh' && NAVIGATOR && typeof NAVIGATOR.standalone !== UNDEF_TYPE && NAVIGATOR.maxTouchPoints && NAVIGATOR.maxTouchPoints > 2) { + this.set(MODEL, 'iPad') + .set(TYPE, TABLET); + } + } + UAParserDevice.prototype = new UAParserItem(); + UAParserDevice.prototype.parseCH = function () { + if (this.uaCH[MOBILE]) { + this.set(TYPE, MOBILE); + } + if (this.uaCH[MODEL]) { + this.set(MODEL, this.uaCH[MODEL]); + } + return this; + }; + + function UAParserEngine (ua, engineMap) { + UAParserItem.call(this, [ + ua, + null, + UA_ENGINE, + engineMap, + [NAME, VERSION], + [VERSION], + null, + [NAME, VERSION] + ]); + this.parse(); + } + UAParserEngine.prototype = new UAParserItem(); + + function UAParserOS (ua, osMap, uach) { + UAParserItem.call(this, [ + ua, + uach, + UA_OS, + osMap, + [NAME, VERSION], + [VERSION], + ' ?os$', + [NAME, VERSION] + ]); + this.parse(); + if (!this.get(NAME) && NAVIGATOR_UADATA && NAVIGATOR_UADATA[PLATFORM] && NAVIGATOR_UADATA[PLATFORM] != 'Unknown') { + this.set(NAME, NAVIGATOR_UADATA[PLATFORM]); + } + } + UAParserOS.prototype = new UAParserItem(); + UAParserOS.prototype.parseCH = function () { + var osName = this.uaCH[PLATFORM]; + if(osName) { + var osVersion = this.uaCH[PLATFORMVER]; + osVersion = (osName == WINDOWS) ? (parseInt(majorize(osVersion), 10) >= 13 ? '11' : '10') : osVersion; + this.set(NAME, osName) + .set(VERSION, osVersion); + } + return this; + }; + + function UAParserResult (ua, resMap, uach) { + UAParserItem.call(this, [ua, uach, UA_RESULT, resMap]); + } + UAParserResult.prototype = new UAParserItem(); + + function UAParser (ua, extensions, headers) { + + if (typeof ua === OBJ_TYPE) { + if (isExtensions(ua)) { + if (typeof extensions === OBJ_TYPE) { + headers = extensions; // case UAParser(extensions, headers) + } + extensions = ua; // case UAParser(extensions) + } else { + headers = ua; // case UAParser(headers) + extensions = undefined; + } + ua = undefined; + } else if (typeof ua === STR_TYPE && !isExtensions(extensions)) { + headers = extensions; // case UAParser(ua, headers) + extensions = undefined; + } + + if (!(this instanceof UAParser)) { + return new UAParser(ua, extensions, headers).getResult(); + } + + var userAgent = ua || + ((NAVIGATOR && NAVIGATOR.userAgent) ? + NAVIGATOR.userAgent : + (headers && headers[USER_AGENT] ? + headers[USER_AGENT] : + EMPTY)), + + HTTP_UACH = new UAParserDataCH(headers, true), + + regexMap = extensions ? + extend(regexes, extensions) : + regexes; + + // public methods + this.getBrowser = function () { + return new UAParserBrowser(userAgent, regexMap[UA_BROWSER], HTTP_UACH).get(); + }; + + this.getCPU = function () { + return new UAParserCPU(userAgent, regexMap[UA_CPU], HTTP_UACH).get(); + }; + + this.getDevice = function () { + return new UAParserDevice(userAgent, regexMap[UA_DEVICE], HTTP_UACH).get(); + }; + + this.getEngine = function () { + return new UAParserEngine(userAgent, regexMap[UA_ENGINE]).get(); + }; + + this.getOS = function () { + return new UAParserOS(userAgent, regexMap[UA_OS], HTTP_UACH).get(); + }; + + this.getResult = function () { + return new UAParserResult(userAgent, regexMap, HTTP_UACH) + .set('ua', userAgent) + .set('ua_ch', HTTP_UACH) + .set(UA_BROWSER, this.getBrowser()) + .set(UA_CPU, this.getCPU()) + .set(UA_DEVICE, this.getDevice()) + .set(UA_ENGINE, this.getEngine()) + .set(UA_OS, this.getOS()) + .get(); + }; + + this.getUA = function () { + return userAgent; + }; + + this.setUA = function (ua) { + userAgent = (typeof ua === STR_TYPE && ua.length > UA_MAX_LENGTH) ? trim(ua, UA_MAX_LENGTH) : ua; + return this; + }; + + this.setUA(userAgent); + return this; + } + + UAParser.VERSION = LIBVERSION; + UAParser.BROWSER = enumerize([NAME, VERSION, MAJOR]); + UAParser.CPU = enumerize([ARCHITECTURE]); + UAParser.DEVICE = enumerize([MODEL, VENDOR, TYPE, CONSOLE, MOBILE, SMARTTV, TABLET, WEARABLE, EMBEDDED]); + UAParser.ENGINE = UAParser.OS = enumerize([NAME, VERSION]); + + export {UAParser}; \ No newline at end of file diff --git a/package.json b/package.json index 37854dce..df2cc2d1 100644 --- a/package.json +++ b/package.json @@ -139,14 +139,20 @@ "yuanyang ", "Yun Young-jin ", "Zach Bjornson " - ], + ], + "type": "commonjs", "main": "src/ua-parser.js", + "module": "dist/ua-parser.mjs", + "exports": { + "require": "./src/ua-parser.js", + "import": "./dist/ua-parser.mjs" + }, "files": [ "dist", "src" ], "scripts": { - "build": "uglifyjs src/ua-parser.js -o dist/ua-parser.min.js --comments '/^ UA/' && uglifyjs src/ua-parser.js -o dist/ua-parser.pack.js --comments '/^ UA/' --compress --mangle", + "build": "uglifyjs src/ua-parser.js -o dist/ua-parser.min.js --comments '/^ UA/' && uglifyjs src/ua-parser.js -o dist/ua-parser.pack.js --comments '/^ UA/' --compress --mangle && node -e \"const fs=require('fs');fs.writeFileSync('dist/ua-parser.mjs','// Generated ESM version of UAParser.js\\n// Source file: /src/ua-parser.js\\n\\n'+fs.readFileSync('src/ua-parser.js','utf-8').replace(/\\(func[\\s\\S]+strict\\';/ig,'const window = undefined;').replace(/\\/[\\/\\s]+export[\\s\\S]+/ig,'export {UAParser};'),'utf-8')\"", "test": "jshint src/ua-parser.js && mocha -R nyan test/test.js", "test-ci": "jshint src/ua-parser.js && mocha -R spec test/test.js", "verup": "node ./node_modules/verup", diff --git a/readme.md b/readme.md index 93f5c815..2733a300 100644 --- a/readme.md +++ b/readme.md @@ -473,6 +473,12 @@ http.createServer(function (req, res) { console.log('Server running at http://127.0.0.1:1337/'); ``` +## Using ES Modules + +```js +import { UAParser } from 'ua-parser-js'; +``` + ## Using TypeScript ```sh