Skip to content

Commit

Permalink
fix(ua): add handling for WebKit-based browsers that do not support a…
Browse files Browse the repository at this point in the history
… Safari version and attempt to map back into an equivalent Safari version
  • Loading branch information
wessberg committed May 20, 2021
1 parent 75e891a commit 1700ca4
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 1 deletion.
119 changes: 119 additions & 0 deletions src/browserslist-generator/browserslist-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1003,6 +1003,17 @@ function getCaniuseBrowserForUseragentBrowser(parser: UaParserWrapper): Partial<
};
}

// For platforms where the HeyTapBrowser doesn't report which Chrome version
// it is based on, we'll have to rely on knowledge from similar user agent strings.
// as far as we know, HeyTapBrowser on non-iOS is always based on Chrome 70 or 77,
// seemingly at random. So we'll have to assume Chrome 70 here.
if (browser.name === "HeyTapBrowser" && engine.name === "WebKit") {
return {
browser: "chrome",
version: "70"
}
}

// Unfortunately, since Caniuse doesn't support PaleMoon,
// we will have to remap it to its closest equivalent Firefox
// version (which it is similar to and a fork of).
Expand Down Expand Up @@ -1212,6 +1223,112 @@ function getCaniuseBrowserForUseragentBrowser(parser: UaParserWrapper): Partial<
};

case "Safari":
// If no browser version is reported, and it is based on WebKit,
// we will have to attempt to "guess" the Safari version with mapping the
// WebKit version to an equivalent Safari version based on the data
// here: https://en.wikipedia.org/wiki/Safari_version_history, even
// though this doesn't seem to map correctly to real-world data
if (browser.version == null && engine.name === "WebKit" && engine.version != null) {
const semver = ensureSemver(undefined, engine.version);

if (lt(semver, "412.0.0")) {
return {
browser: "safari",
version: "1.0"
}
}

if (lt(semver, "522.0.0")) {
return {
browser: "safari",
version: "2.0"
}
}

if (lt(semver, "526.0.0")) {
return {
browser: "safari",
version: "3.0"
}
}

if (lt(semver, "533.0.0")) {
return {
browser: "safari",
version: "4.0"
}
}

if (lt(semver, "536.0.0")) {
return {
browser: "safari",
version: "5.0"
}
}

if (lt(semver, "537.71.0")) {
return {
browser: "safari",
version: "6.0"
}
}

if (lt(semver, "600.0.0")) {
return {
browser: "safari",
version: "7.0"
}
}

if (lt(semver, "601.0.0")) {
return {
browser: "safari",
version: "8.0"
}
}

if (lt(semver, "602.0.0")) {
return {
browser: "safari",
version: "9.0"
}
}

if (lt(semver, "604.0.0")) {
return {
browser: "safari",
version: "10.0"
}
}

if (lt(semver, "606.0.0")) {
return {
browser: "safari",
version: "11.0"
}
}

if (lt(semver, "608.0.0")) {
return {
browser: "safari",
version: "12.0"
}
}

if (lt(semver, "610.0.0")) {
return {
browser: "safari",
version: "13.0"
}
}

// Else it is the current Safari version.
// Keep this updated regularly
return {
browser: "safari",
version: "14.0"
};
}
return {
browser: "safari",
version: browser.version
Expand Down Expand Up @@ -1423,6 +1540,8 @@ export function generateBrowserslistFromUseragent(useragent: string): string[] {
// Prepare a CaniuseBrowser name from the useragent string
let {browser: caniuseBrowserName, version: caniuseBrowserVersion} = getCaniuseBrowserForUseragentBrowser(parser);

// console.log({browser, os, engine, caniuseBrowserName, caniuseBrowserVersion});

// If the browser name or version couldn't be determined, return false immediately
if (caniuseBrowserName == null || caniuseBrowserVersion == null) {
throw new TypeError(`No caniuse browser and/or version could be determined for User Agent: ${useragent}`);
Expand Down
12 changes: 12 additions & 0 deletions src/browserslist-generator/ua-parser-wrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ const PARSER_EXTENSIONS = {
[
"Sogou Explorer",
"version"
],
[
/(HeyTapBrowser)\/([\d.]+)/i
],
[
"HeyTapBrowser",
"version"
]
]
};
Expand Down Expand Up @@ -117,6 +124,11 @@ export class UaParserWrapper {
delete result["Sogou Explorer"];
}

else if (result.HeyTapBrowser != null) {
result.name = "HeyTapBrowser";
delete result.HeyTapBrowser;
}

return result;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export type UseragentBrowserKind =
| "PaleMoon"
| "Arora"
| "Sogou Explorer"
| "HeyTapBrowser"
| "Avant"
| "Baidu"
| "Blazer"
Expand Down
5 changes: 4 additions & 1 deletion src/browserslist-generator/useragent/useragent-typed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import {UseragentEngineKind} from "./useragent-engine-kind";
import {UseragentOsKind} from "./useragent-os-kind";
import {UseragentVendorKind} from "./useragent-vendor-kind";

/* eslint-disable @typescript-eslint/naming-convention */

export interface UseragentBrowser {
name: UseragentBrowserKind | undefined;

Expand All @@ -17,8 +19,9 @@ export interface UseragentBrowser {
*/
major: string | undefined;

// Workaround that allows for extending ua-parser-js
// Workarounds that allows for extending ua-parser-js with custom browser names
"Sogou Explorer"?: string;
"HeyTapBrowser"?: string;
}

export interface UseragentDevice {
Expand Down
16 changes: 16 additions & 0 deletions test/browserslist-generator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,22 @@ test("matchBrowserslistOnUserAgent() => Will match Sogou Explorer, but treat it
);
});

test("matchBrowserslistOnUserAgent() => Will match HeyTapBrowser, but treat it as Chrome (unless on iOS, where it will match as ios_saf). #1", t => {
t.true(
matchBrowserslistOnUserAgent(`Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Safari/537.36 HeyTapBrowser/45.7.7.1`, [
"chrome >= 70"
])
);
});

test("matchBrowserslistOnUserAgent() => Will match wkhtmltoimage. #1", t => {
t.true(
matchBrowserslistOnUserAgent(`Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.34 (KHTML, like Gecko) wkhtmltoimage Safari/534.34`, [
"safari >= 5"
])
);
});

test("matchBrowserslistOnUserAgent() => Will match Dalvik, but treat it as a bot. #1", t => {
t.true(matchBrowserslistOnUserAgent(`Dalvik/2.1.0 (Linux; U; Android 11; SM-N986B Build/RP1A.200720.012)`, ["ie >= 11"]));
});
Expand Down

0 comments on commit 1700ca4

Please sign in to comment.