Skip to content

Instantly share code, notes, and snippets.

@kripod
Last active September 1, 2020 22:02
Show Gist options
  • Save kripod/06e9a5713c6540289a88289254ebd4f0 to your computer and use it in GitHub Desktop.
Save kripod/06e9a5713c6540289a88289254ebd4f0 to your computer and use it in GitHub Desktop.
Retrieve vendor prefixes and alternative names for every CSS property with Browserslist and mdn-browser-compat-data
import browserslist from "browserslist";
import compareVersions from "compare-versions";
import bcd from "mdn-browser-compat-data";
function normalizeVersion(version) {
return version.replace("≤", "");
}
const browsersByBrowserslistId = new Map([
/* Keys: https://github.com/browserslist/browserslist#browsers */
/* Values: https://github.com/mdn/browser-compat-data/blob/master/schemas/compat-data-schema.md#browser-identifiers */
["chrome", "chrome"],
["and_chr", "chrome_android"],
["edge", "edge"],
["firefox", "firefox"],
["and_ff", "firefox_android"],
["ie", "ie"],
["node", "nodejs"],
["opera", "opera"],
["op_mob", "opera_android"],
["and_qq", "qq_android"],
["safari", "safari"],
["ios_saf", "safari_ios"],
["samsung", "samsunginternet_android"],
["and_uc", "uc_android"],
["android", "webview_android"],
]);
const minSupportedVersionsByBrowser = new Map();
browserslist("defaults")
.map((stat) => {
const [browserslistId, versionRange] = stat.split(" ");
return [
browsersByBrowserslistId.get(browserslistId),
versionRange.split("-")[0], // Uses lower version if a range is given
];
})
.filter(([browser]) => browser) // Filter out unknown browsers
.forEach(([browser, version]) => {
// Find minimum version of each browser
if (
!minSupportedVersionsByBrowser.has(browser) ||
compareVersions(version, minSupportedVersionsByBrowser.get(browser)) < 0
) {
minSupportedVersionsByBrowser.set(browser, version);
}
});
const prefixesByStandardProperty = new Map();
const alternativePropertiesByStandardProperty = new Map();
function traverse(property, { __compat, ...subfeatures }) {
if (!__compat) {
for (const subfeatureIdentifier of Object.values(subfeatures)) {
traverse(property, subfeatureIdentifier);
}
return;
}
if (__compat.status && !__compat.status.standard_track) return;
for (const [browser, supportStatement] of Object.entries(__compat.support)) {
const minSupportedVersion = minSupportedVersionsByBrowser.get(browser);
if (!minSupportedVersion) continue;
const supportStatements = Array.isArray(supportStatement)
? supportStatement
: [supportStatement];
const hasNativeSupport =
!supportStatements[0].prefix &&
!supportStatements[0].alternative_name &&
(typeof supportStatements[0].version_added === "string"
? compareVersions(
normalizeVersion(supportStatements[0].version_added),
minSupportedVersion
) <= 0
: supportStatements[0].version_added);
if (!hasNativeSupport) {
supportStatements.forEach(
(
{ prefix, version_added, version_removed, alternative_name, notes },
i
) => {
if (
(typeof version_removed === "string"
? compareVersions(
normalizeVersion(version_removed),
minSupportedVersion
) > 0
: !version_removed) &&
(i === 0 ||
(typeof version_added === "string" &&
typeof supportStatements[0].version_added === "string"
? compareVersions(
normalizeVersion(version_added),
normalizeVersion(supportStatements[0].version_added)
) < 0
: version_added))
) {
if (prefix) {
const prefixes =
prefixesByStandardProperty.get(property) || new Set();
if (prefixes.size === 0) {
prefixesByStandardProperty.set(property, prefixes);
}
prefixes.add(prefix);
}
if (alternative_name) {
const alternativeProperties =
alternativePropertiesByStandardProperty.get(property) ||
new Set();
if (alternativeProperties.size === 0) {
alternativePropertiesByStandardProperty.set(
property,
alternativeProperties
);
}
alternativeProperties.add(alternative_name);
}
/*
if (notes) {
console.log({
browser,
property,
prefix,
alternative_name,
notes,
});
}
*/
}
}
);
}
}
}
Object.entries(bcd.css.properties).forEach(([property, featureIdentifier]) =>
traverse(property, featureIdentifier)
);
console.log(minSupportedVersionsByBrowser);
console.log(prefixesByStandardProperty);
console.log(alternativePropertiesByStandardProperty);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment