Last active
September 1, 2020 22:02
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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