From 3b703a6379f404dba2163d432c9fbaac7a4227c7 Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Sat, 27 Mar 2021 00:10:55 +0700 Subject: [PATCH] Refine device detection with more test cases --- dist/ua-parser.min.js | 2 +- dist/ua-parser.pack.js | 2 +- readme.md | 6 +- src/ua-parser.js | 103 ++++++------- test/device-test.json | 324 +++++++++++++++++++++++++++++++++++++++-- 5 files changed, 372 insertions(+), 65 deletions(-) diff --git a/dist/ua-parser.min.js b/dist/ua-parser.min.js index f5c7c32..6dae2b6 100644 --- a/dist/ua-parser.min.js +++ b/dist/ua-parser.min.js @@ -6,4 +6,4 @@ * Copyright © 2012-2021 Faisal Salman * Licensed under MIT License */ -(function(window,undefined){"use strict";var LIBVERSION="0.7.25",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";var util={extend:function(regexes,extensions){var mergedRegexes={};for(var i in regexes){if(extensions[i]&&extensions[i].length%2===0){mergedRegexes[i]=extensions[i].concat(regexes[i])}else{mergedRegexes[i]=regexes[i]}}return mergedRegexes},has:function(str1,str2){if(typeof str1==="string"){return str2.toLowerCase().indexOf(str1.toLowerCase())!==-1}else{return false}},lowerize:function(str){return str.toLowerCase()},major:function(version){return typeof version===STR_TYPE?version.replace(/[^\d\.]/g,"").split(".")[0]:undefined},trim:function(str){return str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"")}};var mapper={rgx:function(ua,arrays){var i=0,j,k,p,q,matches,match;while(i0){if(q.length==2){if(typeof q[1]==FUNC_TYPE){this[q[0]]=q[1].call(this,match)}else{this[q[0]]=q[1]}}else if(q.length==3){if(typeof q[1]===FUNC_TYPE&&!(q[1].exec&&q[1].test)){this[q[0]]=match?q[1].call(this,match,q[2]):undefined}else{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}},str:function(str,map){for(var i in map){if(typeof map[i]===OBJ_TYPE&&map[i].length>0){for(var j=0;j0){if(q.length==2){if(typeof q[1]==FUNC_TYPE){this[q[0]]=q[1].call(this,match)}else{this[q[0]]=q[1]}}else if(q.length==3){if(typeof q[1]===FUNC_TYPE&&!(q[1].exec&&q[1].test)){this[q[0]]=match?q[1].call(this,match,q[2]):undefined}else{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}},str:function(str,map){for(var i in map){if(typeof map[i]===OBJ_TYPE&&map[i].length>0){for(var j=0;jUA_MAX_LENGTH?util.trim(ua,UA_MAX_LENGTH):ua;return this};this.setUA(_ua);return this};UAParser.VERSION=LIBVERSION;UAParser.BROWSER={NAME:NAME,MAJOR:MAJOR,VERSION:VERSION};UAParser.CPU={ARCHITECTURE:ARCHITECTURE};UAParser.DEVICE={MODEL:MODEL,VENDOR:VENDOR,TYPE:TYPE,CONSOLE:CONSOLE,MOBILE:MOBILE,SMARTTV:SMARTTV,TABLET:TABLET,WEARABLE:WEARABLE,EMBEDDED:EMBEDDED};UAParser.ENGINE={NAME:NAME,VERSION:VERSION};UAParser.OS={NAME:NAME,VERSION:VERSION};if(typeof exports!==UNDEF_TYPE){if(typeof module!==UNDEF_TYPE&&module.exports){exports=module.exports=UAParser}exports.UAParser=UAParser}else{if(typeof define==="function"&&define.amd){define(function(){return UAParser})}else if(typeof window!=="undefined"){window.UAParser=UAParser}}var $=typeof window!=="undefined"&&(window.jQuery||window.Zepto);if($&&!$.ua){var parser=new UAParser;$.ua=parser.getResult();$.ua.get=function(){return parser.getUA()};$.ua.set=function(uastring){parser.setUA(uastring);var result=parser.getResult();for(var prop in result){$.ua[prop]=result[prop]}}}})(typeof window==="object"?window:this); \ No newline at end of file diff --git a/dist/ua-parser.pack.js b/dist/ua-parser.pack.js index abf260b..3a37870 100644 --- a/dist/ua-parser.pack.js +++ b/dist/ua-parser.pack.js @@ -6,4 +6,4 @@ * Copyright © 2012-2021 Faisal Salman * Licensed under MIT License */ -!function(r,u){"use strict";var c="function",i="undefined",b="object",s="model",e="name",o="type",a="vendor",n="version",d="architecture",t="console",w="mobile",l="tablet",m="smarttv",p="wearable",h={extend:function(i,s){var e,o={};for(e in i)s[e]&&s[e].length%2==0?o[e]=s[e].concat(i[e]):o[e]=i[e];return o},has:function(i,s){return"string"==typeof i&&-1!==s.toLowerCase().indexOf(i.toLowerCase())},lowerize:function(i){return i.toLowerCase()},major:function(i){return"string"==typeof i?i.replace(/[^\d\.]/g,"").split(".")[0]:u},trim:function(i){return i.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"")}},g={rgx:function(i,s){for(var e,o,r,a,n,d=0;d 9.80 /(opera)[\/\s]+([\w\.]+)/i // Opera < 9.80 ], [NAME, VERSION], [ @@ -234,20 +234,18 @@ ], [NAME, VERSION], [ /(?:[\s\/]uc?\s?browser|(?:juc.+)ucweb)[\/\s]?([\w\.]+)/i // UCBrowser ], [VERSION, [NAME, 'UCBrowser']], [ - /(?:windowswechat)?\sqbcore\/([\w\.]+).*(?:windowswechat)?/i // WeChat Desktop for Windows Built-in Browser + /(?:windowswechat)?\sqbcore\/([\w\.]+)\b.*(?:windowswechat)?/i // WeChat Desktop for Windows Built-in Browser ], [VERSION, [NAME, 'WeChat(Win) Desktop']], [ /micromessenger\/([\w\.]+)/i // WeChat ], [VERSION, [NAME, 'WeChat']], [ /konqueror\/([\w\.]+)/i // Konqueror ], [VERSION, [NAME, 'Konqueror']], [ - /trident.+rv[:\s]([\w\.]{1,9}).+like\sgecko/i // IE11 + /trident.+rv[:\s]([\w\.]{1,9})\b.+like\sgecko/i // IE11 ], [VERSION, [NAME, 'IE']], [ /yabrowser\/([\w\.]+)/i // Yandex ], [VERSION, [NAME, 'Yandex']], [ - /Avast\/([\w\.]+)/i // Avast Secure Browser - ], [VERSION, [NAME, 'Avast Secure Browser']], [ - /AVG\/([\w\.]+)/i // AVG Secure Browser - ], [VERSION, [NAME, 'AVG Secure Browser']], [ + /(avast|avg)\/([\w\.]+)/i // Avast/AVG Secure Browser + ], [[NAME, /(.+)/, '$1 Secure Browser'], VERSION], [ /focus\/([\w\.]+)/i // Firefox Focus ], [VERSION, [NAME, 'Firefox Focus']], [ /opt\/([\w\.]+)/i // Opera Touch @@ -292,7 +290,7 @@ /\swv\).+(chrome)\/([\w\.]+)/i // Chrome WebView ], [[NAME, 'Chrome WebView'], VERSION], [ - /droid.+\sversion\/([\w\.]+).+(?:mobile\ssafari|safari)/i // Android Browser + /droid.+\sversion\/([\w\.]+)\b.+(?:mobile\ssafari|safari)/i // Android Browser ], [VERSION, [NAME, 'Android Browser']], [ /(chrome|omniweb|arora|[tizenoka]{5}\s?browser)\/v?([\w\.]+)/i // Chrome/OmniWeb/Arora/Tizen/Nokia @@ -368,8 +366,7 @@ ///////////////////// // Samsung - /\b(sch-i[89]0\d|shw-m380s|SM-P605|SM-P610|SM-P587|gt-p\d{4}|gt-n\d+|sgh-t8[56]9|nexus 10)/i, - /(SM-T\w+)/i + /\b(sch-i[89]0\d|shw-m380s|sm-p(?:605|610|587)|sm-t\w+|gt-p\d{4}|gt-n\d+|sgh-t8[56]9|nexus\s10)/i, ], [MODEL, [VENDOR, 'Samsung'], [TYPE, TABLET]], [ /(s[cgp]h-\w+|gt-\w+|galaxy\snexus|sm-\w[\w\d]+)/i, /\ssamsung[\s-]([\w-]+)/i, @@ -381,41 +378,42 @@ ], [MODEL, [VENDOR, 'Apple'], [TYPE, MOBILE]], [ /\((ipad);[\w\s\),;-]+(apple)/i // iPad ], [MODEL, VENDOR, [TYPE, TABLET]], [ - /applecoremedia\/[\w\.]+ \((ipad)/ // iPad + /applecoremedia\/[\w\.]+\s\((ipad)/i ], [MODEL, [VENDOR, 'Apple'], [TYPE, TABLET]], [ // Huawei /d\/huawei([\w\s-]+)[;\)]/i, /\b(nexus\s6p|vog-[at]?l\d\d|ane-[at]?l[x\d]\d|eml-a?l\d\da?|lya-[at]?l\d[\dc]|clt-a?l\d\di?|ele-l\d\d)/i, - /\b(\w{2,4}-[ATU][LN][01259][019])[;\)\s]/i + /\b(\w{2,4}-[atu][ln][01259][019])[;\)\s]/i ], [MODEL, [VENDOR, 'Huawei'], [TYPE, MOBILE]], [ /\b(bah2?-a?[lw]\d{2})/i // Huawei MediaPad ], [MODEL, [VENDOR, 'Huawei'], [TYPE, TABLET]], [ // Xiaomi - /\b(poco\s\w+)\b/i, // Xiaomi POCO + /\b(poco[\s\w]+)(?:\sbuild|\))/i, // Xiaomi POCO /\b;\s(\w+)\s+build\/hm\1/i, // Xiaomi Hongmi 'numeric' models /\b(hm[\s\-_]?note?[\s_]?(?:\d\w)?)\sbuild/i, // Xiaomi Hongmi - /\b(redmi[\s\-_]?(?:note|k)?(?:[\s_]?[\w\s]+))(?:\sbuild|\))/i, // Xiaomi Redmi + /\b(redmi[\s\-_]?(?:note|k)?[\w\s_]+)(?:\sbuild|\))/i, // Xiaomi Redmi /\b(mi[\s\-_]?(?:a\d|one|one[\s_]plus|note lte)?[\s_]?(?:\d?\w?)[\s_]?(?:plus)?)\sbuild/i // Xiaomi Mi ], [[MODEL, /_/g, ' '], [VENDOR, 'Xiaomi'], [TYPE, MOBILE]], [ - /\b(mi[\s\-_]?(?:pad)(?:[\s_]?[\w\s]+))(?:\sbuild|\))/i // Mi Pad tablets + /\b(mi[\s\-_]?(?:pad)(?:[\w\s_]+))(?:\sbuild|\))/i // Mi Pad tablets ],[[MODEL, /_/g, ' '], [VENDOR, 'Xiaomi'], [TYPE, TABLET]], [ // OPPO - /;\s(\w+)\sbuild.+\soppo/i + /;\s(\w+)\sbuild.+\soppo/i, + /\s(cph[12]\d{3}|p(?:af|c[al]|d\w|e[ar])[mt]\d0|x9007)\b/i ], [MODEL, [VENDOR, 'OPPO'], [TYPE, MOBILE]], [ // Vivo - /\svivo\s(\w+)\sbuild/i, - /droid\s[\d\.]+;\s(v(?:1[89]|20)\d\d\w?[at])(?:\sbuild|;)/i + /\svivo\s(\w+)(?:\sbuild|\))/i, + /\s(v(?:1[89]|20)\d\d\w?[at])(?:\sbuild|;)/i ], [MODEL, [VENDOR, 'Vivo'], [TYPE, MOBILE]], [ // Motorola - /\s(milestone|droid(?:[2-4x]|\s(?:bionic|x2|pro|razr))?:?(\s4g)?)[\w\s]+build\//i, + /\s(milestone|droid(?:[2-4x]|\s(?:bionic|x2|pro|razr))?:?(\s4g)?)\b[\w\s]+build\//i, /\smot[\s-](\w*)/i, /(moto[\s\w\(\)]+(?=\sbuild|\)))/i, - /(XT\d{3,4}) build\//i, + /(xt\d{3,4})\sbuild\//i, /(nexus\s6)/i ], [MODEL, [VENDOR, 'Motorola'], [TYPE, MOBILE]], [ /\s(mz60\d|xoom[\s2]{0,2})\sbuild\//i @@ -431,7 +429,7 @@ // Lenovo /(ideatab[\w\-\s]+)/i, - /lenovo\s?(s(?:5000|6000)(?:[\w-]+)|tab(?:[\s\w]+)|[\w-]+)/i // Lenovo tablets + /lenovo\s?(s(?:5000|6000)(?:[\w-]+)|tab(?:[\s\w]+)|[\w-]+)/i // Lenovo tablets ], [MODEL, [VENDOR, 'Lenovo'], [TYPE, TABLET]], [ // Nokia @@ -440,7 +438,7 @@ ], [MODEL, [VENDOR, 'Nokia'], [TYPE, MOBILE]], [ // Google - /droid.+;\s(pixel c)[\s)]/i // Google Pixel C + /droid.+;\s(pixel\sc)[\s)]/i // Google Pixel C ], [MODEL, [VENDOR, 'Google'], [TYPE, TABLET]], [ /droid.+;\s(pixel[\s\daxl]{0,6})(?:\sbuild|\))/i // Google Pixel ], [MODEL, [VENDOR, 'Google'], [TYPE, MOBILE]], [ @@ -453,13 +451,14 @@ ], [[MODEL, 'Xperia Tablet'], [VENDOR, 'Sony'], [TYPE, TABLET]], [ // OnePlus + /\s(kb2005|in20[12]5|be20[12][59])\b/i, /\ba000(1)\s+build/i, // OnePlus /\boneplus\s(a\d{4})[\s)]/i ], [MODEL, [VENDOR, 'OnePlus'], [TYPE, MOBILE]], [ // Amazon /(alexa)webm/i, - /(kf[A-z]+)(\sbuild\/|\)).+silk\//i // Kindle Fire HD + /(kf[a-z]+)(\sbuild\/|\)).+silk\//i // Kindle Fire HD ], [MODEL, [VENDOR, 'Amazon'], [TYPE, TABLET]], [ /(sd|kf)[0349hijorstuw]+(\sbuild\/|\)).+silk\//i // Fire Phone ], [[MODEL, 'Fire Phone'], [VENDOR, 'Amazon'], [TYPE, MOBILE]], [ @@ -471,8 +470,10 @@ ], [MODEL, [VENDOR, 'BlackBerry'], [TYPE, MOBILE]], [ // Asus - /\b(transfo[prime\s]{4,10}\s\w+|eeepc|slider\s\w+|nexus 7|padfone|p00c)/i - ], [MODEL, [VENDOR, 'Asus'], [TYPE, TABLET]], [ + /\b(transfo[prime\s]{4,10}\s\w+|eeepc|slider\s\w+|nexus\s7|padfone|p00c)/i + ], [MODEL, [VENDOR, 'ASUS'], [TYPE, TABLET]], [ + /\s(z[es]6[027][01][km][ls]|zenfone\s\d\w?)\b/i + ], [MODEL, [VENDOR, 'ASUS'], [TYPE, MOBILE]], [ // HTC /(nexus\s9)/i // HTC Nexus 9 @@ -490,7 +491,7 @@ // Meizu /droid.+;\s(m[1-5]\snote)\sbuild/i, - /mz-([\w-]{2,})/i + /\bmz-([\w-]{2,})/i ], [MODEL, [VENDOR, 'Meizu'], [TYPE, MOBILE]], [ // MIXED @@ -511,9 +512,9 @@ /(kindle)\/([\w\.]+)/i, // Kindle /\s(nook)[\w\s]+build\/(\w+)/i, // Nook /(dell)\s(strea[kpr\s\d]*[\dko])/i, // Dell Streak - /[;\/]\s*(le[\s\-]+pan)[\s\-]+(\w{1,9})\s+build/i, // Le Pan Tablets - /[;\/]\s*(trinity)[\-\s]*(t\d{3})\s+build/i, // Trinity Tablets - /\b(gigaset)[\s\-]+(Q\w{1,9})\s+build/i, // Gigaset Tablets + /[;\/]\s?(le[\s\-]+pan)[\s\-]+(\w{1,9})\sbuild/i, // Le Pan Tablets + /[;\/]\s?(trinity)[\-\s]*(t\d{3})\sbuild/i, // Trinity Tablets + /\b(gigaset)[\s\-]+(q\w{1,9})\sbuild/i, // Gigaset Tablets /\b(vodafone)\s([\w\s]+)(?:\)|\sbuild)/i // Vodafone ], [VENDOR, MODEL, [TYPE, TABLET]], [ @@ -523,44 +524,44 @@ ], [MODEL, [VENDOR, 'AT&T'], [TYPE, MOBILE]], [ /sie-(\w*)/i // Siemens ], [MODEL, [VENDOR, 'Siemens'], [TYPE, MOBILE]], [ - /[;\/]\s*(rct[\d\w]+)\s+build/i // RCA Tablets + /[;\/]\s?(rct\w+)\sbuild/i // RCA Tablets ], [MODEL, [VENDOR, 'RCA'], [TYPE, TABLET]], [ - /[;\/\s](venue[\d\s]{2,7})\s+build/i // Dell Venue Tablets + /[;\/\s](venue[\d\s]{2,7})\sbuild/i // Dell Venue Tablets ], [MODEL, [VENDOR, 'Dell'], [TYPE, TABLET]], [ - /[;\/]\s*(q[t|m][\d\w]+)\s+build/i // Verizon Tablet + /[;\/]\s?(q(?:mv|ta)\w+)\sbuild/i // Verizon Tablet ], [MODEL, [VENDOR, 'Verizon'], [TYPE, TABLET]], [ - /[;\/]\s(?:barnes[&\s]+noble\s|bn[rt])([\w\s\+]*)\sbuild/i + /[;\/]\s(?:barnes[&\s]+noble\s|bn[rt])([\w\s\+]*)\sbuild/i // Barnes & Noble Tablet ], [MODEL, [VENDOR, 'Barnes & Noble'], [TYPE, TABLET]], [ - /[;\/]\s+(tm\d{3}.*\b)\s+build/i // Barnes & Noble Tablet + /[;\/]\s(tm\d{3}\w+)\sbuild/i ], [MODEL, [VENDOR, 'NuVision'], [TYPE, TABLET]], [ /;\s(k88)\sbuild/i // ZTE K Series Tablet ], [MODEL, [VENDOR, 'ZTE'], [TYPE, TABLET]], [ /;\s(nx\d{3}j)\sbuild/i // ZTE Nubia ], [MODEL, [VENDOR, 'ZTE'], [TYPE, MOBILE]], [ - /[;\/]\s*(gen\d{3})\s+build.*49h/i // Swiss GEN Mobile + /[;\/]\s?(gen\d{3})\sbuild.*49h/i // Swiss GEN Mobile ], [MODEL, [VENDOR, 'Swiss'], [TYPE, MOBILE]], [ - /[;\/]\s*(zur\d{3})\s+build/i // Swiss ZUR Tablet + /[;\/]\s?(zur\d{3})\sbuild/i // Swiss ZUR Tablet ], [MODEL, [VENDOR, 'Swiss'], [TYPE, TABLET]], [ - /[;\/]\s*((zeki)?tb.*\b)\s+build/i // Zeki Tablets + /[;\/]\s?((zeki)?tb.*\b)\sbuild/i // Zeki Tablets ], [MODEL, [VENDOR, 'Zeki'], [TYPE, TABLET]], [ - /[;\/]\s+([yr]\d{2})\s+build/i, - /[;\/]\s+(dragon[\-\s]+touch\s+|dt)(\w{5})\sbuild/i // Dragon Touch Tablet + /[;\/]\s([yr]\d{2})\sbuild/i, + /[;\/]\s(dragon[\-\s]+touch\s|dt)(\w{5})\sbuild/i // Dragon Touch Tablet ], [[VENDOR, 'Dragon Touch'], MODEL, [TYPE, TABLET]], [ - /[;\/]\s*(ns-?\w{0,9})\sbuild/i // Insignia Tablets + /[;\/]\s?(ns-?\w{0,9})\sbuild/i // Insignia Tablets ], [MODEL, [VENDOR, 'Insignia'], [TYPE, TABLET]], [ - /[;\/]\s*((nxa|Next)-?\w{0,9})\s+build/i // NextBook Tablets + /[;\/]\s?((nxa|Next)-?\w{0,9})\sbuild/i // NextBook Tablets ], [MODEL, [VENDOR, 'NextBook'], [TYPE, TABLET]], [ - /[;\/]\s*(xtreme\_)?(v(1[045]|2[015]|30|40|60|7[05]|90))\s+build/i + /[;\/]\s?(xtreme\_)?(v(1[045]|2[015]|[3469]0|7[05]))\sbuild/i ], [[VENDOR, 'Voice'], MODEL, [TYPE, MOBILE]], [ // Voice Xtreme Phones - /[;\/]\s*(lvtel\-)?(v1[12])\s+build/i // LvTel Phones + /[;\/]\s?(lvtel\-)?(v1[12])\sbuild/i // LvTel Phones ], [[VENDOR, 'LvTel'], MODEL, [TYPE, MOBILE]], [ - /;\s(PH-1)\s/i + /;\s(ph-1)\s/i ], [MODEL, [VENDOR, 'Essential'], [TYPE, MOBILE]], [ // Essential PH-1 - /[;\/]\s*(V(100md|700na|7011|917g).*\b)\s+build/i // Envizen Tablets + /[;\/]\s?(v(100md|700na|7011|917g).*\b)\sbuild/i // Envizen Tablets ], [MODEL, [VENDOR, 'Envizen'], [TYPE, TABLET]], [ - /[;\/]\s*(trio[\s\w\-\.]+)\s+build/i // MachSpeed Tablets + /[;\/]\s?(trio[\s\w\-\.]+)\sbuild/i // MachSpeed Tablets ], [MODEL, [VENDOR, 'MachSpeed'], [TYPE, TABLET]], [ - /[;\/]\s*tu_(1491)\s+build/i // Rotor Tablets + /[;\/]\s?tu_(1491)\sbuild/i // Rotor Tablets ], [MODEL, [VENDOR, 'Rotor'], [TYPE, TABLET]], [ /(shield[\w\s]+)\sbuild/i // Nvidia Shield Tablets ], [MODEL, [VENDOR, 'Nvidia'], [TYPE, TABLET]], [ @@ -568,7 +569,7 @@ ], [VENDOR, MODEL, [TYPE, MOBILE]], [ /(kin\.[onetw]{3})/i // Microsoft Kin ], [[MODEL, /\./g, ' '], [VENDOR, 'Microsoft'], [TYPE, MOBILE]], [ - /droid\s[\d\.]+;\s(cc6{3,4}|et5[16]|mc[239][23]x?|vc8[03]x?)\)/i // Zebra + /droid\s[\d\.]+;\s(cc6666?|et5[16]|mc[239][23]x?|vc8[03]x?)\)/i // Zebra ], [MODEL, [VENDOR, 'Zebra'], [TYPE, TABLET]], [ /droid\s[\d\.]+;\s(ec30|ps20|tc[2-8]\d[kx])\)/i ], [MODEL, [VENDOR, 'Zebra'], [TYPE, MOBILE]], [ @@ -654,7 +655,7 @@ /(icab)[\/\s]([23]\.[\d\.]+)/i // iCab ], [NAME, VERSION], [ - /rv\:([\w\.]{1,9}).+(gecko)/i // Gecko + /rv\:([\w\.]{1,9})\b.+(gecko)/i // Gecko ], [VERSION, NAME] ], @@ -671,7 +672,7 @@ ], [[NAME, 'Windows'], [VERSION, mapper.str, maps.os.windows.version]], [ // iOS/macOS - /ip[honead]{2,4}(?:.*os\s([\w]+)\slike\smac|;\sopera)/i, // iOS + /ip[honead]{2,4}\b(?:.*os\s([\w]+)\slike\smac|;\sopera)/i, // iOS /cfnetwork\/.+darwin/i ], [[VERSION, /_/g, '.'], [NAME, 'iOS']], [ /(mac\sos\sx)\s?([\w\s\.]*)/i, @@ -681,7 +682,7 @@ // Mobile OSes /(android|webos|palm\sos|qnx|bada|rim\stablet\sos|meego|sailfish|contiki)[\/\s-]?([\w\.]*)/i, // Android/WebOS/Palm/QNX/Bada/RIM/MeeGo/Contiki/Sailfish OS - /(blackberry)\w*\/?([\w\.]*)/i, // Blackberry + /(blackberry)\w*\/([\w\.]*)/i, // Blackberry /(tizen|kaios)[\/\s]([\w\.]+)/i // Tizen/KaiOS ], [NAME, VERSION], [ /\(bb(10);/i // BlackBerry 10 diff --git a/test/device-test.json b/test/device-test.json index b53721d..3a7da03 100644 --- a/test/device-test.json +++ b/test/device-test.json @@ -1,30 +1,129 @@ [{ - "desc": "Asus Nexus 7", + "desc": "ASUS Nexus 7", "ua": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 7 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.99 Safari/537.36", "expect": { - "vendor": "Asus", + "vendor": "ASUS", "model": "Nexus 7", "type": "tablet" } }, { - "desc": "Asus Padfone", + "desc": "ASUS Padfone", "ua": "Mozilla/5.0 (Linux; Android 4.1.1; PadFone 2 Build/JRO03L) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.117 Safari/537.36", "expect": { - "vendor": "Asus", + "vendor": "ASUS", "model": "PadFone", "type": "tablet" } }, { - "desc": "Asus ZenPad 10", + "desc": "ASUS ZenPad 10", "ua": "Mozilla/5.0 (Linux; Android 6.0; P00C Build/MRA58K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.76 Safari/537.36", "expect": { - "vendor": "Asus", + "vendor": "ASUS", "model": "P00C", "type": "tablet" } }, + { + "desc": "ASUS ROG", + "ua": "Mozilla/5.0 (Linux; Android 8.1; ZS600KL Build/OPM1.171019.026) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.126 Mobile Safari/537.36", + "expect": { + "vendor": "ASUS", + "model": "ZS600KL", + "type": "mobile" + } + }, + { + "desc": "ASUS ROG II", + "ua": "Mozilla/5.0 (Linux; Android 9; ASUS_I001DA Build/PKQ1.190414.001; xx-xx) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/74.0.3729.136 Mobile Safari/537.36", + "expect": { + "vendor": "ASUS", + "model": "I001DA", + "type": "mobile" + } + }, + { + "desc": "ASUS Zenfone 2", + "ua": "Mozilla/5.0 (Linux; Android 5.0; ASUS ZenFone 2 Build/LRX22C) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/37.0.0.0 Mobile Safari/537.36", + "expect": { + "vendor": "ASUS", + "model": "ZenFone 2", + "type": "mobile" + } + }, + { + "desc": "ASUS Zenfone 3 Deluxe", + "ua": "Mozilla/5.0 (Linux; Android 6.0; ASUS_Z016D Build/MXB48T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.132 Mobile Safari/537.36", + "expect": { + "vendor": "ASUS", + "model": "Z016D", + "type": "mobile" + } + }, + { + "desc": "ASUS Zenfone 5", + "ua": "Mozilla/5.0 (Linux; Android 8.0; ZE620KL Build/OPR1.170623.032) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.158 Mobile Safari/537.36", + "expect": { + "vendor": "ASUS", + "model": "ZE620KL", + "type": "mobile" + } + }, + { + "desc": "ASUS Zenfone 7", + "ua": "Mozilla/5.0 (Linux; Android 10; ASUS_I002D) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.81 Mobile Safari/537.36", + "expect": { + "vendor": "ASUS", + "model": "I002D", + "type": "mobile" + } + }, + { + "desc": "ASUS Zenfone 7 Pro", + "ua": "Mozilla/5.0 (Linux; Android 10; ZS671KS) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.72 Mobile Safari/537.36", + "expect": { + "vendor": "ASUS", + "model": "ZS671KS", + "type": "mobile" + } + }, + { + "desc": "ASUS Zenfone Max Pro (M1)", + "ua": "Mozilla/5.0 (Linux; Android 8.1; ASUS_X00TD Build/OPM1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.137 Mobile Safari/537.36", + "expect": { + "vendor": "ASUS", + "model": "X00TD", + "type": "mobile" + } + }, + { + "desc": "ASUS Zenfone Max M2", + "ua": "Mozilla/5.0 (Linux; Android 8.1; ASUS_X01AD) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.99 Mobile Safari/537.36", + "expect": { + "vendor": "ASUS", + "model": "X01AD", + "type": "mobile" + } + }, + { + "desc": "ASUS Zenfone Max Pro M2", + "ua": "Mozilla/5.0 (Linux; Android 8.1; ASUS_X01BDA) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.99 Mobile Safari/537.36", + "expect": { + "vendor": "ASUS", + "model": "X01BDA", + "type": "mobile" + } + }, + { + "desc": "ASUS Zenfone Go", + "ua": "Mozilla/5.0 (Linux; Android 6.0; ASUS_X009DA Build/MMB29M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36", + "expect": { + "vendor": "ASUS", + "model": "X009DA", + "type": "mobile" + } + }, { "desc": "Acer Iconia A1-810", "ua": "Mozilla/5.0 (Linux; Android 4.2.2; A1-810 Build/JDQ39) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.109 Safari/537.36", @@ -124,6 +223,15 @@ "type": "tablet" } }, + { + "desc": "iPad Air", + "ua": "Mozilla/5.0 (iPad; CPU OS 12_4_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 [FBAN/FBIOS;FBDV/iPad4,1;FBMD/iPad;FBSN/iOS;FBSV/12.4.5;FBSS/2;FBID/tablet;FBLC/en_US;FBOP/5;FBCR/]", + "expect": { + "vendor": "Apple", + "model": "iPad", + "type": "tablet" + } + }, { "desc": "iPod", "ua": "Mozilla/5.0 (iPod touch; CPU iPhone OS 7_0_4 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11B554a Safari/9537.53", @@ -160,6 +268,15 @@ "type": "tablet" } }, + { + "desc": "LG K500", + "ua": "Mozilla/5.0 (Linux; Android 6.0.1; LG-K500 Build/MMB29M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.111 Mobile Safari/537.36", + "expect": { + "vendor": "LG", + "model": "K500", + "type": "mobile" + } + }, { "desc": "LG Nexus 4", "ua": "Mozilla/5.0 (Linux; Android 4.2.1; Nexus 4 Build/JOP40D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Mobile Safari/535.19", @@ -289,7 +406,34 @@ } }, { - "desc": "Motorola Droid RAZR 4G", + "desc": "iPhone SE", + "ua": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 [FBAN/FBIOS;FBDV/iPhone8,4;FBMD/iPhone;FBSN/iOS;FBSV/13.3.1;FBSS/2;FBID/phone;FBLC/en_US;FBOP/5;FBCR/]", + "expect": { + "vendor": "Apple", + "model": "iPhone", + "type": "mobile" + } + }, + { + "desc": "iPhone 11 Pro Max", + "ua": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 [FBAN/FBIOS;FBDV/iPhone12,5;FBMD/iPhone;FBSN/iOS;FBSV/13.3.1;FBSS/3;FBID/phone;FBLC/en_US;FBOP/5;FBCR/]", + "expect": { + "vendor": "Apple", + "model": "iPhone", + "type": "mobile" + } + }, + { + "desc": "iPhone XS", + "ua": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 [FBAN/FBIOS;FBDV/iPhone11,2;FBMD/iPhone;FBSN/iOS;FBSV/13.3.1;FBSS/3;FBID/phone;FBLC/en_US;FBOP/5;FBCR/]", + "expect": { + "vendor": "Apple", + "model": "iPhone", + "type": "mobile" + } + }, + { + "desc": "iPod touch", "ua": "Mozilla/5.0 (iPod touch; CPU iPhone OS 7_0_2 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A501 Safari/9537.53", "expect": { "vendor": "Apple", @@ -405,6 +549,42 @@ "type": "mobile" } }, + { + "desc": "OnePlus 8T", + "ua": "Mozilla/5.0 (Linux; Android 11; KB2005) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.127 Mobile Safari/537.36", + "expect": { + "vendor": "OnePlus", + "model": "KB2005", + "type": "mobile" + } + }, + { + "desc": "OnePlus 8 Pro", + "ua": "Mozilla/5.0 (Linux; Android 10; IN2025) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.119 Mobile Safari/537.36", + "expect": { + "vendor": "OnePlus", + "model": "IN2025", + "type": "mobile" + } + }, + { + "desc": "OnePlus Nord N100", + "ua": "Mozilla/5.0 (Linux; Android 10; BE2015 Build/QKQ1.200719.002; xx-xx) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/83.0.4103.106 Mobile Safari/537.36", + "expect": { + "vendor": "OnePlus", + "model": "BE2015", + "type": "mobile" + } + }, + { + "desc": "OnePlus Nord N10 5G", + "ua": "Mozilla/5.0 (Linux; Android 10; BE2029) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.185 Mobile Safari/537.36", + "expect": { + "vendor": "OnePlus", + "model": "BE2029", + "type": "mobile" + } + }, { "desc": "OPPO Neo", "ua": "Mozilla/5.0 (Linux; U; Android 4.2.2; zh-cn; R831T Build/JDQ39) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 OppoBrowser/3.3.2 Mobile Safari/534.30", @@ -423,6 +603,87 @@ "type": "mobile" } }, + { + "desc": "OPPO A3s", + "ua": "Mozilla/5.0 (Linux; Android 8.1; CPH1803 Build/OPM1.171019.026; xx-xx) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 Mobile Safari/537.36", + "expect": { + "vendor": "OPPO", + "model": "CPH1803", + "type": "mobile" + } + }, + { + "desc": "OPPO A12", + "ua": "Mozilla/5.0 (Linux; Android 9; CPH2083) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.116 Mobile Safari/537.36", + "expect": { + "vendor": "OPPO", + "model": "CPH2083", + "type": "mobile" + } + }, + { + "desc": "OPPO Reno", + "ua": "Mozilla/5.0 (Linux; Android 9; PCAT00 Build/PKQ1.190101.001; xx-xx) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/70.0.3538.110 Mobile Safari/537.36", + "expect": { + "vendor": "OPPO", + "model": "PCAT00", + "type": "mobile" + } + }, + { + "desc": "OPPO Reno3 Pro 5G", + "ua": "Mozilla/5.0 (Linux; Android 10; PCLM50) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.117 Mobile Safari/537.36", + "expect": { + "vendor": "OPPO", + "model": "PCLM50", + "type": "mobile" + } + }, + { + "desc": "OPPO Reno4 SE", + "ua": "Mozilla/5.0 (Linux; U; Android 10; xx-xx; PEAM00 Build/QP1A.190711.020) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/70.0.3538.80 Mobile Safari/537.36", + "expect": { + "vendor": "OPPO", + "model": "PEAM00", + "type": "mobile" + } + }, + { + "desc": "OPPO Reno4 5G", + "ua": "Mozilla/5.0 (Linux; Android 10; PDPM00 Build/QKQ1.200216.002; xx-xx) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/76.0.3809.89 Mobile Safari/537.36", + "expect": { + "vendor": "OPPO", + "model": "PDPM00", + "type": "mobile" + } + }, + { + "desc": "OPPO Reno4 Pro 5G", + "ua": "Mozilla/5.0 (Linux; U; Android 10; xx-xx; PDNT00 Build/QKQ1.200216.002) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/70.0.3538.80 Mobile Safari/537.36", + "expect": { + "vendor": "OPPO", + "model": "PDNT00", + "type": "mobile" + } + }, + { + "desc": "OPPO Find X", + "ua": "Mozilla/5.0 (Linux; Android 8.1; PAFM00 Build/OPM1.171019.026) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Mobile Safari/537.36", + "expect": { + "vendor": "OPPO", + "model": "PAFM00", + "type": "mobile" + } + }, + { + "desc": "OPPO Find 7a", + "ua": "Mozilla/5.0 (Linux; U; Android 4.3; xx-xx; X9007 Build/JLS36C) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30", + "expect": { + "vendor": "OPPO", + "model": "X9007", + "type": "mobile" + } + }, { "desc": "Philips SmartTV", "ua": "Opera/9.80 HbbTV/1.1.1 (; Philips; ; ; ; ) NETTV/4.0.2; en) Version/11.60", @@ -450,6 +711,24 @@ "type": "tablet" } }, + { + "desc": "Samsung Galaxy A21s", + "ua": "Mozilla/5.0 (Linux; Android 10; SAMSUNG SM-A217F) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/11.0 Chrome/75.0.3770.143 Mobile Safari/537.36", + "expect": { + "vendor": "Samsung", + "model": "SM-A217F", + "type": "mobile" + } + }, + { + "desc": "Samsung Galaxy A31", + "ua": "Mozilla/5.0 (Linux; Android 10; SM-A315G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Mobile Safari/537.36", + "expect": { + "vendor": "Samsung", + "model": "SM-A315G", + "type": "mobile" + } + }, { "desc": "Samsung Galaxy A50", "ua": "Mozilla/5.0 (Linux; Android 9; SM-A505F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.105 Mobile Safari/537.36", @@ -532,7 +811,16 @@ } }, { - "desc": "Samsung SM-T700", + "desc": "Samsung Galaxy Tab S7", + "ua": "Mozilla/5.0 (Linux; Android 10; SM-T870) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36", + "expect": { + "vendor": "Samsung", + "model": "SM-T870", + "type": "tablet" + } + }, + { + "desc": "Samsung Galaxy Tab S", "ua": "Mozilla/5.0 (Linux; Android 4.4.2; SM-T700 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.135 Safari/537.36", "expect": { "vendor": "Samsung", @@ -541,7 +829,7 @@ } }, { - "desc": "Samsung SM-T520", + "desc": "Samsung Galaxy Tab Pro 10.1", "ua": "Mozilla/5.0 (Linux; Android 4.4.2; SM-T520 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.135 Safari/537.36", "expect": { "vendor": "Samsung", @@ -1152,6 +1440,15 @@ "type": "mobile" } }, + { + "desc": "Google Pixel 4a", + "ua": "Mozilla/5.0 (Linux; Android 10; Pixel 4a) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.83 Mobile Safari/537.36", + "expect": { + "vendor": "Google", + "model": "Pixel 4a", + "type": "mobile" + } + }, { "desc": "Google Pixel 4 XL", "ua": "Mozilla/5.0 (Linux; Android 10; Pixel 4 XL) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Mobile Safari/537.36", @@ -1161,6 +1458,15 @@ "type": "mobile" } }, + { + "desc": "Google Pixel 5", + "ua": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.120 Mobile Safari/537.36", + "expect": { + "vendor": "Google", + "model": "Pixel 5", + "type": "mobile" + } + }, { "desc": "Generic Android Device", "ua": "Mozilla/5.0 (Linux; U; Android 6.0.1; i980 Build/MRA58K)",