@kcjpop/x-browser-compat
Version:
A Web Component to display browser compatibility data
121 lines (101 loc) • 3.32 kB
JavaScript
const VERSION = "0.0.6";
const URL = `https://unpkg.com/@kcjpop/x-browser-compat@${VERSION}/bcd/`;
const BrowserNameMap = new Map([
["chrome", "Google Chrome"],
["chrome_android", "Google Chrome (Android)"],
["deno", "Deno"],
["edge", "Microsoft Edge"],
["firefox", "Mozilla Firefox"],
["firefox_android", "Firefox (Android)"],
["ie", "Internet Explorer"],
["nodejs", "Node.js"],
["oculus", "Meta Quest Browser"],
["opera", "Opera"],
["opera_android", "Opera (Android)"],
["safari", "Safari"],
["safari_ios", "Safari (iOS)"],
["samsunginternet_android", "Samsung Internet"],
["webview_android", "WebView (Android)"],
]);
const SupportStatus = {
support: "support",
support_unknown_version: "support_unknown_version",
no_support: "no_support",
unknown: "unknown",
};
/**
*
* @see https://github.com/mdn/browser-compat-data/blob/main/schemas/compat-data-schema.md#the-support_statement-object
*/
function getSupportStatus(entry) {
if (entry.version_added === true)
return { status: SupportStatus.support_unknown_version };
if (entry.version_added === false)
return { status: SupportStatus.no_support };
if (entry.version_added === null) return { status: SupportStatus.unknown };
if (typeof entry.version_added === "string")
return { status: SupportStatus.support, version: entry.version_added };
if (Array.isArray(entry)) {
const needle = entry.find((item) => item.version_added != null);
if (needle !== undefined)
return { status: SupportStatus.support, version: needle.version_added };
}
}
function translateBrowserName(name) {
return BrowserNameMap.get(name);
}
export class XBrowserCompat extends HTMLElement {
constructor() {
super();
this.shadow = this.attachShadow({ mode: "open" });
this.path = this.getAttribute("path");
const browsers = this.getAttribute("browsers");
this.browsers =
browsers != null && browsers !== ""
? browsers.split(",").map((s) => s.trim())
: null;
this.render();
}
async render() {
if (this.path == null || this.path?.length === 0) {
this.shadow.innerHTML = 'Missing "path" attribute.';
return;
}
let data = null;
try {
data = await fetch(
URL + this.path.replaceAll(".", "/") + "/index.json"
).then((res) => res.json());
} catch (e) {
console.error(e);
}
if (data == null) {
this.shadow.innerHTML = `No browser compat data found for "path": ${this.path}`;
return;
}
const entries = Array.isArray(this.browsers)
? this.browsers
.map((browserName) =>
data.support[browserName] != null
? [browserName, data.support[browserName]]
: false
)
.filter(Boolean)
: Object.entries(data.support);
this.shadow.innerHTML = entries
.map(([browserName, browser]) => {
const { status, version } = getSupportStatus(browser);
return `<div part="browser ${status}">
<span part="name ${browserName}">${translateBrowserName(
browserName
)}</span>
${
version !== undefined
? `<span part="version">${version}</span>`
: ""
}
</div>`;
})
.join("\n");
}
}