40 lines
1.3 KiB
TypeScript
40 lines
1.3 KiB
TypeScript
export type RenderingEngine = "webkit" | "other";
|
|
|
|
export type RenderingNavigator = {
|
|
userAgent?: string;
|
|
};
|
|
|
|
const BLINK_USER_AGENT_TOKENS = /(?:Chrome|Chromium|HeadlessChrome|Edg|OPR|SamsungBrowser)\//i;
|
|
|
|
function browserNavigator(): RenderingNavigator | undefined {
|
|
if (typeof navigator === "undefined") return undefined;
|
|
return navigator;
|
|
}
|
|
|
|
/**
|
|
* Identify WebKit without mistaking desktop Chromium's AppleWebKit token for
|
|
* the rendering engine. iOS browser brands remain WebKit because iOS routes
|
|
* all browser engines through the system WebKit runtime.
|
|
*/
|
|
export function detectRenderingEngine(
|
|
navigatorLike: RenderingNavigator | null | undefined = browserNavigator(),
|
|
): RenderingEngine {
|
|
if (!navigatorLike) return "other";
|
|
|
|
const userAgent = navigatorLike.userAgent ?? "";
|
|
if (!/AppleWebKit\//i.test(userAgent)) return "other";
|
|
if (BLINK_USER_AGENT_TOKENS.test(userAgent)) return "other";
|
|
|
|
return "webkit";
|
|
}
|
|
|
|
/** Apply the transient engine marker used by scoped rendering workarounds. */
|
|
export function markRenderingEngine(
|
|
root: HTMLElement,
|
|
navigatorLike: RenderingNavigator | null | undefined = browserNavigator(),
|
|
): RenderingEngine {
|
|
const engine = detectRenderingEngine(navigatorLike);
|
|
root.dataset.renderingEngine = engine;
|
|
return engine;
|
|
}
|