@readium/navigator
Version:
Next generation SDK for publications in Web Apps
143 lines (129 loc) • 7.62 kB
text/typescript
/*!
* (℠)
* # sML.js | I'm a Simple and Middling Library.
*
* * Copyright (c) Satoru MATSUSHIMA - https://github.com/satorumurmur/sML
* * Licensed under the MIT license. - http://www.opensource.org/licenses/mit-license.php
*
* Portions of this code come from the sML library
* Current version: 1.0.36
*/
/// <reference types="user-agent-data-types" />
declare interface OSFlags {
iOS: number[];
macOS: number[];
iPadOS: number[];
WindowsPhone: number[];
ChromeOS: number[];
Windows: number[];
Android: number[];
Linux: number[];
Firefox: boolean;
}
declare interface UAFlags {
Gecko: number[];
Firefox: number[];
Waterfox: number[];
Opera: number[];
Silk: number[];
Blink: number[];
EdgeHTML: number[];
Chrome: number[];
Chromium: number[];
Phoebe: number[];
UCBrowser: number[];
Vivaldi: number[];
Safari: number[];
Edge: number[];
WebKit: number[];
Trident: number[];
InternetExplorer: number[];
Flash: number[];
Facebook: number[];
LINE: number[];
}
declare type iOSRequest = "mobile" | "desktop" | undefined;
// Fallback when global 'navigator' is not available, such as in SSR environments.
const userAgent = () => typeof navigator === "undefined" ? "" : (navigator.userAgent || "");
const userAgentData = () => typeof navigator === "undefined" ? undefined : (navigator.userAgentData || undefined);
class sMLFactory {
OS: OSFlags;
UA: UAFlags;
Env!: string[];
constructor() {
const NUAD = userAgentData(), NUA = userAgent();
const _sV = (V?: string | number) => (typeof V === "string" || typeof V === "number") && V ? String(V).replace(/_/g, ".").split(".").map(I => parseInt(I) || 0) : [];
const _dV = (Pre="") => {
if(!Pre) return [];
const RE = new RegExp("^.*" + Pre + "[ :\\/]?(\\d+([\\._]\\d+)*).*$");
if(!RE.test(NUA)) return [];
return _sV(NUA.replace(RE, "$1"));
};
this.OS = ((OS: OSFlags) => {
if( /(macOS|Mac OS X)/.test(NUA)) {
if(/\(iP(hone|od touch);/.test(NUA)) OS.iOS = _dV("CPU (?:iPhone )?OS ");
if( /\(iPad;/.test(NUA)) OS.iOS = OS.iPadOS = _dV("CPU (?:iPhone )?OS ");
else if( /(macOS|Mac OS X) \d/.test(NUA)) document.ontouchend !== undefined ? OS.iOS = OS.iPadOS = _dV() : OS.macOS = _dV("(?:macOS|Mac OS X) ");
} else if( /Windows( NT)? \d/.test(NUA)) OS.Windows = (V => V[0] !== 6 || !V[1] ? V : V[1] === 1 ? [7] : V[1] === 2 ? [8] : [8, 1])(_dV("Windows(?: NT)?"));
else if( /Android \d/.test(NUA)) OS.Android = _dV("Android");
else if( /CrOS/.test(NUA)) OS.ChromeOS = _dV();
else if( /X11;/.test(NUA)) OS.Linux = _dV();
return OS;
})({} as OSFlags); if(NUAD) NUAD.getHighEntropyValues(["architecture", "model", "platform", "platformVersion", "uaFullVersion"]).then((HEUAD: any) => (OS => { const Pf = HEUAD.platform, PfV = HEUAD.platformVersion; if(!Pf || !PfV) return;
if( /^i(OS|P(hone|od touch))$/.test(Pf)) OS.iOS = _sV(PfV);
else if( /^iPad(OS)?$/.test(Pf)) OS.iOS = OS.iPadOS = _sV(PfV);
else if(/^(macOS|(Mac )?OS X|Mac(Intel)?)$/.test(Pf)) document.ontouchend !== undefined ? OS.iOS = OS.iPadOS = _sV() : OS.macOS = _sV(PfV);
else if( /^(Microsoft )?Windows$/.test(Pf)) OS.Windows = _sV(PfV);
else if( /^(Google )?Android$/.test(Pf)) OS.Android = _sV(PfV);
else if( /^((Google )?Chrome OS|CrOS)$/.test(Pf)) OS.ChromeOS = _sV(PfV);
else if( /^(Linux|Ubuntu|X11)$/.test(Pf)) OS.Linux = _sV(PfV);
else return; /**/ Object.keys(this.OS).forEach(Key => delete (this.OS as any)[Key]), Object.assign(this.OS, OS);
})({} as OSFlags));
this.UA = ((UA: UAFlags) => { let _OK = false;
if(NUAD && Array.isArray(NUAD.brands)) { const BnV = NUAD.brands.reduce((BnV: Record<string, number[]>, _: NavigatorUABrandVersion) => { BnV[_.brand] = [(_.version as any) * 1]; return BnV; }, {});
if(BnV["Google Chrome"]) _OK = true, UA.Blink = UA.Chromium = BnV["Chromium"] || [], UA.Chrome = BnV["Google Chrome"];
else if(BnV["Microsoft Edge"]) _OK = true, UA.Blink = UA.Chromium = BnV["Chromium"] || [], UA.Edge = BnV["Microsoft Edge"];
else if(BnV["Opera"]) _OK = true, UA.Blink = UA.Chromium = BnV["Chromium"] || [], UA.Opera = BnV["Opera"];
} if(!_OK) {
if( / Gecko\/\d/.test(NUA)) { UA.Gecko = _dV("rv");
if( / Waterfox\/\d/.test(NUA)) UA.Waterfox = _dV("Waterfox");
else if( / Firefox\/\d/.test(NUA)) UA.Firefox = _dV("Firefox");
} else if( / Edge\/\d/.test(NUA)) { UA.EdgeHTML = _dV("Edge");
UA.Edge = UA.EdgeHTML;
} else if(/ Chrom(ium|e)\/\d/.test(NUA)) { UA.Blink = UA.Chromium = (V => V[0] ? V : _dV("Chrome"))(_dV("Chromium"));
if( / EdgA?\/\d/.test(NUA)) UA.Edge = (V => V[0] ? V : _dV("Edg"))(_dV("EdgA"));
else if( / OPR\/\d/.test(NUA)) UA.Opera = _dV("OPR");
else if( / Vivaldi\/\d/.test(NUA)) UA.Vivaldi = _dV("Vivaldi");
else if( / Silk\/\d/.test(NUA)) UA.Silk = _dV("Silk");
else if( / UCBrowser\/\d/.test(NUA)) UA.UCBrowser = _dV("UCBrowser");
else if( / Phoebe\/\d/.test(NUA)) UA.Phoebe = _dV("Phoebe");
else UA.Chrome = (V => V[0] ? V : UA.Chromium)(_dV("Chrome"));
} else if( / AppleWebKit\/\d/.test(NUA)) { UA.WebKit = _dV("AppleWebKit");
if( / CriOS \d/.test(NUA)) UA.Chrome = _dV("CriOS");
else if( / FxiOS \d/.test(NUA)) UA.Firefox = _dV("FxiOS");
else if( / EdgiOS\/\d/.test(NUA)) UA.Edge = _dV("EdgiOS");
else if( / Version\/\d/.test(NUA)) UA.Safari = _dV("Version");
} else if( / Trident\/\d/.test(NUA)) { UA.Trident = _dV("Trident");
UA.InternetExplorer = (V => V[0] ? V : _dV("MSIE"))(_dV("rv"));
}
} /*+*/ if( /[\[; ]FB(AN|_IAB)\//.test(NUA)) UA.Facebook = _dV("FBAV");
/*+*/ if( / Line\/\d/.test(NUA)) UA.LINE = _dV("Line");
return UA;
})({} as UAFlags);
(this.Env as any) = { get: () => [this.OS, this.UA].reduce((Env: string[], OS_UA) => { for(const Par in OS_UA) if((OS_UA as any)[Par]) Env.push(Par); return Env; }, []) };
}
}
class sMLFactoryWithRequest extends sMLFactory {
get iOSRequest(): iOSRequest {
const NUAD = userAgentData(), NUA = userAgent();
if (this.OS.iOS && !this.OS.iPadOS) {
return "mobile";
} else if (this.OS.iPadOS) {
return (/\(iPad;/.test(NUA) || (NUAD && /^iPad(OS)?$/.test(NUAD.platform))) ? "mobile" : "desktop"
}
return undefined;
}
}
const sML = new sMLFactory();
const sMLWithRequest = new sMLFactoryWithRequest();
export { sML, sMLWithRequest };