From c9d008e97af92aa860f3361964e1fb0e485fca34 Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Sat, 21 Jun 2025 21:41:00 +0700 Subject: [PATCH] Bump version `2.0.4` --- CHANGELOG.md | 21 ++ dist/ua-parser.min.js | 4 +- dist/ua-parser.min.mjs | 4 +- dist/ua-parser.pack.js | 4 +- dist/ua-parser.pack.mjs | 4 +- package-lock.json | 4 +- package.json | 2 +- src/enums/ua-parser-enums.d.ts | 2 +- src/enums/ua-parser-enums.js | 2 +- src/enums/ua-parser-enums.mjs | 14 +- src/extensions/ua-parser-extensions.d.ts | 2 +- src/extensions/ua-parser-extensions.js | 2 +- src/extensions/ua-parser-extensions.mjs | 68 +++++-- src/helpers/ua-parser-helpers.d.ts | 2 +- src/helpers/ua-parser-helpers.js | 2 +- src/helpers/ua-parser-helpers.mjs | 5 +- src/main/ua-parser.d.ts | 2 +- src/main/ua-parser.js | 4 +- src/main/ua-parser.mjs | 237 +++++++++++++---------- 19 files changed, 251 insertions(+), 134 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f2fa9b..d1f9ac6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -65,6 +65,27 @@ --- +## Version 2.0.4 + +- Add new browser: Edge WebView, Edge WebView2 +- Add new device vendor: Lava, Retroid, Vizio +- Add new OS: ArcaOS, Knoppix, Xubuntu, Windows CE, Windows RT +- Improve device detection: Google Pixel & Pixelbook Series, HMD, Infinix, LG WebOS TV, Motorola, Nothing, OnePlus, Sony, Tecno +- Improve OS detection: AIX, Arch, Fuchsia, Haiku, HarmonyOS, Mint, MorphOS, Solaris, Windows +- Improve `withClientHints()` browser naming adjustments: `Microsoft Edge WebView2` => `Edge WebView2` +- Identify device that uses Firefox Reality / Wolvic as `xr` +- Identify device with large screen as `smarttv` +- Identify Windows CE & Windows RT as distinct OS variants +- `extensions` submodule: + - Remove lookbehind assertion to ensure regex compatibility + - Add new crawlers: ChatGLM, Daum, iAskBot, Onespot, Qwantbot, Startpage + - Add new emails: Apple's Mail, DaumMail, Polymail, ProtonMail, SparkDesktop, Zimbra, ZohoMail-Desktop + - Add new fetchers: Iframely, MistralAI-User, Perplexity-User + - Add new inApps: Discord, Evernote, Figma, Flipboard, Mattermost, Notion, Postman, Rambox, Rocket.Chat, Microsoft Teams, TikTok Lite, VS Code + - Add new libraries: AdobeAIR, aiohttp, nutch, httpx, urllib3 +- `enum` submodule: + - Fix mistakenly placed `BLU` categorized as browser name instead of device vendor + ## Version 2.0.3 - Add new browser: Dooble, Ecosia, LG Browser, Otter, qutebrowser, Surf diff --git a/dist/ua-parser.min.js b/dist/ua-parser.min.js index 0c7f407..7d65516 100644 --- a/dist/ua-parser.min.js +++ b/dist/ua-parser.min.js @@ -1,4 +1,4 @@ -/* UAParser.js v2.0.3 +/* UAParser.js v2.0.4 Copyright © 2012-2025 Faisal Salman AGPLv3 License */ -(function(window,undefined){"use strict";var LIBVERSION="2.0.3",UA_MAX_LENGTH=500,USER_AGENT="user-agent",EMPTY="",UNKNOWN="?",FUNC_TYPE="function",UNDEF_TYPE="undefined",OBJ_TYPE="object",STR_TYPE="string",UA_BROWSER="browser",UA_CPU="cpu",UA_DEVICE="device",UA_ENGINE="engine",UA_OS="os",UA_RESULT="result",NAME="name",TYPE="type",VENDOR="vendor",VERSION="version",ARCHITECTURE="architecture",MAJOR="major",MODEL="model",CONSOLE="console",MOBILE="mobile",TABLET="tablet",SMARTTV="smarttv",WEARABLE="wearable",XR="xr",EMBEDDED="embedded",INAPP="inapp",BRANDS="brands",FORMFACTORS="formFactors",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_FORM_FACTORS=CH_HEADER+"-form-factors",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,FULLVERLIST,MOBILE,MODEL,PLATFORM,PLATFORMVER,ARCHITECTURE,FORMFACTORS,BITNESS],AMAZON="Amazon",APPLE="Apple",ASUS="ASUS",BLACKBERRY="BlackBerry",GOOGLE="Google",HUAWEI="Huawei",LENOVO="Lenovo",HONOR="Honor",LG="LG",MICROSOFT="Microsoft",MOTOROLA="Motorola",NVIDIA="Nvidia",ONEPLUS="OnePlus",OPPO="OPPO",SAMSUNG="Samsung",SHARP="Sharp",SONY="Sony",XIAOMI="Xiaomi",ZEBRA="Zebra",CHROME="Chrome",CHROMIUM="Chromium",CHROMECAST="Chromecast",EDGE="Edge",FIREFOX="Firefox",OPERA="Opera",FACEBOOK="Facebook",SOGOU="Sogou",PREFIX_MOBILE="Mobile ",SUFFIX_BROWSER=" Browser",WINDOWS="Windows";var isWindow=typeof window!==UNDEF_TYPE,NAVIGATOR=isWindow&&window.navigator?window.navigator:undefined,NAVIGATOR_UADATA=NAVIGATOR&&NAVIGATOR.userAgentData?NAVIGATOR.userAgentData:undefined;var extend=function(defaultRgx,extensions){var mergedRgx={};var extraRgx=extensions;if(!isExtensions(extensions)){extraRgx={};for(var i in extensions){for(var j in extensions[i]){extraRgx[j]=extensions[i][j].concat(extraRgx[j]?extraRgx[j]:[])}}}for(var k in defaultRgx){mergedRgx[k]=extraRgx[k]&&extraRgx[k].length%2===0?extraRgx[k].concat(defaultRgx[k]):defaultRgx[k]}return mergedRgx},enumerize=function(arr){var enums={};for(var i=0;i0){for(var i in str1){if(lowerize(str1[i])==lowerize(str2))return true}return false}return isString(str1)?lowerize(str2).indexOf(lowerize(str1))!==-1:false},isExtensions=function(obj,deep){for(var prop in obj){return/^(browser|cpu|device|engine|os)$/.test(prop)||(deep?isExtensions(obj[prop]):false)}},isString=function(val){return typeof val===STR_TYPE},itemListToArray=function(header){if(!header)return undefined;var arr=[];var tokens=strip(/\\?\"/g,header).split(",");for(var i=0;i-1){var token=trim(tokens[i]).split(";v=");arr[i]={brand:token[0],version:token[1]}}else{arr[i]=trim(tokens[i])}}return arr},lowerize=function(str){return isString(str)?str.toLowerCase():str},majorize=function(version){return isString(version)?strip(/[^\d\.]/g,version).split(".")[0]:undefined},setProps=function(arr){for(var i in arr){var propName=arr[i];if(typeof propName==OBJ_TYPE&&propName.length==2){this[propName[0]]=propName[1]}else{this[propName]=undefined}}return this},strip=function(pattern,str){return isString(str)?str.replace(pattern,EMPTY):str},stripQuotes=function(str){return strip(/\\?\"/g,str)},trim=function(str,len){if(isString(str)){str=strip(/^\s\s*/,str);return typeof len===UNDEF_TYPE?str:str.substring(0,UA_MAX_LENGTH)}};var rgxMapper=function(ua,arrays){if(!ua||!arrays)return;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}},strMapper=function(str,map){for(var i in map){if(typeof map[i]===OBJ_TYPE&&map[i].length>0){for(var j=0;j2){this.set(MODEL,"iPad").set(TYPE,TABLET)}break;case UA_OS:if(!this.get(NAME)&&NAVIGATOR_UADATA&&NAVIGATOR_UADATA[PLATFORM]){this.set(NAME,NAVIGATOR_UADATA[PLATFORM])}break;case UA_RESULT:var data=this.data;var detect=function(itemType){return data[itemType].getItem().detectFeature().get()};this.set(UA_BROWSER,detect(UA_BROWSER)).set(UA_CPU,detect(UA_CPU)).set(UA_DEVICE,detect(UA_DEVICE)).set(UA_ENGINE,detect(UA_ENGINE)).set(UA_OS,detect(UA_OS))}}return this};this.parseUA=function(){if(this.itemType!=UA_RESULT){rgxMapper.call(this.data,this.ua,this.rgxMap)}if(this.itemType==UA_BROWSER){this.set(MAJOR,majorize(this.get(VERSION)))}return this};this.parseCH=function(){var uaCH=this.uaCH,rgxMap=this.rgxMap;switch(this.itemType){case UA_BROWSER:case UA_ENGINE:var brands=uaCH[FULLVERLIST]||uaCH[BRANDS],prevName;if(brands){for(var i in brands){var brandName=brands[i].brand||brands[i],brandVersion=brands[i].version;if(this.itemType==UA_BROWSER&&!/not.a.brand/i.test(brandName)&&(!prevName||/chrom/i.test(prevName)&&brandName!=CHROMIUM)){brandName=strMapper(brandName,{Chrome:"Google Chrome",Edge:"Microsoft Edge","Chrome WebView":"Android WebView","Chrome Headless":"HeadlessChrome","Huawei Browser":"HuaweiBrowser","MIUI Browser":"Miui Browser","Opera Mobi":"OperaMobile",Yandex:"YaBrowser"});this.set(NAME,brandName).set(VERSION,brandVersion).set(MAJOR,majorize(brandVersion));prevName=brandName}if(this.itemType==UA_ENGINE&&brandName==CHROMIUM){this.set(VERSION,brandVersion)}}}break;case UA_CPU:var archName=uaCH[ARCHITECTURE];if(archName){if(archName&&uaCH[BITNESS]=="64")archName+="64";rgxMapper.call(this.data,archName+";",rgxMap)}break;case UA_DEVICE:if(uaCH[MOBILE]){this.set(TYPE,MOBILE)}if(uaCH[MODEL]){this.set(MODEL,uaCH[MODEL]);if(!this.get(TYPE)||!this.get(VENDOR)){var reParse={};rgxMapper.call(reParse,"droid 9; "+uaCH[MODEL]+")",rgxMap);if(!this.get(TYPE)&&!!reParse.type){this.set(TYPE,reParse.type)}if(!this.get(VENDOR)&&!!reParse.vendor){this.set(VENDOR,reParse.vendor)}}}if(uaCH[FORMFACTORS]){var ff;if(typeof uaCH[FORMFACTORS]!=="string"){var idx=0;while(!ff&&idx=13?"11":"10";this.set(NAME,osName).set(VERSION,osVersion)}if(this.get(NAME)==WINDOWS&&uaCH[MODEL]=="Xbox"){this.set(NAME,"Xbox").set(VERSION,undefined)}break;case UA_RESULT:var data=this.data;var parse=function(itemType){return data[itemType].getItem().setCH(uaCH).parseCH().get()};this.set(UA_BROWSER,parse(UA_BROWSER)).set(UA_CPU,parse(UA_CPU)).set(UA_DEVICE,parse(UA_DEVICE)).set(UA_ENGINE,parse(UA_ENGINE)).set(UA_OS,parse(UA_OS))}return this};setProps.call(this,[["itemType",itemType],["ua",ua],["uaCH",uaCH],["rgxMap",rgxMap],["data",createIData(this,itemType)]]);return this}function UAParser(ua,extensions,headers){if(typeof ua===OBJ_TYPE){if(isExtensions(ua,true)){if(typeof extensions===OBJ_TYPE){headers=extensions}extensions=ua}else{headers=ua;extensions=undefined}ua=undefined}else if(typeof ua===STR_TYPE&&!isExtensions(extensions,true)){headers=extensions;extensions=undefined}if(headers&&typeof headers.append===FUNC_TYPE){var kv={};headers.forEach(function(v,k){kv[k]=v});headers=kv}if(!(this instanceof UAParser)){return new UAParser(ua,extensions,headers).getResult()}var userAgent=typeof ua===STR_TYPE?ua:headers&&headers[USER_AGENT]?headers[USER_AGENT]:NAVIGATOR&&NAVIGATOR.userAgent?NAVIGATOR.userAgent:EMPTY,httpUACH=new UACHData(headers,true),regexMap=extensions?extend(defaultRegexes,extensions):defaultRegexes,createItemFunc=function(itemType){if(itemType==UA_RESULT){return function(){return new UAItem(itemType,userAgent,regexMap,httpUACH).set("ua",userAgent).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()}}else{return function(){return new UAItem(itemType,userAgent,regexMap[itemType],httpUACH).parseUA().get()}}};setProps.call(this,[["getBrowser",createItemFunc(UA_BROWSER)],["getCPU",createItemFunc(UA_CPU)],["getDevice",createItemFunc(UA_DEVICE)],["getEngine",createItemFunc(UA_ENGINE)],["getOS",createItemFunc(UA_OS)],["getResult",createItemFunc(UA_RESULT)],["getUA",function(){return userAgent}],["setUA",function(ua){if(isString(ua))userAgent=ua.length>UA_MAX_LENGTH?trim(ua,UA_MAX_LENGTH):ua;return this}]]).setUA(userAgent);return this}UAParser.VERSION=LIBVERSION;UAParser.BROWSER=enumerize([NAME,VERSION,MAJOR,TYPE]);UAParser.CPU=enumerize([ARCHITECTURE]);UAParser.DEVICE=enumerize([MODEL,VENDOR,TYPE,CONSOLE,MOBILE,SMARTTV,TABLET,WEARABLE,EMBEDDED]);UAParser.ENGINE=UAParser.OS=enumerize([NAME,VERSION]);if(typeof exports!==UNDEF_TYPE){if(typeof module!==UNDEF_TYPE&&module.exports){exports=module.exports=UAParser}exports.UAParser=UAParser}else{if(typeof define===FUNC_TYPE&&define.amd){define(function(){return UAParser})}else if(isWindow){window.UAParser=UAParser}}var $=isWindow&&(window.jQuery||window.Zepto);if($&&!$.ua){var parser=new UAParser;$.ua=parser.getResult();$.ua.get=function(){return parser.getUA()};$.ua.set=function(ua){parser.setUA(ua);var result=parser.getResult();for(var prop in result){$.ua[prop]=result[prop]}}}})(typeof window==="object"?window:this); \ No newline at end of file +(function(window,undefined){"use strict";var LIBVERSION="2.0.4",UA_MAX_LENGTH=500,USER_AGENT="user-agent",EMPTY="",UNKNOWN="?",FUNC_TYPE="function",UNDEF_TYPE="undefined",OBJ_TYPE="object",STR_TYPE="string",UA_BROWSER="browser",UA_CPU="cpu",UA_DEVICE="device",UA_ENGINE="engine",UA_OS="os",UA_RESULT="result",NAME="name",TYPE="type",VENDOR="vendor",VERSION="version",ARCHITECTURE="architecture",MAJOR="major",MODEL="model",CONSOLE="console",MOBILE="mobile",TABLET="tablet",SMARTTV="smarttv",WEARABLE="wearable",XR="xr",EMBEDDED="embedded",INAPP="inapp",BRANDS="brands",FORMFACTORS="formFactors",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_FORM_FACTORS=CH_HEADER+"-form-factors",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,FULLVERLIST,MOBILE,MODEL,PLATFORM,PLATFORMVER,ARCHITECTURE,FORMFACTORS,BITNESS],AMAZON="Amazon",APPLE="Apple",ASUS="ASUS",BLACKBERRY="BlackBerry",GOOGLE="Google",HUAWEI="Huawei",LENOVO="Lenovo",HONOR="Honor",LG="LG",MICROSOFT="Microsoft",MOTOROLA="Motorola",NVIDIA="Nvidia",ONEPLUS="OnePlus",OPPO="OPPO",SAMSUNG="Samsung",SHARP="Sharp",SONY="Sony",XIAOMI="Xiaomi",ZEBRA="Zebra",CHROME="Chrome",CHROMIUM="Chromium",CHROMECAST="Chromecast",EDGE="Edge",FIREFOX="Firefox",OPERA="Opera",FACEBOOK="Facebook",SOGOU="Sogou",PREFIX_MOBILE="Mobile ",SUFFIX_BROWSER=" Browser",WINDOWS="Windows";var isWindow=typeof window!==UNDEF_TYPE,NAVIGATOR=isWindow&&window.navigator?window.navigator:undefined,NAVIGATOR_UADATA=NAVIGATOR&&NAVIGATOR.userAgentData?NAVIGATOR.userAgentData:undefined;var extend=function(defaultRgx,extensions){var mergedRgx={};var extraRgx=extensions;if(!isExtensions(extensions)){extraRgx={};for(var i in extensions){for(var j in extensions[i]){extraRgx[j]=extensions[i][j].concat(extraRgx[j]?extraRgx[j]:[])}}}for(var k in defaultRgx){mergedRgx[k]=extraRgx[k]&&extraRgx[k].length%2===0?extraRgx[k].concat(defaultRgx[k]):defaultRgx[k]}return mergedRgx},enumerize=function(arr){var enums={};for(var i=0;i0){for(var i in str1){if(lowerize(str2)==lowerize(str1[i]))return true}return false}return isString(str1)?lowerize(str2)==lowerize(str1):false},isExtensions=function(obj,deep){for(var prop in obj){return/^(browser|cpu|device|engine|os)$/.test(prop)||(deep?isExtensions(obj[prop]):false)}},isString=function(val){return typeof val===STR_TYPE},itemListToArray=function(header){if(!header)return undefined;var arr=[];var tokens=strip(/\\?\"/g,header).split(",");for(var i=0;i-1){var token=trim(tokens[i]).split(";v=");arr[i]={brand:token[0],version:token[1]}}else{arr[i]=trim(tokens[i])}}return arr},lowerize=function(str){return isString(str)?str.toLowerCase():str},majorize=function(version){return isString(version)?strip(/[^\d\.]/g,version).split(".")[0]:undefined},setProps=function(arr){for(var i in arr){var propName=arr[i];if(typeof propName==OBJ_TYPE&&propName.length==2){this[propName[0]]=propName[1]}else{this[propName]=undefined}}return this},strip=function(pattern,str){return isString(str)?str.replace(pattern,EMPTY):str},stripQuotes=function(str){return strip(/\\?\"/g,str)},trim=function(str,len){if(isString(str)){str=strip(/^\s\s*/,str);return typeof len===UNDEF_TYPE?str:str.substring(0,UA_MAX_LENGTH)}};var rgxMapper=function(ua,arrays){if(!ua||!arrays)return;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)){if(q.length>3){this[q[0]]=match?q[1].apply(this,q.slice(2)):undefined}else{this[q[0]]=match?q[1].call(this,match,q[2]):undefined}}else{if(q.length==3){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 if(q.length>4){this[q[0]]=match?q[3].apply(this,[match.replace(q[1],q[2])].concat(q.slice(4))):undefined}}}}else{this[q]=match?match:undefined}}}}i+=2}},strMapper=function(str,map){for(var i in map){if(typeof map[i]===OBJ_TYPE&&map[i].length>0){for(var j=0;j2){this.set(MODEL,"iPad").set(TYPE,TABLET)}break;case UA_OS:if(!this.get(NAME)&&NAVIGATOR_UADATA&&NAVIGATOR_UADATA[PLATFORM]){this.set(NAME,NAVIGATOR_UADATA[PLATFORM])}break;case UA_RESULT:var data=this.data;var detect=function(itemType){return data[itemType].getItem().detectFeature().get()};this.set(UA_BROWSER,detect(UA_BROWSER)).set(UA_CPU,detect(UA_CPU)).set(UA_DEVICE,detect(UA_DEVICE)).set(UA_ENGINE,detect(UA_ENGINE)).set(UA_OS,detect(UA_OS))}}return this};this.parseUA=function(){if(this.itemType!=UA_RESULT){rgxMapper.call(this.data,this.ua,this.rgxMap)}if(this.itemType==UA_BROWSER){this.set(MAJOR,majorize(this.get(VERSION)))}return this};this.parseCH=function(){var uaCH=this.uaCH,rgxMap=this.rgxMap;switch(this.itemType){case UA_BROWSER:case UA_ENGINE:var brands=uaCH[FULLVERLIST]||uaCH[BRANDS],prevName;if(brands){for(var i in brands){var brandName=brands[i].brand||brands[i],brandVersion=brands[i].version;if(this.itemType==UA_BROWSER&&!/not.a.brand/i.test(brandName)&&(!prevName||/Chrom/.test(prevName)&&brandName!=CHROMIUM||prevName==EDGE&&/WebView2/.test(brandName))){brandName=strMapper(brandName,browserHintsMap);prevName=this.get(NAME);if(!(prevName&&!/Chrom/.test(prevName)&&/Chrom/.test(brandName))){this.set(NAME,brandName).set(VERSION,brandVersion).set(MAJOR,majorize(brandVersion))}prevName=brandName}if(this.itemType==UA_ENGINE&&brandName==CHROMIUM){this.set(VERSION,brandVersion)}}}break;case UA_CPU:var archName=uaCH[ARCHITECTURE];if(archName){if(archName&&uaCH[BITNESS]=="64")archName+="64";rgxMapper.call(this.data,archName+";",rgxMap)}break;case UA_DEVICE:if(uaCH[MOBILE]){this.set(TYPE,MOBILE)}if(uaCH[MODEL]){this.set(MODEL,uaCH[MODEL]);if(!this.get(TYPE)||!this.get(VENDOR)){var reParse={};rgxMapper.call(reParse,"droid 9; "+uaCH[MODEL]+")",rgxMap);if(!this.get(TYPE)&&!!reParse.type){this.set(TYPE,reParse.type)}if(!this.get(VENDOR)&&!!reParse.vendor){this.set(VENDOR,reParse.vendor)}}}if(uaCH[FORMFACTORS]){var ff;if(typeof uaCH[FORMFACTORS]!=="string"){var idx=0;while(!ff&&idx=13?"11":"10";this.set(NAME,osName).set(VERSION,osVersion)}if(this.get(NAME)==WINDOWS&&uaCH[MODEL]=="Xbox"){this.set(NAME,"Xbox").set(VERSION,undefined)}break;case UA_RESULT:var data=this.data;var parse=function(itemType){return data[itemType].getItem().setCH(uaCH).parseCH().get()};this.set(UA_BROWSER,parse(UA_BROWSER)).set(UA_CPU,parse(UA_CPU)).set(UA_DEVICE,parse(UA_DEVICE)).set(UA_ENGINE,parse(UA_ENGINE)).set(UA_OS,parse(UA_OS))}return this};setProps.call(this,[["itemType",itemType],["ua",ua],["uaCH",uaCH],["rgxMap",rgxMap],["data",createIData(this,itemType)]]);return this}function UAParser(ua,extensions,headers){if(typeof ua===OBJ_TYPE){if(isExtensions(ua,true)){if(typeof extensions===OBJ_TYPE){headers=extensions}extensions=ua}else{headers=ua;extensions=undefined}ua=undefined}else if(typeof ua===STR_TYPE&&!isExtensions(extensions,true)){headers=extensions;extensions=undefined}if(headers&&typeof headers.append===FUNC_TYPE){var kv={};headers.forEach(function(v,k){kv[k]=v});headers=kv}if(!(this instanceof UAParser)){return new UAParser(ua,extensions,headers).getResult()}var userAgent=typeof ua===STR_TYPE?ua:headers&&headers[USER_AGENT]?headers[USER_AGENT]:NAVIGATOR&&NAVIGATOR.userAgent?NAVIGATOR.userAgent:EMPTY,httpUACH=new UACHData(headers,true),regexMap=extensions?extend(defaultRegexes,extensions):defaultRegexes,createItemFunc=function(itemType){if(itemType==UA_RESULT){return function(){return new UAItem(itemType,userAgent,regexMap,httpUACH).set("ua",userAgent).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()}}else{return function(){return new UAItem(itemType,userAgent,regexMap[itemType],httpUACH).parseUA().get()}}};setProps.call(this,[["getBrowser",createItemFunc(UA_BROWSER)],["getCPU",createItemFunc(UA_CPU)],["getDevice",createItemFunc(UA_DEVICE)],["getEngine",createItemFunc(UA_ENGINE)],["getOS",createItemFunc(UA_OS)],["getResult",createItemFunc(UA_RESULT)],["getUA",function(){return userAgent}],["setUA",function(ua){if(isString(ua))userAgent=ua.length>UA_MAX_LENGTH?trim(ua,UA_MAX_LENGTH):ua;return this}]]).setUA(userAgent);return this}UAParser.VERSION=LIBVERSION;UAParser.BROWSER=enumerize([NAME,VERSION,MAJOR,TYPE]);UAParser.CPU=enumerize([ARCHITECTURE]);UAParser.DEVICE=enumerize([MODEL,VENDOR,TYPE,CONSOLE,MOBILE,SMARTTV,TABLET,WEARABLE,EMBEDDED]);UAParser.ENGINE=UAParser.OS=enumerize([NAME,VERSION]);if(typeof exports!==UNDEF_TYPE){if(typeof module!==UNDEF_TYPE&&module.exports){exports=module.exports=UAParser}exports.UAParser=UAParser}else{if(typeof define===FUNC_TYPE&&define.amd){define(function(){return UAParser})}else if(isWindow){window.UAParser=UAParser}}var $=isWindow&&(window.jQuery||window.Zepto);if($&&!$.ua){var parser=new UAParser;$.ua=parser.getResult();$.ua.get=function(){return parser.getUA()};$.ua.set=function(ua){parser.setUA(ua);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.min.mjs b/dist/ua-parser.min.mjs index b86273f..3cb0831 100644 --- a/dist/ua-parser.min.mjs +++ b/dist/ua-parser.min.mjs @@ -1,4 +1,4 @@ -/* UAParser.js v2.0.3 +/* UAParser.js v2.0.4 Copyright © 2012-2025 Faisal Salman AGPLv3 License */ -var LIBVERSION="2.0.3",UA_MAX_LENGTH=500,USER_AGENT="user-agent",EMPTY="",UNKNOWN="?",FUNC_TYPE="function",UNDEF_TYPE="undefined",OBJ_TYPE="object",STR_TYPE="string",UA_BROWSER="browser",UA_CPU="cpu",UA_DEVICE="device",UA_ENGINE="engine",UA_OS="os",UA_RESULT="result",NAME="name",TYPE="type",VENDOR="vendor",VERSION="version",ARCHITECTURE="architecture",MAJOR="major",MODEL="model",CONSOLE="console",MOBILE="mobile",TABLET="tablet",SMARTTV="smarttv",WEARABLE="wearable",XR="xr",EMBEDDED="embedded",INAPP="inapp",BRANDS="brands",FORMFACTORS="formFactors",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_FORM_FACTORS=CH_HEADER+"-form-factors",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,FULLVERLIST,MOBILE,MODEL,PLATFORM,PLATFORMVER,ARCHITECTURE,FORMFACTORS,BITNESS],AMAZON="Amazon",APPLE="Apple",ASUS="ASUS",BLACKBERRY="BlackBerry",GOOGLE="Google",HUAWEI="Huawei",LENOVO="Lenovo",HONOR="Honor",LG="LG",MICROSOFT="Microsoft",MOTOROLA="Motorola",NVIDIA="Nvidia",ONEPLUS="OnePlus",OPPO="OPPO",SAMSUNG="Samsung",SHARP="Sharp",SONY="Sony",XIAOMI="Xiaomi",ZEBRA="Zebra",CHROME="Chrome",CHROMIUM="Chromium",CHROMECAST="Chromecast",EDGE="Edge",FIREFOX="Firefox",OPERA="Opera",FACEBOOK="Facebook",SOGOU="Sogou",PREFIX_MOBILE="Mobile ",SUFFIX_BROWSER=" Browser",WINDOWS="Windows";var isWindow=typeof window!==UNDEF_TYPE,NAVIGATOR=isWindow&&window.navigator?window.navigator:undefined,NAVIGATOR_UADATA=NAVIGATOR&&NAVIGATOR.userAgentData?NAVIGATOR.userAgentData:undefined;var extend=function(defaultRgx,extensions){var mergedRgx={};var extraRgx=extensions;if(!isExtensions(extensions)){extraRgx={};for(var i in extensions){for(var j in extensions[i]){extraRgx[j]=extensions[i][j].concat(extraRgx[j]?extraRgx[j]:[])}}}for(var k in defaultRgx){mergedRgx[k]=extraRgx[k]&&extraRgx[k].length%2===0?extraRgx[k].concat(defaultRgx[k]):defaultRgx[k]}return mergedRgx},enumerize=function(arr){var enums={};for(var i=0;i0){for(var i in str1){if(lowerize(str1[i])==lowerize(str2))return true}return false}return isString(str1)?lowerize(str2).indexOf(lowerize(str1))!==-1:false},isExtensions=function(obj,deep){for(var prop in obj){return/^(browser|cpu|device|engine|os)$/.test(prop)||(deep?isExtensions(obj[prop]):false)}},isString=function(val){return typeof val===STR_TYPE},itemListToArray=function(header){if(!header)return undefined;var arr=[];var tokens=strip(/\\?\"/g,header).split(",");for(var i=0;i-1){var token=trim(tokens[i]).split(";v=");arr[i]={brand:token[0],version:token[1]}}else{arr[i]=trim(tokens[i])}}return arr},lowerize=function(str){return isString(str)?str.toLowerCase():str},majorize=function(version){return isString(version)?strip(/[^\d\.]/g,version).split(".")[0]:undefined},setProps=function(arr){for(var i in arr){var propName=arr[i];if(typeof propName==OBJ_TYPE&&propName.length==2){this[propName[0]]=propName[1]}else{this[propName]=undefined}}return this},strip=function(pattern,str){return isString(str)?str.replace(pattern,EMPTY):str},stripQuotes=function(str){return strip(/\\?\"/g,str)},trim=function(str,len){if(isString(str)){str=strip(/^\s\s*/,str);return typeof len===UNDEF_TYPE?str:str.substring(0,UA_MAX_LENGTH)}};var rgxMapper=function(ua,arrays){if(!ua||!arrays)return;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}},strMapper=function(str,map){for(var i in map){if(typeof map[i]===OBJ_TYPE&&map[i].length>0){for(var j=0;j2){this.set(MODEL,"iPad").set(TYPE,TABLET)}break;case UA_OS:if(!this.get(NAME)&&NAVIGATOR_UADATA&&NAVIGATOR_UADATA[PLATFORM]){this.set(NAME,NAVIGATOR_UADATA[PLATFORM])}break;case UA_RESULT:var data=this.data;var detect=function(itemType){return data[itemType].getItem().detectFeature().get()};this.set(UA_BROWSER,detect(UA_BROWSER)).set(UA_CPU,detect(UA_CPU)).set(UA_DEVICE,detect(UA_DEVICE)).set(UA_ENGINE,detect(UA_ENGINE)).set(UA_OS,detect(UA_OS))}}return this};this.parseUA=function(){if(this.itemType!=UA_RESULT){rgxMapper.call(this.data,this.ua,this.rgxMap)}if(this.itemType==UA_BROWSER){this.set(MAJOR,majorize(this.get(VERSION)))}return this};this.parseCH=function(){var uaCH=this.uaCH,rgxMap=this.rgxMap;switch(this.itemType){case UA_BROWSER:case UA_ENGINE:var brands=uaCH[FULLVERLIST]||uaCH[BRANDS],prevName;if(brands){for(var i in brands){var brandName=brands[i].brand||brands[i],brandVersion=brands[i].version;if(this.itemType==UA_BROWSER&&!/not.a.brand/i.test(brandName)&&(!prevName||/chrom/i.test(prevName)&&brandName!=CHROMIUM)){brandName=strMapper(brandName,{Chrome:"Google Chrome",Edge:"Microsoft Edge","Chrome WebView":"Android WebView","Chrome Headless":"HeadlessChrome","Huawei Browser":"HuaweiBrowser","MIUI Browser":"Miui Browser","Opera Mobi":"OperaMobile",Yandex:"YaBrowser"});this.set(NAME,brandName).set(VERSION,brandVersion).set(MAJOR,majorize(brandVersion));prevName=brandName}if(this.itemType==UA_ENGINE&&brandName==CHROMIUM){this.set(VERSION,brandVersion)}}}break;case UA_CPU:var archName=uaCH[ARCHITECTURE];if(archName){if(archName&&uaCH[BITNESS]=="64")archName+="64";rgxMapper.call(this.data,archName+";",rgxMap)}break;case UA_DEVICE:if(uaCH[MOBILE]){this.set(TYPE,MOBILE)}if(uaCH[MODEL]){this.set(MODEL,uaCH[MODEL]);if(!this.get(TYPE)||!this.get(VENDOR)){var reParse={};rgxMapper.call(reParse,"droid 9; "+uaCH[MODEL]+")",rgxMap);if(!this.get(TYPE)&&!!reParse.type){this.set(TYPE,reParse.type)}if(!this.get(VENDOR)&&!!reParse.vendor){this.set(VENDOR,reParse.vendor)}}}if(uaCH[FORMFACTORS]){var ff;if(typeof uaCH[FORMFACTORS]!=="string"){var idx=0;while(!ff&&idx=13?"11":"10";this.set(NAME,osName).set(VERSION,osVersion)}if(this.get(NAME)==WINDOWS&&uaCH[MODEL]=="Xbox"){this.set(NAME,"Xbox").set(VERSION,undefined)}break;case UA_RESULT:var data=this.data;var parse=function(itemType){return data[itemType].getItem().setCH(uaCH).parseCH().get()};this.set(UA_BROWSER,parse(UA_BROWSER)).set(UA_CPU,parse(UA_CPU)).set(UA_DEVICE,parse(UA_DEVICE)).set(UA_ENGINE,parse(UA_ENGINE)).set(UA_OS,parse(UA_OS))}return this};setProps.call(this,[["itemType",itemType],["ua",ua],["uaCH",uaCH],["rgxMap",rgxMap],["data",createIData(this,itemType)]]);return this}function UAParser(ua,extensions,headers){if(typeof ua===OBJ_TYPE){if(isExtensions(ua,true)){if(typeof extensions===OBJ_TYPE){headers=extensions}extensions=ua}else{headers=ua;extensions=undefined}ua=undefined}else if(typeof ua===STR_TYPE&&!isExtensions(extensions,true)){headers=extensions;extensions=undefined}if(headers&&typeof headers.append===FUNC_TYPE){var kv={};headers.forEach(function(v,k){kv[k]=v});headers=kv}if(!(this instanceof UAParser)){return new UAParser(ua,extensions,headers).getResult()}var userAgent=typeof ua===STR_TYPE?ua:headers&&headers[USER_AGENT]?headers[USER_AGENT]:NAVIGATOR&&NAVIGATOR.userAgent?NAVIGATOR.userAgent:EMPTY,httpUACH=new UACHData(headers,true),regexMap=extensions?extend(defaultRegexes,extensions):defaultRegexes,createItemFunc=function(itemType){if(itemType==UA_RESULT){return function(){return new UAItem(itemType,userAgent,regexMap,httpUACH).set("ua",userAgent).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()}}else{return function(){return new UAItem(itemType,userAgent,regexMap[itemType],httpUACH).parseUA().get()}}};setProps.call(this,[["getBrowser",createItemFunc(UA_BROWSER)],["getCPU",createItemFunc(UA_CPU)],["getDevice",createItemFunc(UA_DEVICE)],["getEngine",createItemFunc(UA_ENGINE)],["getOS",createItemFunc(UA_OS)],["getResult",createItemFunc(UA_RESULT)],["getUA",function(){return userAgent}],["setUA",function(ua){if(isString(ua))userAgent=ua.length>UA_MAX_LENGTH?trim(ua,UA_MAX_LENGTH):ua;return this}]]).setUA(userAgent);return this}UAParser.VERSION=LIBVERSION;UAParser.BROWSER=enumerize([NAME,VERSION,MAJOR,TYPE]);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 +var LIBVERSION="2.0.4",UA_MAX_LENGTH=500,USER_AGENT="user-agent",EMPTY="",UNKNOWN="?",FUNC_TYPE="function",UNDEF_TYPE="undefined",OBJ_TYPE="object",STR_TYPE="string",UA_BROWSER="browser",UA_CPU="cpu",UA_DEVICE="device",UA_ENGINE="engine",UA_OS="os",UA_RESULT="result",NAME="name",TYPE="type",VENDOR="vendor",VERSION="version",ARCHITECTURE="architecture",MAJOR="major",MODEL="model",CONSOLE="console",MOBILE="mobile",TABLET="tablet",SMARTTV="smarttv",WEARABLE="wearable",XR="xr",EMBEDDED="embedded",INAPP="inapp",BRANDS="brands",FORMFACTORS="formFactors",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_FORM_FACTORS=CH_HEADER+"-form-factors",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,FULLVERLIST,MOBILE,MODEL,PLATFORM,PLATFORMVER,ARCHITECTURE,FORMFACTORS,BITNESS],AMAZON="Amazon",APPLE="Apple",ASUS="ASUS",BLACKBERRY="BlackBerry",GOOGLE="Google",HUAWEI="Huawei",LENOVO="Lenovo",HONOR="Honor",LG="LG",MICROSOFT="Microsoft",MOTOROLA="Motorola",NVIDIA="Nvidia",ONEPLUS="OnePlus",OPPO="OPPO",SAMSUNG="Samsung",SHARP="Sharp",SONY="Sony",XIAOMI="Xiaomi",ZEBRA="Zebra",CHROME="Chrome",CHROMIUM="Chromium",CHROMECAST="Chromecast",EDGE="Edge",FIREFOX="Firefox",OPERA="Opera",FACEBOOK="Facebook",SOGOU="Sogou",PREFIX_MOBILE="Mobile ",SUFFIX_BROWSER=" Browser",WINDOWS="Windows";var isWindow=typeof window!==UNDEF_TYPE,NAVIGATOR=isWindow&&window.navigator?window.navigator:undefined,NAVIGATOR_UADATA=NAVIGATOR&&NAVIGATOR.userAgentData?NAVIGATOR.userAgentData:undefined;var extend=function(defaultRgx,extensions){var mergedRgx={};var extraRgx=extensions;if(!isExtensions(extensions)){extraRgx={};for(var i in extensions){for(var j in extensions[i]){extraRgx[j]=extensions[i][j].concat(extraRgx[j]?extraRgx[j]:[])}}}for(var k in defaultRgx){mergedRgx[k]=extraRgx[k]&&extraRgx[k].length%2===0?extraRgx[k].concat(defaultRgx[k]):defaultRgx[k]}return mergedRgx},enumerize=function(arr){var enums={};for(var i=0;i0){for(var i in str1){if(lowerize(str2)==lowerize(str1[i]))return true}return false}return isString(str1)?lowerize(str2)==lowerize(str1):false},isExtensions=function(obj,deep){for(var prop in obj){return/^(browser|cpu|device|engine|os)$/.test(prop)||(deep?isExtensions(obj[prop]):false)}},isString=function(val){return typeof val===STR_TYPE},itemListToArray=function(header){if(!header)return undefined;var arr=[];var tokens=strip(/\\?\"/g,header).split(",");for(var i=0;i-1){var token=trim(tokens[i]).split(";v=");arr[i]={brand:token[0],version:token[1]}}else{arr[i]=trim(tokens[i])}}return arr},lowerize=function(str){return isString(str)?str.toLowerCase():str},majorize=function(version){return isString(version)?strip(/[^\d\.]/g,version).split(".")[0]:undefined},setProps=function(arr){for(var i in arr){var propName=arr[i];if(typeof propName==OBJ_TYPE&&propName.length==2){this[propName[0]]=propName[1]}else{this[propName]=undefined}}return this},strip=function(pattern,str){return isString(str)?str.replace(pattern,EMPTY):str},stripQuotes=function(str){return strip(/\\?\"/g,str)},trim=function(str,len){if(isString(str)){str=strip(/^\s\s*/,str);return typeof len===UNDEF_TYPE?str:str.substring(0,UA_MAX_LENGTH)}};var rgxMapper=function(ua,arrays){if(!ua||!arrays)return;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)){if(q.length>3){this[q[0]]=match?q[1].apply(this,q.slice(2)):undefined}else{this[q[0]]=match?q[1].call(this,match,q[2]):undefined}}else{if(q.length==3){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 if(q.length>4){this[q[0]]=match?q[3].apply(this,[match.replace(q[1],q[2])].concat(q.slice(4))):undefined}}}}else{this[q]=match?match:undefined}}}}i+=2}},strMapper=function(str,map){for(var i in map){if(typeof map[i]===OBJ_TYPE&&map[i].length>0){for(var j=0;j2){this.set(MODEL,"iPad").set(TYPE,TABLET)}break;case UA_OS:if(!this.get(NAME)&&NAVIGATOR_UADATA&&NAVIGATOR_UADATA[PLATFORM]){this.set(NAME,NAVIGATOR_UADATA[PLATFORM])}break;case UA_RESULT:var data=this.data;var detect=function(itemType){return data[itemType].getItem().detectFeature().get()};this.set(UA_BROWSER,detect(UA_BROWSER)).set(UA_CPU,detect(UA_CPU)).set(UA_DEVICE,detect(UA_DEVICE)).set(UA_ENGINE,detect(UA_ENGINE)).set(UA_OS,detect(UA_OS))}}return this};this.parseUA=function(){if(this.itemType!=UA_RESULT){rgxMapper.call(this.data,this.ua,this.rgxMap)}if(this.itemType==UA_BROWSER){this.set(MAJOR,majorize(this.get(VERSION)))}return this};this.parseCH=function(){var uaCH=this.uaCH,rgxMap=this.rgxMap;switch(this.itemType){case UA_BROWSER:case UA_ENGINE:var brands=uaCH[FULLVERLIST]||uaCH[BRANDS],prevName;if(brands){for(var i in brands){var brandName=brands[i].brand||brands[i],brandVersion=brands[i].version;if(this.itemType==UA_BROWSER&&!/not.a.brand/i.test(brandName)&&(!prevName||/Chrom/.test(prevName)&&brandName!=CHROMIUM||prevName==EDGE&&/WebView2/.test(brandName))){brandName=strMapper(brandName,browserHintsMap);prevName=this.get(NAME);if(!(prevName&&!/Chrom/.test(prevName)&&/Chrom/.test(brandName))){this.set(NAME,brandName).set(VERSION,brandVersion).set(MAJOR,majorize(brandVersion))}prevName=brandName}if(this.itemType==UA_ENGINE&&brandName==CHROMIUM){this.set(VERSION,brandVersion)}}}break;case UA_CPU:var archName=uaCH[ARCHITECTURE];if(archName){if(archName&&uaCH[BITNESS]=="64")archName+="64";rgxMapper.call(this.data,archName+";",rgxMap)}break;case UA_DEVICE:if(uaCH[MOBILE]){this.set(TYPE,MOBILE)}if(uaCH[MODEL]){this.set(MODEL,uaCH[MODEL]);if(!this.get(TYPE)||!this.get(VENDOR)){var reParse={};rgxMapper.call(reParse,"droid 9; "+uaCH[MODEL]+")",rgxMap);if(!this.get(TYPE)&&!!reParse.type){this.set(TYPE,reParse.type)}if(!this.get(VENDOR)&&!!reParse.vendor){this.set(VENDOR,reParse.vendor)}}}if(uaCH[FORMFACTORS]){var ff;if(typeof uaCH[FORMFACTORS]!=="string"){var idx=0;while(!ff&&idx=13?"11":"10";this.set(NAME,osName).set(VERSION,osVersion)}if(this.get(NAME)==WINDOWS&&uaCH[MODEL]=="Xbox"){this.set(NAME,"Xbox").set(VERSION,undefined)}break;case UA_RESULT:var data=this.data;var parse=function(itemType){return data[itemType].getItem().setCH(uaCH).parseCH().get()};this.set(UA_BROWSER,parse(UA_BROWSER)).set(UA_CPU,parse(UA_CPU)).set(UA_DEVICE,parse(UA_DEVICE)).set(UA_ENGINE,parse(UA_ENGINE)).set(UA_OS,parse(UA_OS))}return this};setProps.call(this,[["itemType",itemType],["ua",ua],["uaCH",uaCH],["rgxMap",rgxMap],["data",createIData(this,itemType)]]);return this}function UAParser(ua,extensions,headers){if(typeof ua===OBJ_TYPE){if(isExtensions(ua,true)){if(typeof extensions===OBJ_TYPE){headers=extensions}extensions=ua}else{headers=ua;extensions=undefined}ua=undefined}else if(typeof ua===STR_TYPE&&!isExtensions(extensions,true)){headers=extensions;extensions=undefined}if(headers&&typeof headers.append===FUNC_TYPE){var kv={};headers.forEach(function(v,k){kv[k]=v});headers=kv}if(!(this instanceof UAParser)){return new UAParser(ua,extensions,headers).getResult()}var userAgent=typeof ua===STR_TYPE?ua:headers&&headers[USER_AGENT]?headers[USER_AGENT]:NAVIGATOR&&NAVIGATOR.userAgent?NAVIGATOR.userAgent:EMPTY,httpUACH=new UACHData(headers,true),regexMap=extensions?extend(defaultRegexes,extensions):defaultRegexes,createItemFunc=function(itemType){if(itemType==UA_RESULT){return function(){return new UAItem(itemType,userAgent,regexMap,httpUACH).set("ua",userAgent).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()}}else{return function(){return new UAItem(itemType,userAgent,regexMap[itemType],httpUACH).parseUA().get()}}};setProps.call(this,[["getBrowser",createItemFunc(UA_BROWSER)],["getCPU",createItemFunc(UA_CPU)],["getDevice",createItemFunc(UA_DEVICE)],["getEngine",createItemFunc(UA_ENGINE)],["getOS",createItemFunc(UA_OS)],["getResult",createItemFunc(UA_RESULT)],["getUA",function(){return userAgent}],["setUA",function(ua){if(isString(ua))userAgent=ua.length>UA_MAX_LENGTH?trim(ua,UA_MAX_LENGTH):ua;return this}]]).setUA(userAgent);return this}UAParser.VERSION=LIBVERSION;UAParser.BROWSER=enumerize([NAME,VERSION,MAJOR,TYPE]);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/dist/ua-parser.pack.js b/dist/ua-parser.pack.js index ab102f1..94f5cc5 100644 --- a/dist/ua-parser.pack.js +++ b/dist/ua-parser.pack.js @@ -1,4 +1,4 @@ -/* UAParser.js v2.0.3 +/* UAParser.js v2.0.4 Copyright © 2012-2025 Faisal Salman AGPLv3 License */ -((i,l)=>{function U(i){for(var e={},t=0;t{var t,o={},r=e;if(!_i(e))for(var a in r={},e)for(var s in e[a])r[s]=e[a][s].concat(r[s]||[]);for(t in i)o[t]=r[t]&&r[t].length%2==0?r[t].concat(i[t]):i[t];return o})(Ii,e):Ii,j.call(this,[["getBrowser",(n=function(i){return i==g?function(){return new Bi(i,r,s,a).set("ua",r).set(u,this.getBrowser()).set(h,this.getCPU()).set(p,this.getDevice()).set(m,this.getEngine()).set(f,this.getOS()).get()}:function(){return new Bi(i,r,s[i],a).parseUA().get()}})(u)],["getCPU",n(h)],["getDevice",n(p)],["getEngine",n(m)],["getOS",n(f)],["getResult",n(g)],["getUA",function(){return r}],["setUA",function(i){return H(i)&&(r=i.length>E?Hi(i,E):i),this}]]).setUA(r),this):new I(i,e,t).getResult()}I.VERSION="2.0.3",I.BROWSER=U([v,y,L,k]),I.CPU=U([C]),I.DEVICE=U([T,x,k,G,S,e,r,t,D]),I.ENGINE=I.OS=U([v,y]),typeof exports!==n?(exports=typeof module!==n&&module.exports?module.exports=I:exports).UAParser=I:typeof define===R&&define.amd?define(function(){return I}):Ti&&(i.UAParser=I);var Ri,Vi=Ti&&(i.jQuery||i.Zepto);Vi&&!Vi.ua&&(Ri=new I,Vi.ua=Ri.getResult(),Vi.ua.get=function(){return Ri.getUA()},Vi.ua.set=function(i){Ri.setUA(i);var e,t=Ri.getResult();for(e in t)Vi.ua[e]=t[e]})})("object"==typeof window?window:this); \ No newline at end of file +((i,l)=>{function I(i){for(var e={},t=0;t{var t,o={},r=e;if(!Ti(e))for(var a in r={},e)for(var s in e[a])r[s]=e[a][s].concat(r[s]||[]);for(t in i)o[t]=r[t]&&r[t].length%2==0?r[t].concat(i[t]):i[t];return o})(Pi,e):Pi,M.call(this,[["getBrowser",(n=function(i){return i==g?function(){return new Gi(i,r,s,a).set("ua",r).set(u,this.getBrowser()).set(h,this.getCPU()).set(p,this.getDevice()).set(m,this.getEngine()).set(f,this.getOS()).get()}:function(){return new Gi(i,r,s[i],a).parseUA().get()}})(u)],["getCPU",n(h)],["getDevice",n(p)],["getEngine",n(m)],["getOS",n(f)],["getResult",n(g)],["getUA",function(){return r}],["setUA",function(i){return O(i)&&(r=i.length>U?Mi(i,U):i),this}]]).setUA(r),this):new V(i,e,t).getResult()}V.VERSION="2.0.4",V.BROWSER=I([v,y,G,k]),V.CPU=I([C]),V.DEVICE=I([S,x,k,W,_,e,r,t,F]),V.ENGINE=V.OS=I([v,y]),typeof exports!==n?(exports=typeof module!==n&&module.exports?module.exports=V:exports).UAParser=V:typeof define===R&&define.amd?define(function(){return V}):qi&&(i.UAParser=V);var Wi,Ni=qi&&(i.jQuery||i.Zepto);Ni&&!Ni.ua&&(Wi=new V,Ni.ua=Wi.getResult(),Ni.ua.get=function(){return Wi.getUA()},Ni.ua.set=function(i){Wi.setUA(i);var e,t=Wi.getResult();for(e in t)Ni.ua[e]=t[e]})})("object"==typeof window?window:this); \ No newline at end of file diff --git a/dist/ua-parser.pack.mjs b/dist/ua-parser.pack.mjs index 6c16240..03863a2 100644 --- a/dist/ua-parser.pack.mjs +++ b/dist/ua-parser.pack.mjs @@ -1,4 +1,4 @@ -/* UAParser.js v2.0.3 +/* UAParser.js v2.0.4 Copyright © 2012-2025 Faisal Salman AGPLv3 License */ -function E(i){for(var e={},o=0;o{var o,t={},r=e;if(!_i(e))for(var a in r={},e)for(var s in e[a])r[s]=e[a][s].concat(r[s]||[]);for(o in i)t[o]=r[o]&&r[o].length%2==0?r[o].concat(i[o]):i[o];return t})(Ii,e):Ii,M.call(this,[["getBrowser",(n=function(i){return i==f?function(){return new Pi(i,r,s,a).set("ua",r).set(c,this.getBrowser()).set(u,this.getCPU()).set(h,this.getDevice()).set(p,this.getEngine()).set(m,this.getOS()).get()}:function(){return new Pi(i,r,s[i],a).parseUA().get()}})(c)],["getCPU",n(u)],["getDevice",n(h)],["getEngine",n(p)],["getOS",n(m)],["getResult",n(f)],["getUA",function(){return r}],["setUA",function(i){return A(i)&&(r=i.length>B?Ai(i,B):i),this}]]).setUA(r),this):new j(i,e,o).getResult()}j.VERSION="2.0.3",j.BROWSER=E([g,x,C,v]),j.CPU=E([y]),j.DEVICE=E([T,k,v,L,S,i,r,e,F]),j.ENGINE=j.OS=E([g,x]);export{j as UAParser}; \ No newline at end of file +function I(i){for(var e={},o=0;o{var o,t={},r=e;if(!zi(e))for(var a in r={},e)for(var s in e[a])r[s]=e[a][s].concat(r[s]||[]);for(o in i)t[o]=r[o]&&r[o].length%2==0?r[o].concat(i[o]):i[o];return t})(Ii,e):Ii,A.call(this,[["getBrowser",(n=function(i){return i==f?function(){return new Li(i,r,s,a).set("ua",r).set(c,this.getBrowser()).set(u,this.getCPU()).set(h,this.getDevice()).set(p,this.getEngine()).set(m,this.getOS()).get()}:function(){return new Li(i,r,s[i],a).parseUA().get()}})(c)],["getCPU",n(u)],["getDevice",n(h)],["getEngine",n(p)],["getOS",n(m)],["getResult",n(f)],["getUA",function(){return r}],["setUA",function(i){return H(i)&&(r=i.length>B?Mi(i,B):i),this}]]).setUA(r),this):new V(i,e,o).getResult()}V.VERSION="2.0.4",V.BROWSER=I([g,x,C,v]),V.CPU=I([y]),V.DEVICE=I([S,k,v,G,_,i,r,e,N]),V.ENGINE=V.OS=I([g,x]);export{V as UAParser}; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 70cf439..7dd00ea 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ua-parser-js", - "version": "2.0.3", + "version": "2.0.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "ua-parser-js", - "version": "2.0.3", + "version": "2.0.4", "funding": [ { "type": "opencollective", diff --git a/package.json b/package.json index ba1f89d..4ca4f0b 100755 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "title": "UAParser.js", "name": "ua-parser-js", - "version": "2.0.3", + "version": "2.0.4", "author": "Faisal Salman (http://faisalman.com)", "description": "Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent & Client Hints data. Supports browser & node.js environment", "keywords": [ diff --git a/src/enums/ua-parser-enums.d.ts b/src/enums/ua-parser-enums.d.ts index 97c760a..e8d3615 100644 --- a/src/enums/ua-parser-enums.d.ts +++ b/src/enums/ua-parser-enums.d.ts @@ -1,4 +1,4 @@ -// Type definitions for Enums submodule of UAParser.js v2.0.3 +// Type definitions for Enums submodule of UAParser.js v2.0.4 // Project: https://github.com/faisalman/ua-parser-js // Definitions by: Faisal Salman diff --git a/src/enums/ua-parser-enums.js b/src/enums/ua-parser-enums.js index 803970c..174d787 100644 --- a/src/enums/ua-parser-enums.js +++ b/src/enums/ua-parser-enums.js @@ -1,5 +1,5 @@ /////////////////////////////////////////////// -/* Enums for UAParser.js v2.0.3 +/* Enums for UAParser.js v2.0.4 https://github.com/faisalman/ua-parser-js Author: Faisal Salman AGPLv3 License */ diff --git a/src/enums/ua-parser-enums.mjs b/src/enums/ua-parser-enums.mjs index 571eb70..089af95 100644 --- a/src/enums/ua-parser-enums.mjs +++ b/src/enums/ua-parser-enums.mjs @@ -3,7 +3,7 @@ // Source: /src/enums/ua-parser-enums.js /////////////////////////////////////////////// -/* Enums for UAParser.js v2.0.3 +/* Enums for UAParser.js v2.0.4 https://github.com/faisalman/ua-parser-js Author: Faisal Salman AGPLv3 License */ @@ -25,7 +25,6 @@ const Browser = Object.freeze({ BAIDU: 'Baidu Browser', BASILISK: 'Basilisk', BLAZER: 'Blazer', - BLU: 'BLU', BOLT: 'Bolt', BOWSER: 'Bowser', BRAVE: 'Brave', @@ -48,6 +47,8 @@ const Browser = Object.freeze({ DUCKDUCKGO: 'DuckDuckGo', ECOSIA: 'Ecosia', EDGE: 'Edge', + EDGE_WEBVIEW: 'Edge WebView', + EDGE_WEBVIEW2: 'Edge WebView2', EPIPHANY: 'Epiphany', FACEBOOK: 'Facebook', FALKON: 'Falkon', @@ -218,6 +219,7 @@ const Vendor = Object.freeze({ ATT: 'AT&T', BENQ: 'BenQ', BLACKBERRY: 'BlackBerry', + BLU: 'BLU', CAT: 'Cat', DELL: 'Dell', ENERGIZER: 'Energizer', @@ -236,6 +238,7 @@ const Vendor = Object.freeze({ ITEL: 'itel', JOLLA: 'Jolla', KOBO: 'Kobo', + LAVA: 'Lava', LENOVO: 'Lenovo', LG: 'LG', MEIZU: 'Meizu', @@ -256,6 +259,7 @@ const Vendor = Object.freeze({ PICO: 'Pico', POLYTRON: 'Polytron', REALME: 'Realme', + RETROID: 'Retroid', RIM: 'RIM', ROKU: 'Roku', SAMSUNG: 'Samsung', @@ -270,6 +274,7 @@ const Vendor = Object.freeze({ TESLA: 'Tesla', ULEFONE: 'Ulefone', VIVO: 'Vivo', + VIZIO: 'Vizio', VODAFONE: 'Vodafone', XBOX: 'Xbox', XIAOMI: 'Xiaomi', @@ -307,6 +312,7 @@ const OS = Object.freeze({ AMIGA_OS: 'Amiga OS', ANDROID: 'Android', ANDROID_X86: 'Android-x86', + ARCAOS: 'ArcaOS', ARCH: 'Arch', BADA: 'Bada', BEOS: 'BeOS', @@ -337,6 +343,7 @@ const OS = Object.freeze({ IOS: 'iOS', JOLI: 'Joli', KAIOS: 'KaiOS', + KNOPPIX: 'Knoppix', KUBUNTU: 'Kubuntu', LINPUS: 'Linpus', LINSPIRE: 'Linspire', @@ -385,10 +392,13 @@ const OS = Object.freeze({ WATCHOS: 'watchOS', WEBOS: 'WebOS', WINDOWS: 'Windows', + WINDOWS_CE: 'Windows CE', WINDOWS_IOT: 'Windows IoT', WINDOWS_MOBILE: 'Windows Mobile', WINDOWS_PHONE: 'Windows Phone', + WINDOWS_RT: 'Windows RT', XBOX: 'Xbox', + XUBUNTU: 'Xubuntu', ZENWALK: 'Zenwalk' // TODO : test! diff --git a/src/extensions/ua-parser-extensions.d.ts b/src/extensions/ua-parser-extensions.d.ts index 3b9b63a..4ee31dd 100644 --- a/src/extensions/ua-parser-extensions.d.ts +++ b/src/extensions/ua-parser-extensions.d.ts @@ -1,4 +1,4 @@ -// Type definitions for Helpers submodule of UAParser.js v2.0.3 +// Type definitions for Helpers submodule of UAParser.js v2.0.4 // Project: https://github.com/faisalman/ua-parser-js // Definitions by: Faisal Salman diff --git a/src/extensions/ua-parser-extensions.js b/src/extensions/ua-parser-extensions.js index d89b7ec..4cd644f 100644 --- a/src/extensions/ua-parser-extensions.js +++ b/src/extensions/ua-parser-extensions.js @@ -1,5 +1,5 @@ /////////////////////////////////////////////// -/* Extensions for UAParser.js v2.0.3 +/* Extensions for UAParser.js v2.0.4 https://github.com/faisalman/ua-parser-js Author: Faisal Salman AGPLv3 License */ diff --git a/src/extensions/ua-parser-extensions.mjs b/src/extensions/ua-parser-extensions.mjs index 9770ebc..9401493 100644 --- a/src/extensions/ua-parser-extensions.mjs +++ b/src/extensions/ua-parser-extensions.mjs @@ -3,7 +3,7 @@ // Source: /src/extensions/ua-parser-extensions.js /////////////////////////////////////////////// -/* Extensions for UAParser.js v2.0.3 +/* Extensions for UAParser.js v2.0.4 https://github.com/faisalman/ua-parser-js Author: Faisal Salman AGPLv3 License */ @@ -52,13 +52,15 @@ const Crawlers = Object.freeze({ // DuckDuckBot - http://duckduckgo.com/duckduckbot.html // FacebookBot - https://developers.facebook.com/docs/sharing/bot/ // GPTBot - https://platform.openai.com/docs/gptbot + // iAskBot - https://iask.ai // LinkedInBot - http://www.linkedin.com // MJ12bot - https://mj12bot.com/ // MojeekBot - https://www.mojeek.com/bot.html + // Onespot - https://www.onespot.com/identifying-traffic.html // OpenAI's SearchGPT - https://platform.openai.com/docs/bots // PerplexityBot - https://perplexity.ai/perplexitybot // SeznamBot - http://napoveda.seznam.cz/seznambot-intro - /((?:adidx|ahrefs|amazon|bing|cc|dot|duckduck|exa|facebook|gpt|linkedin|mj12|mojeek|oai-search|perplexity|semrush|seznam)bot)\/([\w\.-]+)/i, + /((?:adidx|ahrefs|amazon|bing|cc|dot|duckduck|exa|facebook|gpt|iask|linkedin|mj12|mojeek|oai-search|onespot-scraper|perplexity|semrush|seznam)bot)\/([\w\.-]+)/i, // Applebot - http://apple.com/go/applebot /(applebot(?:-extended)?)\/?([\w\.]*)/i, @@ -72,6 +74,9 @@ const Crawlers = Object.freeze({ // Coc Coc Bot - https://help.coccoc.com/en/search-engine /(coccocbot-(?:image|web))\/([\w\.]+)/i, + // Daum + /(daum(?:oa)?(?:-image)?)[ \/]([\w\.]+)/i, + // Facebook / Meta // https://developers.facebook.com/docs/sharing/webmasters/web-crawlers /(facebook(?:externalhit|catalog)|meta-externalagent)\/([\w\.]+)/i, @@ -82,6 +87,9 @@ const Crawlers = Object.freeze({ // Internet Archive (archive.org) /(ia_archiver|archive\.org_bot)\/?([\w\.]*)/i, + // Qwantbot - https://help.qwant.com/bot + /(qwantbot)[-\w]*\/?([\w\.]*)/i, + // SemrushBot - http://www.semrush.com/bot.html /((?:semrush|splitsignal)bot[-abcfimostw]*)\/?([\w\.-]*)/i, @@ -97,8 +105,8 @@ const Crawlers = Object.freeze({ // Yeti (Naver) /(yeti)\/([\w\.]+)/i, - // aiHitBot / Diffbot / Linespider / Magpie-Crawler / Omgilibot / OpenAI Image Downloader / Webzio-Extended / Screaming Frog SEO Spider / Timpibot / VelenPublicWebCrawler / YisouSpider / YouBot - /((?:aihit|diff|timpi|you)bot|omgili(?:bot)?|openai image downloader|(?:magpie-|velenpublicweb)crawler|webzio-extended|(?:screaming frog seo |line|yisou)spider)\/?([\w\.]*)/i + // aiHitBot / Diffbot / Linespider / Magpie-Crawler / Omgilibot / OpenAI Image Downloader / Webzio-Extended / Screaming Frog SEO Spider / Startpage / Timpibot / VelenPublicWebCrawler / YisouSpider / YouBot + /((?:aihit|diff|timpi|you)bot|omgili(?:bot)?|openai image downloader|(?:magpie-|velenpublicweb)crawler|startpageprivateimageproxy|webzio-extended|(?:chatglm-|line|screaming frog seo |yisou)spider)\/?([\w\.]*)/i ], [NAME, VERSION, [TYPE, CRAWLER]], @@ -208,9 +216,18 @@ const ExtraDevices = Object.freeze({ const Emails = Object.freeze({ browser : [ [ - // Evolution / Kontact/KMail / [Microsoft/Mac] Outlook / Thunderbird - /(airmail|bluemail|emclient|evolution|foxmail|kmail2?|kontact|(?:microsoft |mac)?outlook(?:-express)?|navermailapp|(?!chrom.+)sparrow|thunderbird|yahoo)(?:m.+ail; |[\/ ])([\w\.]+)/i - ], [NAME, VERSION, [TYPE, EMAIL]] + // Evolution / Kontact/KMail[2] / [Microsoft/Mac] Outlook / Thunderbird + // Airmail / BlueMail / DaumMail / eMClient / Foxmail / NaverMailApp / Polymail + // ProtonMail / SparkDesktop / Sparrow / Yahoo! Mail / Zimbra / ZohoMail-Desktop + /((?:air|blue|daum|fox|poly|proton)mail|emclient|evolution|kmail2?|kontact|(?:microsoft |mac)?outlook(?:-express)?|navermailapp|(?!chrom.+)sparrow|sparkdesktop|thunderbird|yahoo|zohomail-desktop)(?:m.+ail; |[\/ ])([\w\.]+)/i, + + // Apple's Mail + /(mail)\/([\w\.]+) cf/i + ], [NAME, VERSION, [TYPE, EMAIL]], [ + + // Zimbra + /zdesktop\/([\w\.]+)/i + ], [VERSION, [NAME, 'Zimbra'], [TYPE, EMAIL]] ] }); @@ -226,8 +243,11 @@ const Fetchers = Object.freeze({ // DuckAssistBot - https://duckduckgo.com/duckassistbot/ // Better Uptime / BingPreview / Mastodon / MicrosoftPreview / Pinterestbot / Redditbot / Rogerbot / SiteAuditBot / Telegrambot / Twitterbot / UptimeRobot // Google Site Verifier / Meta / Yahoo! Japan + // Iframely - https://iframely.com/docs/about + // Perplexity-User - https://docs.perplexity.ai/guides/bots + // MistralAI-User - https://docs.mistral.ai/robots/ // Yandex Bots - https://yandex.com/bots - /(ahrefssiteaudit|(?:bing|microsoft)preview|chatgpt-user|mastodon|(?:discord|duckassist|linkedin|pinterest|reddit|roger|siteaudit|twitter|uptimero)bot|google-site-verification|meta-externalfetcher|y!?j-dlc|yandex(?:calendar|direct(?:dyn)?|searchshop)|yadirectfetcher)\/([\w\.]+)/i, + /(ahrefssiteaudit|(?:bing|microsoft)preview|(?:chatgpt|mistralai|perplexity)-user|mastodon|(?:discord|duckassist|linkedin|pinterest|reddit|roger|siteaudit|twitter|uptimero)bot|google-site-verification|iframely|meta-externalfetcher|y!?j-dlc|yandex(?:calendar|direct(?:dyn)?|searchshop)|yadirectfetcher)\/([\w\.]+)/i, // Bluesky /(bluesky) cardyb\/([\w\.]+)/i, @@ -261,13 +281,31 @@ const Fetchers = Object.freeze({ /////////////////// const InApps = Object.freeze({ - browser : [ + browser : [[ + // Discord/Figma/Flipboard/Mattermost/Notion/Postman/Rambox/Rocket.Chat/Slack/Teams + /\b(discord|figma|mattermost|notion|postman|rambox|rocket.chat|slack|teams)\/([\w\.]+).+(electron\/|; ios)/i, + /(flipboard)\/([\w\.]+)/i + ], [NAME, VERSION, [TYPE, INAPP]], [ + + // Evernote/Teams on mobile + /(evernote) win/i, + /(teams)mobile-(ios|and)/i + ], [NAME, [TYPE, INAPP]], [ + // Slack - [/(?:slack(?=.+electron|.+ios)|chatlyio)\/([\d\.]+)/i], - [VERSION, [NAME, 'Slack'], [TYPE, INAPP]], + /chatlyio\/([\d\.]+)/i], + [VERSION, [NAME, 'Slack'], [TYPE, INAPP]], [ + + // TikTok Lite + /ultralite app_version\/([\w\.]+)/i], + [VERSION, [NAME, 'TikTok Lite'], [TYPE, INAPP]], [ + + // VS Code + /\) code\/([\d\.]+).+electron\//i], + [VERSION, [NAME, 'VS Code'], [TYPE, INAPP]], [ // Yahoo! Japan - [/jp\.co\.yahoo\.(?:android\.yjtop|ipn\.appli)\/([\d\.]+)/i], + /jp\.co\.yahoo\.(?:android\.yjtop|ipn\.appli)\/([\d\.]+)/i], [VERSION, [NAME, 'Yahoo! Japan'], [TYPE, INAPP]] ] }); @@ -332,8 +370,10 @@ const Libraries = Object.freeze({ browser : [ // Apache-HttpClient/Axios/go-http-client/got/GuzzleHttp/Java[-HttpClient]/jsdom/libwww-perl/lua-resty-http/Needle/node-fetch/OkHttp/PHP-SOAP/PostmanRuntime/python-urllib/python-requests/Scrapy/superagent [ - /^(apache-httpclient|axios|(?:go|java)-http-client|got|guzzlehttp|java|libwww-perl|lua-resty-http|needle|node-(?:fetch|superagent)|okhttp|php-soap|postmanruntime|python-(?:urllib|requests)|scrapy)\/([\w\.]+)/i, - /(jsdom|(?<=\()java)\/([\w\.]+)/i + /^(apache-httpclient|axios|(?:go|java)-http-client|got|guzzlehttp|java|libwww-perl|lua-resty-http|needle|node-(?:fetch|superagent)|okhttp|php-soap|postmanruntime|python-(?:httpx|urllib[23]?|requests)|scrapy)\/([\w\.]+)/i, + /(adobeair|aiohttp|jsdom)\/([\w\.]+)/i, + /(nutch)-([\w\.-]+)(\(|$)/i, + /\((java)\/([\w\.]+)/i ], [NAME, VERSION, [TYPE, LIBRARY]] ] }); diff --git a/src/helpers/ua-parser-helpers.d.ts b/src/helpers/ua-parser-helpers.d.ts index 4b6c808..fc53c61 100644 --- a/src/helpers/ua-parser-helpers.d.ts +++ b/src/helpers/ua-parser-helpers.d.ts @@ -1,4 +1,4 @@ -// Type definitions for Helpers submodule of UAParser.js v2.0.3 +// Type definitions for Helpers submodule of UAParser.js v2.0.4 // Project: https://github.com/faisalman/ua-parser-js // Definitions by: Faisal Salman diff --git a/src/helpers/ua-parser-helpers.js b/src/helpers/ua-parser-helpers.js index d14667b..8f79fe8 100644 --- a/src/helpers/ua-parser-helpers.js +++ b/src/helpers/ua-parser-helpers.js @@ -1,5 +1,5 @@ /////////////////////////////////////////////// -/* Helpers for UAParser.js v2.0.3 +/* Helpers for UAParser.js v2.0.4 https://github.com/faisalman/ua-parser-js Author: Faisal Salman AGPLv3 License */ diff --git a/src/helpers/ua-parser-helpers.mjs b/src/helpers/ua-parser-helpers.mjs index e47aae4..3530e7d 100644 --- a/src/helpers/ua-parser-helpers.mjs +++ b/src/helpers/ua-parser-helpers.mjs @@ -3,7 +3,7 @@ // Source: /src/helpers/ua-parser-helpers.js /////////////////////////////////////////////// -/* Helpers for UAParser.js v2.0.3 +/* Helpers for UAParser.js v2.0.4 https://github.com/faisalman/ua-parser-js Author: Faisal Salman AGPLv3 License */ @@ -114,6 +114,9 @@ const isAIBot = (resultOrUA) => [ // You.com 'youbot', + // Zhipu AI + 'chatglm-spider', + // Zyte 'scrapy' diff --git a/src/main/ua-parser.d.ts b/src/main/ua-parser.d.ts index 6c7c9f8..9533b68 100644 --- a/src/main/ua-parser.d.ts +++ b/src/main/ua-parser.d.ts @@ -1,4 +1,4 @@ -// Type definitions for UAParser.js v2.0.3 +// Type definitions for UAParser.js v2.0.4 // Project: https://github.com/faisalman/ua-parser-js // Definitions by: Faisal Salman diff --git a/src/main/ua-parser.js b/src/main/ua-parser.js index e3373d2..b325e7b 100755 --- a/src/main/ua-parser.js +++ b/src/main/ua-parser.js @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////////// -/* UAParser.js v2.0.3 +/* UAParser.js v2.0.4 Copyright © 2012-2025 Faisal Salman AGPLv3 License *//* Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data. @@ -19,7 +19,7 @@ // Constants ///////////// - var LIBVERSION = '2.0.3', + var LIBVERSION = '2.0.4', UA_MAX_LENGTH = 500, USER_AGENT = 'user-agent', EMPTY = '', diff --git a/src/main/ua-parser.mjs b/src/main/ua-parser.mjs index 00eb9bb..13d7caa 100644 --- a/src/main/ua-parser.mjs +++ b/src/main/ua-parser.mjs @@ -3,7 +3,7 @@ // Source: /src/main/ua-parser.js ///////////////////////////////////////////////////////////////////////////////// -/* UAParser.js v2.0.3 +/* UAParser.js v2.0.4 Copyright © 2012-2025 Faisal Salman AGPLv3 License *//* Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data. @@ -21,7 +21,7 @@ // Constants ///////////// - var LIBVERSION = '2.0.3', + var LIBVERSION = '2.0.4', UA_MAX_LENGTH = 500, USER_AGENT = 'user-agent', EMPTY = '', @@ -154,11 +154,11 @@ has = function (str1, str2) { if (typeof str1 === OBJ_TYPE && str1.length > 0) { for (var i in str1) { - if (lowerize(str1[i]) == lowerize(str2)) return true; + if (lowerize(str2) == lowerize(str1[i])) return true; } return false; } - return isString(str1) ? lowerize(str2).indexOf(lowerize(str1)) !== -1 : false; + return isString(str1) ? lowerize(str2) == lowerize(str1) : false; }, isExtensions = function (obj, deep) { for (var prop in obj) { @@ -249,17 +249,25 @@ // assign given value, ignore regex match this[q[0]] = q[1]; } - } else if (q.length === 3) { - // check whether function or regex + } else if (q.length >= 3) { + // Check whether q[1] 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; + if (q.length > 3) { + this[q[0]] = match ? q[1].apply(this, q.slice(2)) : undefined; + } else { + // 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; + if (q.length == 3) { + // 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 if (q.length > 4) { + this[q[0]] = match ? q[3].apply(this, [match.replace(q[1], q[2])].concat(q.slice(4))) : 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; @@ -293,17 +301,17 @@ ////////////// var 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' + 'ME' : '4.90', + 'NT 3.51': '3.51', + 'NT 4.0': '4.0', + '2000' : ['5.0', '5.01'], + 'XP' : ['5.1', '5.2'], + 'Vista' : '6.0', + '7' : '6.1', + '8' : '6.2', + '8.1' : '6.3', + '10' : ['6.4', '10.0'], + 'NT' : '' }, formFactorsMap = { @@ -315,6 +323,18 @@ 'xr' : ['VR', 'XR'], '?' : ['Desktop', 'Unknown'], '*' : undefined + }, + + browserHintsMap = { + 'Chrome' : 'Google Chrome', + 'Edge' : 'Microsoft Edge', + 'Edge WebView2' : 'Microsoft Edge WebView2', + 'Chrome WebView': 'Android WebView', + 'Chrome Headless':'HeadlessChrome', + 'Huawei Browser': 'HuaweiBrowser', + 'MIUI Browser' : 'Miui Browser', + 'Opera Mobi' : 'OperaMobile', + 'Yandex' : 'YaBrowser' }; ////////////// @@ -328,7 +348,9 @@ // Most common regardless engine /\b(?:crmo|crios)\/([\w\.]+)/i // Chrome for Android/iOS ], [VERSION, [NAME, PREFIX_MOBILE + 'Chrome']], [ - /edg(?:e|ios|a)?\/([\w\.]+)/i // Microsoft Edge + /webview.+edge\/([\w\.]+)/i // Microsoft Edge + ], [VERSION, [NAME, EDGE+' WebView']], [ + /edg(?:e|ios|a)?\/([\w\.]+)/i ], [VERSION, [NAME, 'Edge']], [ // Presto based @@ -420,7 +442,6 @@ // WebView /((?:fban\/fbios|fb_iab\/fb4a)(?!.+fbav)|;fbav\/([\w\.]+);)/i // Facebook App for iOS & Android ], [[NAME, FACEBOOK], VERSION, [TYPE, INAPP]], [ - /(Klarna)\/([\w\.]+)/i, // Klarna Shopping Browser for iOS & Android /(kakao(?:talk|story))[\/ ]([\w\.]+)/i, // Kakao App /(naver)\(.*?(\d+\.[\w\.]+).*\)/i, // Naver InApp /(daum)apps[\/ ]([\w\.]+)/i, // Daum App @@ -428,7 +449,7 @@ /\b(line)\/([\w\.]+)\/iab/i, // Line App for Android /(alipay)client\/([\w\.]+)/i, // Alipay /(twitter)(?:and| f.+e\/([\w\.]+))/i, // Twitter - /(instagram|snapchat)[\/ ]([-\w\.]+)/i // Instagram/Snapchat + /(instagram|snapchat|klarna)[\/ ]([-\w\.]+)/i // Instagram/Snapchat/Klarna ], [NAME, VERSION, [TYPE, INAPP]], [ /\bgsa\/([\w\.]+) .*safari\//i // Google Search Appliance on iOS ], [VERSION, [NAME, 'GSA'], [TYPE, INAPP]], [ @@ -443,6 +464,9 @@ /headlesschrome(?:\/([\w\.]+)| )/i // Chrome Headless ], [VERSION, [NAME, CHROME+' Headless']], [ + /wv\).+chrome\/([\w\.]+).+edgw\//i // Edge WebView2 + ], [VERSION, [NAME, EDGE+' WebView2']], [ + / wv\).+(chrome)\/([\w\.]+)/i // Chrome WebView ], [[NAME, CHROME+' WebView'], VERSION], [ @@ -535,7 +559,7 @@ /\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)-(?![lr])\w+|sc[g-]?[\d]+a?|galaxy nexus)/i, - /samsung[- ]((?!sm-[lr])[-\w]+)/i, + /samsung[- ]((?!sm-[lr]|browser)[-\w]+)/i, /sec-(sgh\w+)/i ], [MODEL, [VENDOR, SAMSUNG], [TYPE, MOBILE]], [ @@ -580,16 +604,22 @@ / ([\w ]+) miui\/v?\d/i ], [[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, MOBILE]], [ + // OnePlus + /droid.+; (cph2[3-6]\d[13579]|((gm|hd)19|(ac|be|in|kb)20|(d[en]|eb|le|mt)21|ne22)[0-2]\d|p[g-k]\w[1m]10)\b/i, + /(?:one)?(?:plus)? (a\d0\d\d)(?: b|\))/i + ], [MODEL, [VENDOR, ONEPLUS], [TYPE, MOBILE]], [ + // 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]], [ /\b(opd2(\d{3}a?))(?: bui|\))/i - ], [MODEL, [VENDOR, strMapper, { 'OnePlus' : ['304', '403', '203'], '*' : OPPO }], [TYPE, TABLET]], [ + ], [MODEL, [VENDOR, strMapper, { 'OnePlus' : ['203', '304', '403', '404', '413', '415'], '*' : OPPO }], [TYPE, TABLET]], [ + + // BLU + /(vivo (5r?|6|8l?|go|one|s|x[il]?[2-4]?)[\w\+ ]*)(?: bui|\))/i // Vivo series + ], [MODEL, [VENDOR, 'BLU'], [TYPE, MOBILE]], [ - // BLU Vivo Series - /(vivo (5r?|6|8l?|go|one|s|x[il]?[2-4]?)[\w\+ ]*)(?: bui|\))/i - ], [MODEL, [VENDOR, 'BLU'], [TYPE, MOBILE]], [ // Vivo /; vivo (\w+)(?: bui|\))/i, /\b(v[12]\d{3}\w?[at])(?: bui|;)/i @@ -599,10 +629,17 @@ /\b(rmx[1-3]\d{3})(?: bui|;|\))/i ], [MODEL, [VENDOR, 'Realme'], [TYPE, MOBILE]], [ + // Lenovo + /(ideatab[-\w ]+|602lv|d-42a|a101lv|a2109a|a3500-hv|s[56]000|pb-6505[my]|tb-?x?\d{3,4}(?:f[cu]|xu|[av])|yt\d?-[jx]?\d+[lfmx])( bui|;|\)|\/)/i, + /lenovo ?(b[68]0[08]0-?[hf]?|tab(?:[\w- ]+?)|tb[\w-]{6,7})( bui|;|\)|\/)/i + ], [MODEL, [VENDOR, LENOVO], [TYPE, TABLET]], [ + /lenovo[-_ ]?([-\w ]+?)(?: bui|\)|\/)/i + ], [MODEL, [VENDOR, LENOVO], [TYPE, MOBILE]], [ + // Motorola /\b(milestone|droid(?:[2-4x]| (?:bionic|x2|pro|razr))?:?( 4g)?)\b[\w ]+build\//i, - /\bmot(?:orola)?[- ](\w*)/i, - /((?:moto(?! 360)[\w\(\) ]+|xt\d{3,4}|nexus 6)(?= bui|\)))/i + /\bmot(?:orola)?[- ]([\w\s]+)(\)| bui)/i, + /((?:moto(?! 360)[-\w\(\) ]+|xt\d{3,4}[cgkosw\+]?[-\d]*|nexus 6)(?= bui|\)))/i ], [MODEL, [VENDOR, MOTOROLA], [TYPE, MOBILE]], [ /\b(mz60\d|xoom[2 ]{0,2}) build\//i ], [MODEL, [VENDOR, MOTOROLA], [TYPE, TABLET]], [ @@ -611,15 +648,10 @@ /((?=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|watch))(\w+)/i, + /\blg[-e;\/ ]+(?!.*(?:browser|netcast|android tv|watch|webos))(\w+)/i, /\blg-?([\d\w]+) bui/i ], [MODEL, [VENDOR, LG], [TYPE, MOBILE]], [ - // Lenovo - /(ideatab[-\w ]+|602lv|d-42a|a101lv|a2109a|a3500-hv|s[56]000|pb-6505[my]|tb-?x?\d{3,4}(?:f[cu]|xu|[av])|yt\d?-[jx]?\d+[lfmx])( bui|;|\)|\/)/i, - /lenovo ?(b[68]0[08]0-?[hf]?|tab(?:[\w- ]+?)|tb[\w-]{6,7})( bui|;|\)|\/)/i - ], [MODEL, [VENDOR, LENOVO], [TYPE, TABLET]], [ - // Nokia /(nokia) (t[12][01])/i ], [VENDOR, MODEL, [TYPE, TABLET]], [ @@ -630,21 +662,19 @@ // Google /(pixel (c|tablet))\b/i // Google Pixel C/Tablet ], [MODEL, [VENDOR, GOOGLE], [TYPE, TABLET]], [ - /droid.+; (pixel[\daxl ]{0,6})(?: bui|\))/i // Google Pixel + // Google Pixel + /droid.+;(?: google)? (g(01[13]a|020[aem]|025[jn]|1b60|1f8f|2ybb|4s1m|576d|5nz6|8hhn|8vou|a02099|c15s|d1yq|e2ae|ec77|gh2x|kv4x|p4bc|pj41|r83y|tt9q|ur25|wvk6)|pixel[\d ]*a?( pro)?( xl)?( fold)?( \(5g\))?)( bui|\))/i ], [MODEL, [VENDOR, GOOGLE], [TYPE, MOBILE]], [ + /(google) (pixelbook( go)?)/i + ], [VENDOR, MODEL], [ // 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 + /droid.+; (a?\d[0-2]{2}so|[c-g]\d{4}|so[-gl]\w+|xq-\w\w\d\d)(?= 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|aeo(?!bc)\w\w)( bui|\))/i, // Kindle Fire without Silk / Echo Show @@ -715,7 +745,7 @@ ], [MODEL, [VENDOR, 'Smartfren'], [TYPE, MOBILE]], [ // Nothing - /droid.+; (a(?:015|06[35]|142p?))/i + /droid.+; (a(in)?(0(15|59|6[35])|142)p?)/i ], [MODEL, [VENDOR, 'Nothing'], [TYPE, MOBILE]], [ // Archos @@ -726,17 +756,20 @@ /; (ac[3-6]\d\w{2,8})( b|\))/i ], [MODEL, [VENDOR, 'Archos'], [TYPE, MOBILE]], [ + // HMD + /; (n159v)/i + ], [MODEL, [VENDOR, 'HMD'], [TYPE, MOBILE]], [ + // MIXED /(imo) (tab \w+)/i, // IMO - /(infinix) (x1101b?)/i // Infinix XPad + /(infinix|tecno) (x1101b?|p904|dp(7c|8d|10a)( pro)?|p70[1-3]a?|p904|t1101)/i // Infinix XPad / Tecno ], [VENDOR, MODEL, [TYPE, TABLET]], [ - /(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus(?! zenw)|dell|jolla|meizu|motorola|polytron|infinix|tecno|micromax|advan)[-_ ]?([-\w]*)/i, - // BlackBerry/BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron/Infinix/Tecno/Micromax/Advan - /; (blu|hmd|imo|tcl)[_ ]([\w\+ ]+?)(?: bui|\)|; r)/i, // BLU/HMD/IMO/TCL + /(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus(?! zenw)|dell|jolla|meizu|motorola|polytron|tecno|micromax|advan)[-_ ]?([-\w]*)/i, + // BlackBerry/BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron/Tecno/Micromax/Advan + /; (blu|hmd|imo|infinix|lava|oneplus|tcl)[_ ]([\w\+ ]+?)(?: bui|\)|; r)/i, // BLU/HMD/IMO/Infinix/Lava/OnePlus/TCL /(hp) ([\w ]+\w)/i, // HP iPAQ /(microsoft); (lumia[\w ]+)/i, // Microsoft Lumia - /(lenovo)[-_ ]?([-\w ]+?)(?: bui|\)|\/)/i, // Lenovo /(oppo) ?([\w ]+) bui/i // OPPO ], [VENDOR, MODEL, [TYPE, MOBILE]], [ @@ -768,6 +801,7 @@ ], [VENDOR, [TYPE, SMARTTV]], [ /hbbtv.+maple;(\d+)/i ], [[MODEL, /^/, 'SmartTV'], [VENDOR, SAMSUNG], [TYPE, SMARTTV]], [ + /(vizio)(?: |.+model\/)(\w+-\w+)/i, // Vizio /tcast.+(lg)e?. ([-\w]+)/i // LG SmartTV ], [VENDOR, MODEL, [TYPE, SMARTTV]], [ /(nux; netcast.+smarttv|lg (netcast\.tv-201\d|android tv))/i @@ -799,26 +833,27 @@ ], [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]], [ + ], [[VENDOR, /.+\/(\w+)/, '$1', strMapper, {'LG':'lge'}], [MODEL, trim], [TYPE, SMARTTV]], [ // SmartTV from Unidentified Vendors /droid.+; ([\w- ]+) (?:android tv|smart[- ]?tv)/i ], [MODEL, [TYPE, SMARTTV]], [ - /\b(android tv|smart[- ]?tv|opera tv|tv; rv:)\b/i + /\b(android tv|smart[- ]?tv|opera tv|tv; rv:|large screen[\w ]+safari)\b/i ], [[TYPE, SMARTTV]], [ /////////////////// // CONSOLES /////////////////// - /(ouya)/i, // Ouya - /(nintendo) (\w+)/i // Nintendo - ], [VENDOR, MODEL, [TYPE, CONSOLE]], [ - /droid.+; (shield)( bui|\))/i // Nvidia Portable - ], [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]], [ + /(ouya)/i, // Ouya + /(nintendo) (\w+)/i, // Nintendo + /(retroid) (pocket ([^\)]+))/i // Retroid Pocket + ], [VENDOR, MODEL, [TYPE, CONSOLE]], [ + /droid.+; (shield)( bui|\))/i // Nvidia Portable + ], [MODEL, [VENDOR, NVIDIA], [TYPE, CONSOLE]], [ /////////////////// // WEARABLES @@ -854,6 +889,8 @@ ], [VENDOR, MODEL, [TYPE, XR]], [ /(quest( \d| pro)?s?).+vr/i // Meta Quest ], [MODEL, [VENDOR, FACEBOOK], [TYPE, XR]], [ + /mobile vr; rv.+firefox/i // Unidentifiable VR device using Firefox Reality / Wolvic + ], [[TYPE, XR]], [ /////////////////// // EMBEDDED @@ -865,7 +902,7 @@ ], [MODEL, [VENDOR, AMAZON], [TYPE, EMBEDDED]], [ /(homepod).+mac os/i // Apple HomePod ], [MODEL, [VENDOR, APPLE], [TYPE, EMBEDDED]], [ - /windows iot/i + /windows iot/i // Unidentifiable embedded device using Windows IoT ], [[TYPE, EMBEDDED]], [ //////////////////// @@ -911,14 +948,17 @@ os : [[ // Windows - /microsoft (windows) (vista|xp)/i // Windows (iTunes) + /(windows nt) (6\.[23]); arm/i // Windows RT + ], [[NAME, /N/, 'R'], [VERSION, strMapper, windowsVersionMap]], [ + /(windows (?:phone|mobile|iot))(?: os)?[\/ ]?([\d\.]*( se)?)/i, // Windows IoT/Mobile/Phone + // Windows NT/3.1/95/98/ME/2000/XP/Vista/7/8/8.1/10/11 + /(windows)[\/ ](1[01]|2000|3\.1|7|8(\.1)?|9[58]|me|server 20\d\d( r2)?|vista|xp)/i + ], [NAME, VERSION], [ + /windows nt ?([\d\.\)]*)(?!.+xbox)/i, + /\bwin(?=3| ?9|n)(?:nt| 9x )?([\d\.;]*)/i + ], [[VERSION, /(;|\))/g, '', strMapper, windowsVersionMap], [NAME, WINDOWS]], [ + /(windows ce)\/?([\d\.]*)/i // Windows CE ], [NAME, VERSION], [ - /(windows (?:phone(?: os)?|mobile|iot))[\/ ]?([\d\.\w ]*)/i // Windows Phone - ], [NAME, [VERSION, strMapper, windowsVersionMap]], [ - /windows nt 6\.2; (arm)/i, // Windows RT - /windows[\/ ]([ntce\d\. ]+\w)(?!.+xbox)/i, - /(?:win(?=3|9|n)|win 9x )([nt\d\.]+)/i - ], [[VERSION, strMapper, windowsVersionMap], [NAME, WINDOWS]], [ // iOS/macOS /[adehimnop]{4,7}\b(?:.*os ([\w]+) like mac|; opera)/i, // iOS @@ -926,7 +966,7 @@ /cfnetwork\/.+darwin/i ], [[VERSION, /_/g, '.'], [NAME, 'iOS']], [ /(mac os x) ?([\w\. ]*)/i, - /(macintosh|mac_powerpc\b)(?!.+haiku)/i // Mac OS + /(macintosh|mac_powerpc\b)(?!.+(haiku|morphos))/i // Mac OS ], [[NAME, 'macOS'], [VERSION, /_/g, '.']], [ // Google Chromecast @@ -942,12 +982,13 @@ ], [VERSION, [NAME, CHROMECAST]], [ // Mobile OSes - /droid ([\w\.]+)\b.+(android[- ]x86|harmonyos)/i // Android-x86/HarmonyOS + /droid ([\w\.]+)\b.+(android[- ]x86)/i // Android-x86 ], [VERSION, NAME], [ /(ubuntu) ([\w\.]+) like android/i // Ubuntu Touch ], [[NAME, /(.+)/, '$1 Touch'], VERSION], [ + /(harmonyos)[\/ ]?([\d\.]*)/i, // HarmonyOS // Android/Blackberry/WebOS/QNX/Bada/RIM/KaiOS/Maemo/MeeGo/S40/Sailfish OS/OpenHarmony/Tizen - /(android|bada|blackberry|kaios|maemo|meego|openharmony|qnx|rim tablet os|sailfish|series40|symbian|tizen|webos)\w*[-\/\.; ]?([\d\.]*)/i + /(android|bada|blackberry|kaios|maemo|meego|openharmony|qnx|rim tablet os|sailfish|series40|symbian|tizen)\w*[-\/\.; ]?([\d\.]*)/i ], [NAME, VERSION], [ /\(bb(10);/i // BlackBerry 10 ], [VERSION, [NAME, BLACKBERRY]], [ @@ -955,9 +996,12 @@ ], [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 + /\b(?:hp)?wos(?:browser)?\/([\w\.]+)/i, // WebOS + /webos(?:[ \/]?|\.tv-20(?=2[2-9]))(\d[\d\.]*)/i ], [VERSION, [NAME, 'webOS']], [ + /web0s;.+?(?:chr[o0]me|safari)\/(\d+)/i + // https://webostv.developer.lge.com/develop/specifications/web-api-and-web-engine + ], [[VERSION, strMapper, {'25':'120','24':'108','23':'94','22':'87','6':'79','5':'68','4':'53','3':'38','2':'538','1':'537','*':'TV'}], [NAME, 'webOS']], [ /watch(?: ?os[,\/]|\d,\d\/)([\d\.]+)/i // watchOS ], [VERSION, [NAME, 'watchOS']], [ @@ -977,20 +1021,20 @@ // 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)(?: arm\w*| x86\w*| ?)([\w\.]*)/i, // Hurd/Linux + /linux.+(mint)[\/\(\) ]?([\w\.]*)/i, // Mint + /(mageia|vectorlinux|fuchsia|arcaos|arch(?= ?linux))[;l ]([\d\.]*)/i, // Mageia/VectorLinux/Fuchsia/ArcaOS/Arch + /([kxln]?ubuntu|debian|suse|opensuse|gentoo|slackware|fedora|mandriva|centos|pclinuxos|red ?hat|zenwalk|linpus|raspbian|plan 9|minix|risc os|contiki|deepin|manjaro|elementary os|sabayon|linspire|knoppix)(?: gnu[\/ ]linux)?(?: enterprise)?(?:[- ]linux)?(?:-gnu)?[-\/ ]?(?!chrom|package)([-\w\.]*)/i, + // Ubuntu/Debian/SUSE/Gentoo/Slackware/Fedora/Mandriva/CentOS/PCLinuxOS/RedHat/Zenwalk/Linpus/Raspbian/Plan9/Minix/RISCOS/Contiki/Deepin/Manjaro/elementary/Sabayon/Linspire/Knoppix + /((?:open)?solaris)[-\/ ]?([\w\.]*)/i, // Solaris + /\b(aix)[; ]([1-9\.]{0,4})/i, // AIX + /(hurd|linux|morphos)(?: (?:arm|x86|ppc)\w*| ?)([\w\.]*)/i, // Hurd/Linux/MorphOS /(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 + /(haiku) ?(r\d)?/i // Haiku ], [NAME, VERSION], [ - /(sunos) ?([\w\.\d]*)/i // Solaris + /(sunos) ?([\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|serenityos)/i, // BeOS/OS2/AmigaOS/MorphOS/OpenVMS/Fuchsia/HP-UX/SerenityOS + /\b(beos|os\/2|amigaos|openvms|hp-ux|serenityos)/i, // BeOS/OS2/AmigaOS/OpenVMS/HP-UX/SerenityOS /(unix) ?([\w\.]*)/i // UNIX ], [NAME, VERSION] ] @@ -1224,21 +1268,20 @@ for (var i in brands) { var brandName = brands[i].brand || brands[i], brandVersion = brands[i].version; - if (this.itemType == UA_BROWSER && !/not.a.brand/i.test(brandName) && (!prevName || (/chrom/i.test(prevName) && brandName != CHROMIUM))) { - brandName = strMapper(brandName, { - 'Chrome' : 'Google Chrome', - 'Edge' : 'Microsoft Edge', - 'Chrome WebView' : 'Android WebView', - 'Chrome Headless' : 'HeadlessChrome', - 'Huawei Browser' : 'HuaweiBrowser', - 'MIUI Browser' : 'Miui Browser', - 'Opera Mobi' : 'OperaMobile', - 'Yandex' : 'YaBrowser' - }); - this.set(NAME, brandName) - .set(VERSION, brandVersion) - .set(MAJOR, majorize(brandVersion)); - prevName = brandName; + if (this.itemType == UA_BROWSER && + !/not.a.brand/i.test(brandName) && + (!prevName || + (/Chrom/.test(prevName) && brandName != CHROMIUM) || + (prevName == EDGE && /WebView2/.test(brandName)) + )) { + brandName = strMapper(brandName, browserHintsMap); + prevName = this.get(NAME); + if (!(prevName && !/Chrom/.test(prevName) && /Chrom/.test(brandName))) { + this.set(NAME, brandName) + .set(VERSION, brandVersion) + .set(MAJOR, majorize(brandVersion)); + } + prevName = brandName; } if (this.itemType == UA_ENGINE && brandName == CHROMIUM) { this.set(VERSION, brandVersion);