web_lib

Common web application libraries
git clone https://radroots.dev/git/web_lib.git
Log | Files | Refs | LICENSE

browser.ts (3153B)


      1 export type BrowserPlatformInfo = {
      2     os: string;
      3     browser: string;
      4     version: string;
      5 };
      6 
      7 const REMOVE_EXCESS_MOZILLA_AND_VERSION = /^mozilla\/\d\.\d\W/;
      8 const BROWSER_PATTERN = /(\w+)\/(\d+\.\d+(?:\.\d+)?(?:\.\d+)?)/g;
      9 const ENGINE_AND_VERSION_PATTERN = /^(ver|cri|gec)/;
     10 const BRAND_LIST = ['chrome', 'opera', 'safari', 'edge', 'firefox'];
     11 
     12 const MOBILE_OS_PATTERNS: Record<string, RegExp> = {
     13     iphone: /iphone/,
     14     ipad: /ipad|macintosh/,
     15     android: /android/
     16 };
     17 
     18 const DESKTOP_OS_PATTERNS: Record<string, RegExp> = {
     19     windows: /win/,
     20     mac: /macintosh/,
     21     linux: /linux/
     22 };
     23 
     24 const parse_user_agent_string = (ua_string: string): BrowserPlatformInfo => {
     25     const ua = ua_string.toLowerCase().replace(REMOVE_EXCESS_MOZILLA_AND_VERSION, '');
     26 
     27     const mobile_os = Object.keys(MOBILE_OS_PATTERNS).find(
     28         (key) => MOBILE_OS_PATTERNS[key].test(ua) && navigator.maxTouchPoints >= 1
     29     );
     30     const desktop_os = Object.keys(DESKTOP_OS_PATTERNS).find((key) => DESKTOP_OS_PATTERNS[key].test(ua));
     31     const os = mobile_os || desktop_os || '';
     32 
     33     const browser_matches = ua.match(BROWSER_PATTERN);
     34     const version_regex = /version\/(\d+(\.\d+)*)/;
     35     const safari_version_match = ua.match(version_regex);
     36     const safari_version = Array.isArray(safari_version_match) ? safari_version_match[1] : null;
     37 
     38     const browser_offset =
     39         browser_matches && browser_matches.length > 2 && !ENGINE_AND_VERSION_PATTERN.test(browser_matches[1])
     40             ? 1
     41             : 0;
     42     const browser_result =
     43         browser_matches && browser_matches[browser_matches.length - 1 - browser_offset].split('/');
     44     const browser = browser_result ? browser_result[0] : '';
     45     const version = safari_version || (browser_result ? browser_result[1] : '');
     46 
     47     return { os, browser, version };
     48 };
     49 
     50 export const browser_platform = (): BrowserPlatformInfo | undefined => {
     51     if (typeof navigator !== 'undefined') {
     52         if ('userAgentData' in navigator && navigator.userAgentData) {
     53             const ua_data = navigator.userAgentData;
     54             const os = ua_data.platform.toLowerCase();
     55             let browser = '';
     56             let version = '';
     57 
     58             if (Array.isArray(ua_data.brands)) {
     59                 for (const { brand, version: brand_version } of ua_data.brands) {
     60                     const lower_brand = brand.toLowerCase();
     61                     if (BRAND_LIST.some((b) => lower_brand.includes(b))) {
     62                         browser = lower_brand;
     63                         version = brand_version;
     64                         break;
     65                     }
     66                 }
     67             }
     68 
     69             if (!browser && navigator.userAgent) {
     70                 return parse_user_agent_string(navigator.userAgent);
     71             }
     72             return { os, browser, version };
     73         }
     74 
     75         if (navigator.userAgent) {
     76             return parse_user_agent_string(navigator.userAgent);
     77         }
     78 
     79         const nav_platform = navigator.platform;
     80         if (!nav_platform) return undefined;
     81         return {
     82             os: nav_platform,
     83             browser: '',
     84             version: ''
     85         };
     86     }
     87 
     88     return undefined;
     89 };