From f0097de6d5491e1028589ddf0cf558508a0074e1 Mon Sep 17 00:00:00 2001 From: "Thomas F. K. Jorna" Date: Sun, 9 Nov 2025 22:16:03 +0100 Subject: [PATCH 1/3] fix: improve unhighlightable contents check --- navigator/src/helpers/sML.ts | 293 ++++++++++++++++++++++------------- 1 file changed, 187 insertions(+), 106 deletions(-) diff --git a/navigator/src/helpers/sML.ts b/navigator/src/helpers/sML.ts index 8b672189..df6628cc 100644 --- a/navigator/src/helpers/sML.ts +++ b/navigator/src/helpers/sML.ts @@ -11,133 +11,214 @@ /// declare interface OSFlags { - iOS: number[]; - macOS: number[]; - iPadOS: number[]; - WindowsPhone: number[]; - ChromeOS: number[]; - Windows: number[]; - Android: number[]; - Linux: number[]; - Firefox: boolean; + 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[]; + 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); +const userAgent = () => + typeof navigator === "undefined" ? "" : navigator.userAgent || ""; +const userAgentData = () => + typeof navigator === "undefined" + ? undefined + : navigator.userAgentData || undefined; class sMLFactory { - OS: OSFlags; - UA: UAFlags; - Env!: string[]; + OS: OSFlags; + UA: UAFlags; + Env!: string[]; - constructor() { - const NUAD = userAgentData(), NUA = userAgent(); + 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")); - }; + 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.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, _: 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.UA = ((UA: UAFlags) => { + let _OK = false; + if (NUAD && Array.isArray(NUAD.brands)) { + const BnV = NUAD.brands.reduce( + (BnV: Record, _: 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; }, []) }; - } + (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(); + 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; + 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 }; \ No newline at end of file +export { sML, sMLWithRequest }; From 7b3c9a66123795232ce8203f2426d89768b08520 Mon Sep 17 00:00:00 2001 From: "Thomas F. K. Jorna" Date: Sun, 9 Nov 2025 22:43:34 +0100 Subject: [PATCH 2/3] fix: restore accidental edit --- navigator/src/helpers/sML.ts | 293 +++++++++++++---------------------- 1 file changed, 106 insertions(+), 187 deletions(-) diff --git a/navigator/src/helpers/sML.ts b/navigator/src/helpers/sML.ts index df6628cc..8b672189 100644 --- a/navigator/src/helpers/sML.ts +++ b/navigator/src/helpers/sML.ts @@ -11,214 +11,133 @@ /// declare interface OSFlags { - iOS: number[]; - macOS: number[]; - iPadOS: number[]; - WindowsPhone: number[]; - ChromeOS: number[]; - Windows: number[]; - Android: number[]; - Linux: number[]; - Firefox: boolean; + 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[]; + 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; +const userAgent = () => typeof navigator === "undefined" ? "" : (navigator.userAgent || ""); +const userAgentData = () => typeof navigator === "undefined" ? undefined : (navigator.userAgentData || undefined); class sMLFactory { - OS: OSFlags; - UA: UAFlags; - Env!: string[]; + OS: OSFlags; + UA: UAFlags; + Env!: string[]; - constructor() { - const NUAD = userAgentData(), - NUA = userAgent(); + 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")); - }; + 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.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, _: 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.UA = ((UA: UAFlags) => { let _OK = false; + if(NUAD && Array.isArray(NUAD.brands)) { const BnV = NUAD.brands.reduce((BnV: Record, _: 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; - }, []), - }; - } + (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(); + 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"; - } + 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; - } + return undefined; + } } const sML = new sMLFactory(); const sMLWithRequest = new sMLFactoryWithRequest(); -export { sML, sMLWithRequest }; +export { sML, sMLWithRequest }; \ No newline at end of file From e96d53f8671317c8c15d24340cfb3f5fec90ee85 Mon Sep 17 00:00:00 2001 From: "Thomas F. K. Jorna" Date: Sun, 9 Nov 2025 22:46:08 +0100 Subject: [PATCH 3/3] fix: actually include the fix --- navigator-html-injectables/src/modules/Decorator.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/navigator-html-injectables/src/modules/Decorator.ts b/navigator-html-injectables/src/modules/Decorator.ts index f804aef9..a528926f 100644 --- a/navigator-html-injectables/src/modules/Decorator.ts +++ b/navigator-html-injectables/src/modules/Decorator.ts @@ -103,8 +103,12 @@ class DecorationGroup { // The common ancestor is an element that definitely cannot be highlighted this.notTextFlag?.set(id, true); } - if(ancestor.querySelector(cannotNativeHighlight.join(", ").toLowerCase())) { - // Contains elements that definitely cannot be highlighted as children + // Check if the range itself contains elements that cannot be highlighted + const rangeFragment = range.cloneContents(); + const tempDiv = this.wnd.document.createElement('div'); + tempDiv.appendChild(rangeFragment); + if(tempDiv.querySelector(cannotNativeHighlight.join(", ").toLowerCase())) { + // Range contains elements that definitely cannot be highlighted this.notTextFlag?.set(id, true); } if((ancestor.textContent?.trim() || "").length === 0) {