UNPKG

@junobuild/analytics

Version:

Tracker for Juno analytics

4 lines 126 kB
{ "version": 3, "sources": ["../../../../node_modules/web-vitals/dist/web-vitals.js", "../../node_modules/ua-parser-js/src/ua-parser.js", "../../../../node_modules/nanoid/index.js", "../../../../node_modules/nanoid/url-alphabet/index.js", "../../src/constants/container.constants.ts", "../../src/utils/dfinity/nullish.utils.ts", "../../src/utils/dfinity/json.utils.ts", "../../src/api/orbiter.api.ts", "../../src/services/orbiter.services.ts", "../../src/utils/date.utils.ts", "../../src/utils/analytics.utils.ts", "../../src/services/performance.services.ts", "../../src/services/user-agent.services.ts", "../../src/utils/dfinity/asserts.utils.ts", "../../src/utils/env.utils.ts", "../../src/utils/log.utils.ts", "../../src/tracker.ts", "../../src/utils/window.env.utils.ts", "../../src/index.ts"], "sourcesContent": ["let e=-1;const t=t=>{addEventListener(\"pageshow\",(n=>{n.persisted&&(e=n.timeStamp,t(n))}),!0)},n=(e,t,n,i)=>{let o,s;return r=>{t.value>=0&&(r||i)&&(s=t.value-(o??0),(s||void 0===o)&&(o=t.value,t.delta=s,t.rating=((e,t)=>e>t[1]?\"poor\":e>t[0]?\"needs-improvement\":\"good\")(t.value,n),e(t)))}},i=e=>{requestAnimationFrame((()=>requestAnimationFrame((()=>e()))))},o=()=>{const e=performance.getEntriesByType(\"navigation\")[0];if(e&&e.responseStart>0&&e.responseStart<performance.now())return e},s=()=>{const e=o();return e?.activationStart??0},r=(t,n=-1)=>{const i=o();let r=\"navigate\";e>=0?r=\"back-forward-cache\":i&&(document.prerendering||s()>0?r=\"prerender\":document.wasDiscarded?r=\"restore\":i.type&&(r=i.type.replace(/_/g,\"-\")));return{name:t,value:n,rating:\"good\",delta:0,entries:[],id:`v5-${Date.now()}-${Math.floor(8999999999999*Math.random())+1e12}`,navigationType:r}},c=new WeakMap;function a(e,t){return c.get(e)||c.set(e,new t),c.get(e)}class d{t;i=0;o=[];h(e){if(e.hadRecentInput)return;const t=this.o[0],n=this.o.at(-1);this.i&&t&&n&&e.startTime-n.startTime<1e3&&e.startTime-t.startTime<5e3?(this.i+=e.value,this.o.push(e)):(this.i=e.value,this.o=[e]),this.t?.(e)}}const h=(e,t,n={})=>{try{if(PerformanceObserver.supportedEntryTypes.includes(e)){const i=new PerformanceObserver((e=>{Promise.resolve().then((()=>{t(e.getEntries())}))}));return i.observe({type:e,buffered:!0,...n}),i}}catch{}},f=e=>{let t=!1;return()=>{t||(e(),t=!0)}};let u=-1;const l=()=>\"hidden\"!==document.visibilityState||document.prerendering?1/0:0,m=e=>{\"hidden\"===document.visibilityState&&u>-1&&(u=\"visibilitychange\"===e.type?e.timeStamp:0,v())},g=()=>{addEventListener(\"visibilitychange\",m,!0),addEventListener(\"prerenderingchange\",m,!0)},v=()=>{removeEventListener(\"visibilitychange\",m,!0),removeEventListener(\"prerenderingchange\",m,!0)},p=()=>{if(u<0){const e=s(),n=document.prerendering?void 0:globalThis.performance.getEntriesByType(\"visibility-state\").filter((t=>\"hidden\"===t.name&&t.startTime>e))[0]?.startTime;u=n??l(),g(),t((()=>{setTimeout((()=>{u=l(),g()}))}))}return{get firstHiddenTime(){return u}}},y=e=>{document.prerendering?addEventListener(\"prerenderingchange\",(()=>e()),!0):e()},b=[1800,3e3],P=(e,o={})=>{y((()=>{const c=p();let a,d=r(\"FCP\");const f=h(\"paint\",(e=>{for(const t of e)\"first-contentful-paint\"===t.name&&(f.disconnect(),t.startTime<c.firstHiddenTime&&(d.value=Math.max(t.startTime-s(),0),d.entries.push(t),a(!0)))}));f&&(a=n(e,d,b,o.reportAllChanges),t((t=>{d=r(\"FCP\"),a=n(e,d,b,o.reportAllChanges),i((()=>{d.value=performance.now()-t.timeStamp,a(!0)}))})))}))},T=[.1,.25],E=(e,o={})=>{P(f((()=>{let s,c=r(\"CLS\",0);const f=a(o,d),u=e=>{for(const t of e)f.h(t);f.i>c.value&&(c.value=f.i,c.entries=f.o,s())},l=h(\"layout-shift\",u);l&&(s=n(e,c,T,o.reportAllChanges),document.addEventListener(\"visibilitychange\",(()=>{\"hidden\"===document.visibilityState&&(u(l.takeRecords()),s(!0))})),t((()=>{f.i=0,c=r(\"CLS\",0),s=n(e,c,T,o.reportAllChanges),i((()=>s()))})),setTimeout(s))})))};let _=0,L=1/0,M=0;const C=e=>{for(const t of e)t.interactionId&&(L=Math.min(L,t.interactionId),M=Math.max(M,t.interactionId),_=M?(M-L)/7+1:0)};let I;const w=()=>I?_:performance.interactionCount??0,F=()=>{\"interactionCount\"in performance||I||(I=h(\"event\",C,{type:\"event\",buffered:!0,durationThreshold:0}))};let k=0;class A{u=[];l=new Map;m;v;p(){k=w(),this.u.length=0,this.l.clear()}P(){const e=Math.min(this.u.length-1,Math.floor((w()-k)/50));return this.u[e]}h(e){if(this.m?.(e),!e.interactionId&&\"first-input\"!==e.entryType)return;const t=this.u.at(-1);let n=this.l.get(e.interactionId);if(n||this.u.length<10||e.duration>t.T){if(n?e.duration>n.T?(n.entries=[e],n.T=e.duration):e.duration===n.T&&e.startTime===n.entries[0].startTime&&n.entries.push(e):(n={id:e.interactionId,entries:[e],T:e.duration},this.l.set(n.id,n),this.u.push(n)),this.u.sort(((e,t)=>t.T-e.T)),this.u.length>10){const e=this.u.splice(10);for(const t of e)this.l.delete(t.id)}this.v?.(n)}}}const B=e=>{const t=globalThis.requestIdleCallback||setTimeout;\"hidden\"===document.visibilityState?e():(e=f(e),document.addEventListener(\"visibilitychange\",e,{once:!0}),t((()=>{e(),document.removeEventListener(\"visibilitychange\",e)})))},N=[200,500],S=(e,i={})=>{globalThis.PerformanceEventTiming&&\"interactionId\"in PerformanceEventTiming.prototype&&y((()=>{F();let o,s=r(\"INP\");const c=a(i,A),d=e=>{B((()=>{for(const t of e)c.h(t);const t=c.P();t&&t.T!==s.value&&(s.value=t.T,s.entries=t.entries,o())}))},f=h(\"event\",d,{durationThreshold:i.durationThreshold??40});o=n(e,s,N,i.reportAllChanges),f&&(f.observe({type:\"first-input\",buffered:!0}),document.addEventListener(\"visibilitychange\",(()=>{\"hidden\"===document.visibilityState&&(d(f.takeRecords()),o(!0))})),t((()=>{c.p(),s=r(\"INP\"),o=n(e,s,N,i.reportAllChanges)})))}))};class q{m;h(e){this.m?.(e)}}const x=[2500,4e3],O=(e,o={})=>{y((()=>{const c=p();let d,u=r(\"LCP\");const l=a(o,q),m=e=>{o.reportAllChanges||(e=e.slice(-1));for(const t of e)l.h(t),t.startTime<c.firstHiddenTime&&(u.value=Math.max(t.startTime-s(),0),u.entries=[t],d())},g=h(\"largest-contentful-paint\",m);if(g){d=n(e,u,x,o.reportAllChanges);const s=f((()=>{m(g.takeRecords()),g.disconnect(),d(!0)}));for(const e of[\"keydown\",\"click\",\"visibilitychange\"])addEventListener(e,(()=>B(s)),{capture:!0,once:!0});t((t=>{u=r(\"LCP\"),d=n(e,u,x,o.reportAllChanges),i((()=>{u.value=performance.now()-t.timeStamp,d(!0)}))}))}}))},$=[800,1800],D=e=>{document.prerendering?y((()=>D(e))):\"complete\"!==document.readyState?addEventListener(\"load\",(()=>D(e)),!0):setTimeout(e)},H=(e,i={})=>{let c=r(\"TTFB\"),a=n(e,c,$,i.reportAllChanges);D((()=>{const d=o();d&&(c.value=Math.max(d.responseStart-s(),0),c.entries=[d],a(!0),t((()=>{c=r(\"TTFB\",0),a=n(e,c,$,i.reportAllChanges),a(!0)})))}))};export{T as CLSThresholds,b as FCPThresholds,N as INPThresholds,x as LCPThresholds,$ as TTFBThresholds,E as onCLS,P as onFCP,S as onINP,O as onLCP,H as onTTFB};\n", "/////////////////////////////////////////////////////////////////////////////////\n/* UAParser.js v1.0.40\n Copyright \u00A9 2012-2024 Faisal Salman <f@faisalman.com>\n MIT License *//*\n Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data.\n Supports browser & node.js environment. \n Demo : https://faisalman.github.io/ua-parser-js\n Source : https://github.com/faisalman/ua-parser-js */\n/////////////////////////////////////////////////////////////////////////////////\n\n(function (window, undefined) {\n\n 'use strict';\n\n //////////////\n // Constants\n /////////////\n\n\n var LIBVERSION = '1.0.40',\n EMPTY = '',\n UNKNOWN = '?',\n FUNC_TYPE = 'function',\n UNDEF_TYPE = 'undefined',\n OBJ_TYPE = 'object',\n STR_TYPE = 'string',\n MAJOR = 'major',\n MODEL = 'model',\n NAME = 'name',\n TYPE = 'type',\n VENDOR = 'vendor',\n VERSION = 'version',\n ARCHITECTURE= 'architecture',\n CONSOLE = 'console',\n MOBILE = 'mobile',\n TABLET = 'tablet',\n SMARTTV = 'smarttv',\n WEARABLE = 'wearable',\n EMBEDDED = 'embedded',\n UA_MAX_LENGTH = 500;\n\n var AMAZON = 'Amazon',\n APPLE = 'Apple',\n ASUS = 'ASUS',\n BLACKBERRY = 'BlackBerry',\n BROWSER = 'Browser',\n CHROME = 'Chrome',\n EDGE = 'Edge',\n FIREFOX = 'Firefox',\n GOOGLE = 'Google',\n HUAWEI = 'Huawei',\n LG = 'LG',\n MICROSOFT = 'Microsoft',\n MOTOROLA = 'Motorola',\n OPERA = 'Opera',\n SAMSUNG = 'Samsung',\n SHARP = 'Sharp',\n SONY = 'Sony',\n XIAOMI = 'Xiaomi',\n ZEBRA = 'Zebra',\n FACEBOOK = 'Facebook',\n CHROMIUM_OS = 'Chromium OS',\n MAC_OS = 'Mac OS',\n SUFFIX_BROWSER = ' Browser';\n\n ///////////\n // Helper\n //////////\n\n var extend = function (regexes, extensions) {\n var mergedRegexes = {};\n for (var i in regexes) {\n if (extensions[i] && extensions[i].length % 2 === 0) {\n mergedRegexes[i] = extensions[i].concat(regexes[i]);\n } else {\n mergedRegexes[i] = regexes[i];\n }\n }\n return mergedRegexes;\n },\n enumerize = function (arr) {\n var enums = {};\n for (var i=0; i<arr.length; i++) {\n enums[arr[i].toUpperCase()] = arr[i];\n }\n return enums;\n },\n has = function (str1, str2) {\n return typeof str1 === STR_TYPE ? lowerize(str2).indexOf(lowerize(str1)) !== -1 : false;\n },\n lowerize = function (str) {\n return str.toLowerCase();\n },\n majorize = function (version) {\n return typeof(version) === STR_TYPE ? version.replace(/[^\\d\\.]/g, EMPTY).split('.')[0] : undefined;\n },\n trim = function (str, len) {\n if (typeof(str) === STR_TYPE) {\n str = str.replace(/^\\s\\s*/, EMPTY);\n return typeof(len) === UNDEF_TYPE ? str : str.substring(0, UA_MAX_LENGTH);\n }\n };\n\n ///////////////\n // Map helper\n //////////////\n\n var rgxMapper = function (ua, arrays) {\n\n var i = 0, j, k, p, q, matches, match;\n\n // loop through all regexes maps\n while (i < arrays.length && !matches) {\n\n var regex = arrays[i], // even sequence (0,2,4,..)\n props = arrays[i + 1]; // odd sequence (1,3,5,..)\n j = k = 0;\n\n // try matching uastring with regexes\n while (j < regex.length && !matches) {\n\n if (!regex[j]) { break; }\n matches = regex[j++].exec(ua);\n\n if (!!matches) {\n for (p = 0; p < props.length; p++) {\n match = matches[++k];\n q = props[p];\n // check if given property is actually array\n if (typeof q === OBJ_TYPE && q.length > 0) {\n if (q.length === 2) {\n if (typeof q[1] == FUNC_TYPE) {\n // assign modified match\n this[q[0]] = q[1].call(this, match);\n } else {\n // assign given value, ignore regex match\n this[q[0]] = q[1];\n }\n } else if (q.length === 3) {\n // check whether function or regex\n if (typeof q[1] === FUNC_TYPE && !(q[1].exec && q[1].test)) {\n // call function (usually string mapper)\n this[q[0]] = match ? q[1].call(this, match, q[2]) : undefined;\n } else {\n // sanitize match using given regex\n this[q[0]] = match ? match.replace(q[1], q[2]) : undefined;\n }\n } else if (q.length === 4) {\n this[q[0]] = match ? q[3].call(this, match.replace(q[1], q[2])) : undefined;\n }\n } else {\n this[q] = match ? match : undefined;\n }\n }\n }\n }\n i += 2;\n }\n },\n\n strMapper = function (str, map) {\n\n for (var i in map) {\n // check if current value is array\n if (typeof map[i] === OBJ_TYPE && map[i].length > 0) {\n for (var j = 0; j < map[i].length; j++) {\n if (has(map[i][j], str)) {\n return (i === UNKNOWN) ? undefined : i;\n }\n }\n } else if (has(map[i], str)) {\n return (i === UNKNOWN) ? undefined : i;\n }\n }\n return map.hasOwnProperty('*') ? map['*'] : str;\n };\n\n ///////////////\n // String map\n //////////////\n\n // Safari < 3.0\n var oldSafariMap = {\n '1.0' : '/8',\n '1.2' : '/1',\n '1.3' : '/3',\n '2.0' : '/412',\n '2.0.2' : '/416',\n '2.0.3' : '/417',\n '2.0.4' : '/419',\n '?' : '/'\n },\n windowsVersionMap = {\n 'ME' : '4.90',\n 'NT 3.11' : 'NT3.51',\n 'NT 4.0' : 'NT4.0',\n '2000' : 'NT 5.0',\n 'XP' : ['NT 5.1', 'NT 5.2'],\n 'Vista' : 'NT 6.0',\n '7' : 'NT 6.1',\n '8' : 'NT 6.2',\n '8.1' : 'NT 6.3',\n '10' : ['NT 6.4', 'NT 10.0'],\n 'RT' : 'ARM'\n };\n\n //////////////\n // Regex map\n /////////////\n\n var regexes = {\n\n browser : [[\n\n /\\b(?:crmo|crios)\\/([\\w\\.]+)/i // Chrome for Android/iOS\n ], [VERSION, [NAME, 'Chrome']], [\n /edg(?:e|ios|a)?\\/([\\w\\.]+)/i // Microsoft Edge\n ], [VERSION, [NAME, 'Edge']], [\n\n // Presto based\n /(opera mini)\\/([-\\w\\.]+)/i, // Opera Mini\n /(opera [mobiletab]{3,6})\\b.+version\\/([-\\w\\.]+)/i, // Opera Mobi/Tablet\n /(opera)(?:.+version\\/|[\\/ ]+)([\\w\\.]+)/i // Opera\n ], [NAME, VERSION], [\n /opios[\\/ ]+([\\w\\.]+)/i // Opera mini on iphone >= 8.0\n ], [VERSION, [NAME, OPERA+' Mini']], [\n /\\bop(?:rg)?x\\/([\\w\\.]+)/i // Opera GX\n ], [VERSION, [NAME, OPERA+' GX']], [\n /\\bopr\\/([\\w\\.]+)/i // Opera Webkit\n ], [VERSION, [NAME, OPERA]], [\n\n // Mixed\n /\\bb[ai]*d(?:uhd|[ub]*[aekoprswx]{5,6})[\\/ ]?([\\w\\.]+)/i // Baidu\n ], [VERSION, [NAME, 'Baidu']], [\n /\\b(?:mxbrowser|mxios|myie2)\\/?([-\\w\\.]*)\\b/i // Maxthon\n ], [VERSION, [NAME, 'Maxthon']], [\n /(kindle)\\/([\\w\\.]+)/i, // Kindle\n /(lunascape|maxthon|netfront|jasmine|blazer|sleipnir)[\\/ ]?([\\w\\.]*)/i, \n // Lunascape/Maxthon/Netfront/Jasmine/Blazer/Sleipnir\n // Trident based\n /(avant|iemobile|slim(?:browser|boat|jet))[\\/ ]?([\\d\\.]*)/i, // Avant/IEMobile/SlimBrowser/SlimBoat/Slimjet\n /(?:ms|\\()(ie) ([\\w\\.]+)/i, // Internet Explorer\n\n // Blink/Webkit/KHTML based // Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS/Bowser/QupZilla/Falkon\n /(flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi|iridium|phantomjs|bowser|qupzilla|falkon|rekonq|puffin|brave|whale(?!.+naver)|qqbrowserlite|duckduckgo|klar|helio|(?=comodo_)?dragon)\\/([-\\w\\.]+)/i,\n // Rekonq/Puffin/Brave/Whale/QQBrowserLite/QQ//Vivaldi/DuckDuckGo/Klar/Helio/Dragon\n /(heytap|ovi|115)browser\\/([\\d\\.]+)/i, // HeyTap/Ovi/115\n /(weibo)__([\\d\\.]+)/i // Weibo\n ], [NAME, VERSION], [\n /quark(?:pc)?\\/([-\\w\\.]+)/i // Quark\n ], [VERSION, [NAME, 'Quark']], [\n /\\bddg\\/([\\w\\.]+)/i // DuckDuckGo\n ], [VERSION, [NAME, 'DuckDuckGo']], [\n /(?:\\buc? ?browser|(?:juc.+)ucweb)[\\/ ]?([\\w\\.]+)/i // UCBrowser\n ], [VERSION, [NAME, 'UC'+BROWSER]], [\n /microm.+\\bqbcore\\/([\\w\\.]+)/i, // WeChat Desktop for Windows Built-in Browser\n /\\bqbcore\\/([\\w\\.]+).+microm/i,\n /micromessenger\\/([\\w\\.]+)/i // WeChat\n ], [VERSION, [NAME, 'WeChat']], [\n /konqueror\\/([\\w\\.]+)/i // Konqueror\n ], [VERSION, [NAME, 'Konqueror']], [\n /trident.+rv[: ]([\\w\\.]{1,9})\\b.+like gecko/i // IE11\n ], [VERSION, [NAME, 'IE']], [\n /ya(?:search)?browser\\/([\\w\\.]+)/i // Yandex\n ], [VERSION, [NAME, 'Yandex']], [\n /slbrowser\\/([\\w\\.]+)/i // Smart Lenovo Browser\n ], [VERSION, [NAME, 'Smart Lenovo '+BROWSER]], [\n /(avast|avg)\\/([\\w\\.]+)/i // Avast/AVG Secure Browser\n ], [[NAME, /(.+)/, '$1 Secure '+BROWSER], VERSION], [\n /\\bfocus\\/([\\w\\.]+)/i // Firefox Focus\n ], [VERSION, [NAME, FIREFOX+' Focus']], [\n /\\bopt\\/([\\w\\.]+)/i // Opera Touch\n ], [VERSION, [NAME, OPERA+' Touch']], [\n /coc_coc\\w+\\/([\\w\\.]+)/i // Coc Coc Browser\n ], [VERSION, [NAME, 'Coc Coc']], [\n /dolfin\\/([\\w\\.]+)/i // Dolphin\n ], [VERSION, [NAME, 'Dolphin']], [\n /coast\\/([\\w\\.]+)/i // Opera Coast\n ], [VERSION, [NAME, OPERA+' Coast']], [\n /miuibrowser\\/([\\w\\.]+)/i // MIUI Browser\n ], [VERSION, [NAME, 'MIUI' + SUFFIX_BROWSER]], [\n /fxios\\/([\\w\\.-]+)/i // Firefox for iOS\n ], [VERSION, [NAME, FIREFOX]], [\n /\\bqihoobrowser\\/?([\\w\\.]*)/i // 360\n ], [VERSION, [NAME, '360']], [\n /\\b(qq)\\/([\\w\\.]+)/i // QQ\n ], [[NAME, /(.+)/, '$1Browser'], VERSION], [\n /(oculus|sailfish|huawei|vivo|pico)browser\\/([\\w\\.]+)/i\n ], [[NAME, /(.+)/, '$1' + SUFFIX_BROWSER], VERSION], [ // Oculus/Sailfish/HuaweiBrowser/VivoBrowser/PicoBrowser\n /samsungbrowser\\/([\\w\\.]+)/i // Samsung Internet\n ], [VERSION, [NAME, SAMSUNG + ' Internet']], [\n /metasr[\\/ ]?([\\d\\.]+)/i // Sogou Explorer\n ], [VERSION, [NAME, 'Sogou Explorer']], [\n /(sogou)mo\\w+\\/([\\d\\.]+)/i // Sogou Mobile\n ], [[NAME, 'Sogou Mobile'], VERSION], [\n /(electron)\\/([\\w\\.]+) safari/i, // Electron-based App\n /(tesla)(?: qtcarbrowser|\\/(20\\d\\d\\.[-\\w\\.]+))/i, // Tesla\n /m?(qqbrowser|2345(?=browser|chrome|explorer))\\w*[\\/ ]?v?([\\w\\.]+)/i // QQ/2345\n ], [NAME, VERSION], [\n /(lbbrowser|rekonq)/i, // LieBao Browser/Rekonq\n /\\[(linkedin)app\\]/i // LinkedIn App for iOS & Android\n ], [NAME], [\n /ome\\/([\\w\\.]+) \\w* ?(iron) saf/i, // Iron\n /ome\\/([\\w\\.]+).+qihu (360)[es]e/i // 360\n ], [VERSION, NAME], [\n\n // WebView\n /((?:fban\\/fbios|fb_iab\\/fb4a)(?!.+fbav)|;fbav\\/([\\w\\.]+);)/i // Facebook App for iOS & Android\n ], [[NAME, FACEBOOK], VERSION], [\n /(Klarna)\\/([\\w\\.]+)/i, // Klarna Shopping Browser for iOS & Android\n /(kakao(?:talk|story))[\\/ ]([\\w\\.]+)/i, // Kakao App\n /(naver)\\(.*?(\\d+\\.[\\w\\.]+).*\\)/i, // Naver InApp\n /safari (line)\\/([\\w\\.]+)/i, // Line App for iOS\n /\\b(line)\\/([\\w\\.]+)\\/iab/i, // Line App for Android\n /(alipay)client\\/([\\w\\.]+)/i, // Alipay\n /(twitter)(?:and| f.+e\\/([\\w\\.]+))/i, // Twitter\n /(chromium|instagram|snapchat)[\\/ ]([-\\w\\.]+)/i // Chromium/Instagram/Snapchat\n ], [NAME, VERSION], [\n /\\bgsa\\/([\\w\\.]+) .*safari\\//i // Google Search Appliance on iOS\n ], [VERSION, [NAME, 'GSA']], [\n /musical_ly(?:.+app_?version\\/|_)([\\w\\.]+)/i // TikTok\n ], [VERSION, [NAME, 'TikTok']], [\n\n /headlesschrome(?:\\/([\\w\\.]+)| )/i // Chrome Headless\n ], [VERSION, [NAME, CHROME+' Headless']], [\n\n / wv\\).+(chrome)\\/([\\w\\.]+)/i // Chrome WebView\n ], [[NAME, CHROME+' WebView'], VERSION], [\n\n /droid.+ version\\/([\\w\\.]+)\\b.+(?:mobile safari|safari)/i // Android Browser\n ], [VERSION, [NAME, 'Android '+BROWSER]], [\n\n /(chrome|omniweb|arora|[tizenoka]{5} ?browser)\\/v?([\\w\\.]+)/i // Chrome/OmniWeb/Arora/Tizen/Nokia\n ], [NAME, VERSION], [\n\n /version\\/([\\w\\.\\,]+) .*mobile\\/\\w+ (safari)/i // Mobile Safari\n ], [VERSION, [NAME, 'Mobile Safari']], [\n /version\\/([\\w(\\.|\\,)]+) .*(mobile ?safari|safari)/i // Safari & Safari Mobile\n ], [VERSION, NAME], [\n /webkit.+?(mobile ?safari|safari)(\\/[\\w\\.]+)/i // Safari < 3.0\n ], [NAME, [VERSION, strMapper, oldSafariMap]], [\n\n /(webkit|khtml)\\/([\\w\\.]+)/i\n ], [NAME, VERSION], [\n\n // Gecko based\n /(navigator|netscape\\d?)\\/([-\\w\\.]+)/i // Netscape\n ], [[NAME, 'Netscape'], VERSION], [\n /(wolvic|librewolf)\\/([\\w\\.]+)/i // Wolvic/LibreWolf\n ], [NAME, VERSION], [\n /mobile vr; rv:([\\w\\.]+)\\).+firefox/i // Firefox Reality\n ], [VERSION, [NAME, FIREFOX+' Reality']], [\n /ekiohf.+(flow)\\/([\\w\\.]+)/i, // Flow\n /(swiftfox)/i, // Swiftfox\n /(icedragon|iceweasel|camino|chimera|fennec|maemo browser|minimo|conkeror)[\\/ ]?([\\w\\.\\+]+)/i,\n // IceDragon/Iceweasel/Camino/Chimera/Fennec/Maemo/Minimo/Conkeror\n /(seamonkey|k-meleon|icecat|iceape|firebird|phoenix|palemoon|basilisk|waterfox)\\/([-\\w\\.]+)$/i,\n // Firefox/SeaMonkey/K-Meleon/IceCat/IceApe/Firebird/Phoenix\n /(firefox)\\/([\\w\\.]+)/i, // Other Firefox-based\n /(mozilla)\\/([\\w\\.]+) .+rv\\:.+gecko\\/\\d+/i, // Mozilla\n\n // Other\n /(polaris|lynx|dillo|icab|doris|amaya|w3m|netsurf|obigo|mosaic|(?:go|ice|up)[\\. ]?browser)[-\\/ ]?v?([\\w\\.]+)/i,\n // Polaris/Lynx/Dillo/iCab/Doris/Amaya/w3m/NetSurf/Obigo/Mosaic/Go/ICE/UP.Browser\n /(links) \\(([\\w\\.]+)/i // Links\n ], [NAME, [VERSION, /_/g, '.']], [\n \n /(cobalt)\\/([\\w\\.]+)/i // Cobalt\n ], [NAME, [VERSION, /master.|lts./, \"\"]]\n ],\n\n cpu : [[\n\n /(?:(amd|x(?:(?:86|64)[-_])?|wow|win)64)[;\\)]/i // AMD64 (x64)\n ], [[ARCHITECTURE, 'amd64']], [\n\n /(ia32(?=;))/i // IA32 (quicktime)\n ], [[ARCHITECTURE, lowerize]], [\n\n /((?:i[346]|x)86)[;\\)]/i // IA32 (x86)\n ], [[ARCHITECTURE, 'ia32']], [\n\n /\\b(aarch64|arm(v?8e?l?|_?64))\\b/i // ARM64\n ], [[ARCHITECTURE, 'arm64']], [\n\n /\\b(arm(?:v[67])?ht?n?[fl]p?)\\b/i // ARMHF\n ], [[ARCHITECTURE, 'armhf']], [\n\n // PocketPC mistakenly identified as PowerPC\n /windows (ce|mobile); ppc;/i\n ], [[ARCHITECTURE, 'arm']], [\n\n /((?:ppc|powerpc)(?:64)?)(?: mac|;|\\))/i // PowerPC\n ], [[ARCHITECTURE, /ower/, EMPTY, lowerize]], [\n\n /(sun4\\w)[;\\)]/i // SPARC\n ], [[ARCHITECTURE, 'sparc']], [\n\n /((?:avr32|ia64(?=;))|68k(?=\\))|\\barm(?=v(?:[1-7]|[5-7]1)l?|;|eabi)|(?=atmel )avr|(?:irix|mips|sparc)(?:64)?\\b|pa-risc)/i\n // IA64, 68K, ARM/64, AVR/32, IRIX/64, MIPS/64, SPARC/64, PA-RISC\n ], [[ARCHITECTURE, lowerize]]\n ],\n\n device : [[\n\n //////////////////////////\n // MOBILES & TABLETS\n /////////////////////////\n\n // Samsung\n /\\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\n ], [MODEL, [VENDOR, SAMSUNG], [TYPE, TABLET]], [\n /\\b((?:s[cgp]h|gt|sm)-(?![lr])\\w+|sc[g-]?[\\d]+a?|galaxy nexus)/i,\n /samsung[- ]((?!sm-[lr])[-\\w]+)/i,\n /sec-(sgh\\w+)/i\n ], [MODEL, [VENDOR, SAMSUNG], [TYPE, MOBILE]], [\n\n // Apple\n /(?:\\/|\\()(ip(?:hone|od)[\\w, ]*)(?:\\/|;)/i // iPod/iPhone\n ], [MODEL, [VENDOR, APPLE], [TYPE, MOBILE]], [\n /\\((ipad);[-\\w\\),; ]+apple/i, // iPad\n /applecoremedia\\/[\\w\\.]+ \\((ipad)/i,\n /\\b(ipad)\\d\\d?,\\d\\d?[;\\]].+ios/i\n ], [MODEL, [VENDOR, APPLE], [TYPE, TABLET]], [\n /(macintosh);/i\n ], [MODEL, [VENDOR, APPLE]], [\n\n // Sharp\n /\\b(sh-?[altvz]?\\d\\d[a-ekm]?)/i\n ], [MODEL, [VENDOR, SHARP], [TYPE, MOBILE]], [\n\n // Honor\n /(?:honor)([-\\w ]+)[;\\)]/i\n ], [MODEL, [VENDOR, 'Honor'], [TYPE, MOBILE]], [\n\n // Huawei\n /\\b((?:ag[rs][23]?|bah2?|sht?|btv)-a?[lw]\\d{2})\\b(?!.+d\\/s)/i\n ], [MODEL, [VENDOR, HUAWEI], [TYPE, TABLET]], [\n /(?:huawei)([-\\w ]+)[;\\)]/i,\n /\\b(nexus 6p|\\w{2,4}e?-[atu]?[ln][\\dx][012359c][adn]?)\\b(?!.+d\\/s)/i\n ], [MODEL, [VENDOR, HUAWEI], [TYPE, MOBILE]], [\n\n // Xiaomi\n /\\b(poco[\\w ]+|m2\\d{3}j\\d\\d[a-z]{2})(?: bui|\\))/i, // Xiaomi POCO\n /\\b; (\\w+) build\\/hm\\1/i, // Xiaomi Hongmi 'numeric' models\n /\\b(hm[-_ ]?note?[_ ]?(?:\\d\\w)?) bui/i, // Xiaomi Hongmi\n /\\b(redmi[\\-_ ]?(?:note|k)?[\\w_ ]+)(?: bui|\\))/i, // Xiaomi Redmi\n /oid[^\\)]+; (m?[12][0-389][01]\\w{3,6}[c-y])( bui|; wv|\\))/i, // Xiaomi Redmi 'numeric' models\n /\\b(mi[-_ ]?(?:a\\d|one|one[_ ]plus|note lte|max|cc)?[_ ]?(?:\\d?\\w?)[_ ]?(?:plus|se|lite|pro)?)(?: bui|\\))/i // Xiaomi Mi\n ], [[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, MOBILE]], [\n /oid[^\\)]+; (2\\d{4}(283|rpbf)[cgl])( bui|\\))/i, // Redmi Pad\n /\\b(mi[-_ ]?(?:pad)(?:[\\w_ ]+))(?: bui|\\))/i // Mi Pad tablets\n ],[[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, TABLET]], [\n\n // OPPO\n /; (\\w+) bui.+ oppo/i,\n /\\b(cph[12]\\d{3}|p(?:af|c[al]|d\\w|e[ar])[mt]\\d0|x9007|a101op)\\b/i\n ], [MODEL, [VENDOR, 'OPPO'], [TYPE, MOBILE]], [\n /\\b(opd2\\d{3}a?) bui/i\n ], [MODEL, [VENDOR, 'OPPO'], [TYPE, TABLET]], [\n\n // Vivo\n /vivo (\\w+)(?: bui|\\))/i,\n /\\b(v[12]\\d{3}\\w?[at])(?: bui|;)/i\n ], [MODEL, [VENDOR, 'Vivo'], [TYPE, MOBILE]], [\n\n // Realme\n /\\b(rmx[1-3]\\d{3})(?: bui|;|\\))/i\n ], [MODEL, [VENDOR, 'Realme'], [TYPE, MOBILE]], [\n\n // Motorola\n /\\b(milestone|droid(?:[2-4x]| (?:bionic|x2|pro|razr))?:?( 4g)?)\\b[\\w ]+build\\//i,\n /\\bmot(?:orola)?[- ](\\w*)/i,\n /((?:moto[\\w\\(\\) ]+|xt\\d{3,4}|nexus 6)(?= bui|\\)))/i\n ], [MODEL, [VENDOR, MOTOROLA], [TYPE, MOBILE]], [\n /\\b(mz60\\d|xoom[2 ]{0,2}) build\\//i\n ], [MODEL, [VENDOR, MOTOROLA], [TYPE, TABLET]], [\n\n // LG\n /((?=lg)?[vl]k\\-?\\d{3}) bui| 3\\.[-\\w; ]{10}lg?-([06cv9]{3,4})/i\n ], [MODEL, [VENDOR, LG], [TYPE, TABLET]], [\n /(lm(?:-?f100[nv]?|-[\\w\\.]+)(?= bui|\\))|nexus [45])/i,\n /\\blg[-e;\\/ ]+((?!browser|netcast|android tv)\\w+)/i,\n /\\blg-?([\\d\\w]+) bui/i\n ], [MODEL, [VENDOR, LG], [TYPE, MOBILE]], [\n\n // Lenovo\n /(ideatab[-\\w ]+)/i,\n /lenovo ?(s[56]000[-\\w]+|tab(?:[\\w ]+)|yt[-\\d\\w]{6}|tb[-\\d\\w]{6})/i\n ], [MODEL, [VENDOR, 'Lenovo'], [TYPE, TABLET]], [\n\n // Nokia\n /(?:maemo|nokia).*(n900|lumia \\d+)/i,\n /nokia[-_ ]?([-\\w\\.]*)/i\n ], [[MODEL, /_/g, ' '], [VENDOR, 'Nokia'], [TYPE, MOBILE]], [\n\n // Google\n /(pixel c)\\b/i // Google Pixel C\n ], [MODEL, [VENDOR, GOOGLE], [TYPE, TABLET]], [\n /droid.+; (pixel[\\daxl ]{0,6})(?: bui|\\))/i // Google Pixel\n ], [MODEL, [VENDOR, GOOGLE], [TYPE, MOBILE]], [\n\n // Sony\n /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\n ], [MODEL, [VENDOR, SONY], [TYPE, MOBILE]], [\n /sony tablet [ps]/i,\n /\\b(?:sony)?sgp\\w+(?: bui|\\))/i\n ], [[MODEL, 'Xperia Tablet'], [VENDOR, SONY], [TYPE, TABLET]], [\n\n // OnePlus\n / (kb2005|in20[12]5|be20[12][59])\\b/i,\n /(?:one)?(?:plus)? (a\\d0\\d\\d)(?: b|\\))/i\n ], [MODEL, [VENDOR, 'OnePlus'], [TYPE, MOBILE]], [\n\n // Amazon\n /(alexa)webm/i,\n /(kf[a-z]{2}wi|aeo(?!bc)\\w\\w)( bui|\\))/i, // Kindle Fire without Silk / Echo Show\n /(kf[a-z]+)( bui|\\)).+silk\\//i // Kindle Fire HD\n ], [MODEL, [VENDOR, AMAZON], [TYPE, TABLET]], [\n /((?:sd|kf)[0349hijorstuw]+)( bui|\\)).+silk\\//i // Fire Phone\n ], [[MODEL, /(.+)/g, 'Fire Phone $1'], [VENDOR, AMAZON], [TYPE, MOBILE]], [\n\n // BlackBerry\n /(playbook);[-\\w\\),; ]+(rim)/i // BlackBerry PlayBook\n ], [MODEL, VENDOR, [TYPE, TABLET]], [\n /\\b((?:bb[a-f]|st[hv])100-\\d)/i,\n /\\(bb10; (\\w+)/i // BlackBerry 10\n ], [MODEL, [VENDOR, BLACKBERRY], [TYPE, MOBILE]], [\n\n // Asus\n /(?:\\b|asus_)(transfo[prime ]{4,10} \\w+|eeepc|slider \\w+|nexus 7|padfone|p00[cj])/i\n ], [MODEL, [VENDOR, ASUS], [TYPE, TABLET]], [\n / (z[bes]6[027][012][km][ls]|zenfone \\d\\w?)\\b/i\n ], [MODEL, [VENDOR, ASUS], [TYPE, MOBILE]], [\n\n // HTC\n /(nexus 9)/i // HTC Nexus 9\n ], [MODEL, [VENDOR, 'HTC'], [TYPE, TABLET]], [\n /(htc)[-;_ ]{1,2}([\\w ]+(?=\\)| bui)|\\w+)/i, // HTC\n\n // ZTE\n /(zte)[- ]([\\w ]+?)(?: bui|\\/|\\))/i,\n /(alcatel|geeksphone|nexian|panasonic(?!(?:;|\\.))|sony(?!-bra))[-_ ]?([-\\w]*)/i // Alcatel/GeeksPhone/Nexian/Panasonic/Sony\n ], [VENDOR, [MODEL, /_/g, ' '], [TYPE, MOBILE]], [\n\n // TCL\n /droid [\\w\\.]+; ((?:8[14]9[16]|9(?:0(?:48|60|8[01])|1(?:3[27]|66)|2(?:6[69]|9[56])|466))[gqswx])\\w*(\\)| bui)/i\n ], [MODEL, [VENDOR, 'TCL'], [TYPE, TABLET]], [\n\n // itel\n /(itel) ((\\w+))/i\n ], [[VENDOR, lowerize], MODEL, [TYPE, strMapper, { 'tablet' : ['p10001l', 'w7001'], '*' : 'mobile' }]], [\n\n // Acer\n /droid.+; ([ab][1-7]-?[0178a]\\d\\d?)/i\n ], [MODEL, [VENDOR, 'Acer'], [TYPE, TABLET]], [\n\n // Meizu\n /droid.+; (m[1-5] note) bui/i,\n /\\bmz-([-\\w]{2,})/i\n ], [MODEL, [VENDOR, 'Meizu'], [TYPE, MOBILE]], [\n \n // Ulefone\n /; ((?:power )?armor(?:[\\w ]{0,8}))(?: bui|\\))/i\n ], [MODEL, [VENDOR, 'Ulefone'], [TYPE, MOBILE]], [\n\n // Energizer\n /; (energy ?\\w+)(?: bui|\\))/i,\n /; energizer ([\\w ]+)(?: bui|\\))/i\n ], [MODEL, [VENDOR, 'Energizer'], [TYPE, MOBILE]], [\n\n // Cat\n /; cat (b35);/i,\n /; (b15q?|s22 flip|s48c|s62 pro)(?: bui|\\))/i\n ], [MODEL, [VENDOR, 'Cat'], [TYPE, MOBILE]], [\n\n // Smartfren\n /((?:new )?andromax[\\w- ]+)(?: bui|\\))/i\n ], [MODEL, [VENDOR, 'Smartfren'], [TYPE, MOBILE]], [\n\n // Nothing\n /droid.+; (a(?:015|06[35]|142p?))/i\n ], [MODEL, [VENDOR, 'Nothing'], [TYPE, MOBILE]], [\n\n // MIXED\n /(blackberry|benq|palm(?=\\-)|sonyericsson|acer|asus|dell|meizu|motorola|polytron|infinix|tecno|micromax|advan)[-_ ]?([-\\w]*)/i,\n // BlackBerry/BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron/Infinix/Tecno/Micromax/Advan\n /; (imo) ((?!tab)[\\w ]+?)(?: bui|\\))/i, // IMO\n /(hp) ([\\w ]+\\w)/i, // HP iPAQ\n /(asus)-?(\\w+)/i, // Asus\n /(microsoft); (lumia[\\w ]+)/i, // Microsoft Lumia\n /(lenovo)[-_ ]?([-\\w]+)/i, // Lenovo\n /(jolla)/i, // Jolla\n /(oppo) ?([\\w ]+) bui/i // OPPO\n ], [VENDOR, MODEL, [TYPE, MOBILE]], [\n\n /(imo) (tab \\w+)/i, // IMO\n /(kobo)\\s(ereader|touch)/i, // Kobo\n /(archos) (gamepad2?)/i, // Archos\n /(hp).+(touchpad(?!.+tablet)|tablet)/i, // HP TouchPad\n /(kindle)\\/([\\w\\.]+)/i, // Kindle\n /(nook)[\\w ]+build\\/(\\w+)/i, // Nook\n /(dell) (strea[kpr\\d ]*[\\dko])/i, // Dell Streak\n /(le[- ]+pan)[- ]+(\\w{1,9}) bui/i, // Le Pan Tablets\n /(trinity)[- ]*(t\\d{3}) bui/i, // Trinity Tablets\n /(gigaset)[- ]+(q\\w{1,9}) bui/i, // Gigaset Tablets\n /(vodafone) ([\\w ]+)(?:\\)| bui)/i // Vodafone\n ], [VENDOR, MODEL, [TYPE, TABLET]], [\n\n /(surface duo)/i // Surface Duo\n ], [MODEL, [VENDOR, MICROSOFT], [TYPE, TABLET]], [\n /droid [\\d\\.]+; (fp\\du?)(?: b|\\))/i // Fairphone\n ], [MODEL, [VENDOR, 'Fairphone'], [TYPE, MOBILE]], [\n /(u304aa)/i // AT&T\n ], [MODEL, [VENDOR, 'AT&T'], [TYPE, MOBILE]], [\n /\\bsie-(\\w*)/i // Siemens\n ], [MODEL, [VENDOR, 'Siemens'], [TYPE, MOBILE]], [\n /\\b(rct\\w+) b/i // RCA Tablets\n ], [MODEL, [VENDOR, 'RCA'], [TYPE, TABLET]], [\n /\\b(venue[\\d ]{2,7}) b/i // Dell Venue Tablets\n ], [MODEL, [VENDOR, 'Dell'], [TYPE, TABLET]], [\n /\\b(q(?:mv|ta)\\w+) b/i // Verizon Tablet\n ], [MODEL, [VENDOR, 'Verizon'], [TYPE, TABLET]], [\n /\\b(?:barnes[& ]+noble |bn[rt])([\\w\\+ ]*) b/i // Barnes & Noble Tablet\n ], [MODEL, [VENDOR, 'Barnes & Noble'], [TYPE, TABLET]], [\n /\\b(tm\\d{3}\\w+) b/i\n ], [MODEL, [VENDOR, 'NuVision'], [TYPE, TABLET]], [\n /\\b(k88) b/i // ZTE K Series Tablet\n ], [MODEL, [VENDOR, 'ZTE'], [TYPE, TABLET]], [\n /\\b(nx\\d{3}j) b/i // ZTE Nubia\n ], [MODEL, [VENDOR, 'ZTE'], [TYPE, MOBILE]], [\n /\\b(gen\\d{3}) b.+49h/i // Swiss GEN Mobile\n ], [MODEL, [VENDOR, 'Swiss'], [TYPE, MOBILE]], [\n /\\b(zur\\d{3}) b/i // Swiss ZUR Tablet\n ], [MODEL, [VENDOR, 'Swiss'], [TYPE, TABLET]], [\n /\\b((zeki)?tb.*\\b) b/i // Zeki Tablets\n ], [MODEL, [VENDOR, 'Zeki'], [TYPE, TABLET]], [\n /\\b([yr]\\d{2}) b/i,\n /\\b(dragon[- ]+touch |dt)(\\w{5}) b/i // Dragon Touch Tablet\n ], [[VENDOR, 'Dragon Touch'], MODEL, [TYPE, TABLET]], [\n /\\b(ns-?\\w{0,9}) b/i // Insignia Tablets\n ], [MODEL, [VENDOR, 'Insignia'], [TYPE, TABLET]], [\n /\\b((nxa|next)-?\\w{0,9}) b/i // NextBook Tablets\n ], [MODEL, [VENDOR, 'NextBook'], [TYPE, TABLET]], [\n /\\b(xtreme\\_)?(v(1[045]|2[015]|[3469]0|7[05])) b/i // Voice Xtreme Phones\n ], [[VENDOR, 'Voice'], MODEL, [TYPE, MOBILE]], [\n /\\b(lvtel\\-)?(v1[12]) b/i // LvTel Phones\n ], [[VENDOR, 'LvTel'], MODEL, [TYPE, MOBILE]], [\n /\\b(ph-1) /i // Essential PH-1\n ], [MODEL, [VENDOR, 'Essential'], [TYPE, MOBILE]], [\n /\\b(v(100md|700na|7011|917g).*\\b) b/i // Envizen Tablets\n ], [MODEL, [VENDOR, 'Envizen'], [TYPE, TABLET]], [\n /\\b(trio[-\\w\\. ]+) b/i // MachSpeed Tablets\n ], [MODEL, [VENDOR, 'MachSpeed'], [TYPE, TABLET]], [\n /\\btu_(1491) b/i // Rotor Tablets\n ], [MODEL, [VENDOR, 'Rotor'], [TYPE, TABLET]], [\n /(shield[\\w ]+) b/i // Nvidia Shield Tablets\n ], [MODEL, [VENDOR, 'Nvidia'], [TYPE, TABLET]], [\n /(sprint) (\\w+)/i // Sprint Phones\n ], [VENDOR, MODEL, [TYPE, MOBILE]], [\n /(kin\\.[onetw]{3})/i // Microsoft Kin\n ], [[MODEL, /\\./g, ' '], [VENDOR, MICROSOFT], [TYPE, MOBILE]], [\n /droid.+; (cc6666?|et5[16]|mc[239][23]x?|vc8[03]x?)\\)/i // Zebra\n ], [MODEL, [VENDOR, ZEBRA], [TYPE, TABLET]], [\n /droid.+; (ec30|ps20|tc[2-8]\\d[kx])\\)/i\n ], [MODEL, [VENDOR, ZEBRA], [TYPE, MOBILE]], [\n\n ///////////////////\n // SMARTTVS\n ///////////////////\n\n /smart-tv.+(samsung)/i // Samsung\n ], [VENDOR, [TYPE, SMARTTV]], [\n /hbbtv.+maple;(\\d+)/i\n ], [[MODEL, /^/, 'SmartTV'], [VENDOR, SAMSUNG], [TYPE, SMARTTV]], [\n /(nux; netcast.+smarttv|lg (netcast\\.tv-201\\d|android tv))/i // LG SmartTV\n ], [[VENDOR, LG], [TYPE, SMARTTV]], [\n /(apple) ?tv/i // Apple TV\n ], [VENDOR, [MODEL, APPLE+' TV'], [TYPE, SMARTTV]], [\n /crkey/i // Google Chromecast\n ], [[MODEL, CHROME+'cast'], [VENDOR, GOOGLE], [TYPE, SMARTTV]], [\n /droid.+aft(\\w+)( bui|\\))/i // Fire TV\n ], [MODEL, [VENDOR, AMAZON], [TYPE, SMARTTV]], [\n /\\(dtv[\\);].+(aquos)/i,\n /(aquos-tv[\\w ]+)\\)/i // Sharp\n ], [MODEL, [VENDOR, SHARP], [TYPE, SMARTTV]],[\n /(bravia[\\w ]+)( bui|\\))/i // Sony\n ], [MODEL, [VENDOR, SONY], [TYPE, SMARTTV]], [\n /(mitv-\\w{5}) bui/i // Xiaomi\n ], [MODEL, [VENDOR, XIAOMI], [TYPE, SMARTTV]], [\n /Hbbtv.*(technisat) (.*);/i // TechniSAT\n ], [VENDOR, MODEL, [TYPE, SMARTTV]], [\n /\\b(roku)[\\dx]*[\\)\\/]((?:dvp-)?[\\d\\.]*)/i, // Roku\n /hbbtv\\/\\d+\\.\\d+\\.\\d+ +\\([\\w\\+ ]*; *([\\w\\d][^;]*);([^;]*)/i // HbbTV devices\n ], [[VENDOR, trim], [MODEL, trim], [TYPE, SMARTTV]], [\n /\\b(android tv|smart[- ]?tv|opera tv|tv; rv:)\\b/i // SmartTV from Unidentified Vendors\n ], [[TYPE, SMARTTV]], [\n\n ///////////////////\n // CONSOLES\n ///////////////////\n\n /(ouya)/i, // Ouya\n /(nintendo) ([wids3utch]+)/i // Nintendo\n ], [VENDOR, MODEL, [TYPE, CONSOLE]], [\n /droid.+; (shield) bui/i // Nvidia\n ], [MODEL, [VENDOR, 'Nvidia'], [TYPE, CONSOLE]], [\n /(playstation [345portablevi]+)/i // Playstation\n ], [MODEL, [VENDOR, SONY], [TYPE, CONSOLE]], [\n /\\b(xbox(?: one)?(?!; xbox))[\\); ]/i // Microsoft Xbox\n ], [MODEL, [VENDOR, MICROSOFT], [TYPE, CONSOLE]], [\n\n ///////////////////\n // WEARABLES\n ///////////////////\n\n /\\b(sm-[lr]\\d\\d[05][fnuw]?s?)\\b/i // Samsung Galaxy Watch\n ], [MODEL, [VENDOR, SAMSUNG], [TYPE, WEARABLE]], [\n /((pebble))app/i // Pebble\n ], [VENDOR, MODEL, [TYPE, WEARABLE]], [\n /(watch)(?: ?os[,\\/]|\\d,\\d\\/)[\\d\\.]+/i // Apple Watch\n ], [MODEL, [VENDOR, APPLE], [TYPE, WEARABLE]], [\n /droid.+; (glass) \\d/i // Google Glass\n ], [MODEL, [VENDOR, GOOGLE], [TYPE, WEARABLE]], [\n /droid.+; (wt63?0{2,3})\\)/i\n ], [MODEL, [VENDOR, ZEBRA], [TYPE, WEARABLE]], [\n\n ///////////////////\n // XR\n ///////////////////\n\n /droid.+; (glass) \\d/i // Google Glass\n ], [MODEL, [VENDOR, GOOGLE], [TYPE, WEARABLE]], [\n /(pico) (4|neo3(?: link|pro)?)/i // Pico\n ], [VENDOR, MODEL, [TYPE, WEARABLE]], [\n /; (quest( \\d| pro)?)/i // Oculus Quest\n ], [MODEL, [VENDOR, FACEBOOK], [TYPE, WEARABLE]], [\n\n ///////////////////\n // EMBEDDED\n ///////////////////\n\n /(tesla)(?: qtcarbrowser|\\/[-\\w\\.]+)/i // Tesla\n ], [VENDOR, [TYPE, EMBEDDED]], [\n /(aeobc)\\b/i // Echo Dot\n ], [MODEL, [VENDOR, AMAZON], [TYPE, EMBEDDED]], [\n\n ////////////////////\n // MIXED (GENERIC)\n ///////////////////\n\n /droid .+?; ([^;]+?)(?: bui|; wv\\)|\\) applew).+? mobile safari/i // Android Phones from Unidentified Vendors\n ], [MODEL, [TYPE, MOBILE]], [\n /droid .+?; ([^;]+?)(?: bui|\\) applew).+?(?! mobile) safari/i // Android Tablets from Unidentified Vendors\n ], [MODEL, [TYPE, TABLET]], [\n /\\b((tablet|tab)[;\\/]|focus\\/\\d(?!.+mobile))/i // Unidentifiable Tablet\n ], [[TYPE, TABLET]], [\n /(phone|mobile(?:[;\\/]| [ \\w\\/\\.]*safari)|pda(?=.+windows ce))/i // Unidentifiable Mobile\n ], [[TYPE, MOBILE]], [\n /(android[-\\w\\. ]{0,9});.+buil/i // Generic Android Device\n ], [MODEL, [VENDOR, 'Generic']]\n ],\n\n engine : [[\n\n /windows.+ edge\\/([\\w\\.]+)/i // EdgeHTML\n ], [VERSION, [NAME, EDGE+'HTML']], [\n\n /(arkweb)\\/([\\w\\.]+)/i // ArkWeb\n ], [NAME, VERSION], [\n\n /webkit\\/537\\.36.+chrome\\/(?!27)([\\w\\.]+)/i // Blink\n ], [VERSION, [NAME, 'Blink']], [\n\n /(presto)\\/([\\w\\.]+)/i, // Presto\n /(webkit|trident|netfront|netsurf|amaya|lynx|w3m|goanna|servo)\\/([\\w\\.]+)/i, // WebKit/Trident/NetFront/NetSurf/Amaya/Lynx/w3m/Goanna/Servo\n /ekioh(flow)\\/([\\w\\.]+)/i, // Flow\n /(khtml|tasman|links)[\\/ ]\\(?([\\w\\.]+)/i, // KHTML/Tasman/Links\n /(icab)[\\/ ]([23]\\.[\\d\\.]+)/i, // iCab\n /\\b(libweb)/i\n ], [NAME, VERSION], [\n\n /rv\\:([\\w\\.]{1,9})\\b.+(gecko)/i // Gecko\n ], [VERSION, NAME]\n ],\n\n os : [[\n\n