diff --git a/scripts/stats.ts b/scripts/stats.ts index 4367758d17b..e570075e312 100644 --- a/scripts/stats.ts +++ b/scripts/stats.ts @@ -1,56 +1,83 @@ import { Compat } from "compute-baseline/browser-compat-data"; +import { fileURLToPath } from "node:url"; +import yargs from "yargs"; import { features } from "../index.js"; -const featureCount = Object.keys(features).length; - -const keys = [...new Compat().walk()] - .filter((f) => !f.id.startsWith("webextensions")) - .map((f) => f.id).length; - -const compatKeys = Object.values(features).flatMap( - (f) => f.compat_features ?? [], -).length; - -const featureSizes = Object.values(features) - .map((feature) => (feature.compat_features ?? []).length) - .sort((a, b) => a - b); - -const stats = { - features: featureCount, - compatKeys, - compatCoverage: compatKeys / keys, - compatKeysPerFeatureMean: compatKeys / featureCount, - compatKeysPerFeatureMedian: (() => { - const sizes = featureSizes; - const middle = Math.floor(sizes.length / 2); - return sizes.length % 2 - ? sizes[middle] - : (sizes[middle - 1] + sizes[middle]) / 2; - })(), - compatKeysPerFeatureMode: (() => { - const frequencyMap = new Map(); - for (const size of featureSizes) { - frequencyMap.set(size, (frequencyMap.get(size) ?? 0) + 1); +const argv = yargs(process.argv.slice(2)) + .scriptName("stats") + .usage("$0", "Generate statistics") + .option("verbose", { + alias: "v", + describe: "Show more detailed stats", + type: "count", + default: 0, + defaultDescription: "warn", + }).argv; + +export function stats(detailed: boolean = false) { + const featureCount = Object.keys(features).length; + + const keys = []; + const doneKeys = Object.values(features).flatMap( + (f) => f.compat_features ?? [], + ); + const toDoKeys = []; + const deprecatedNonStandardKeys = []; + + for (const f of new Compat().walk()) { + if (!f.id.startsWith("webextensions")) { + keys.push(f.id); + + if (!f.deprecated && f.standard_track) { + if (!doneKeys.includes(f.id)) { + toDoKeys.push(f.id); + } + } else { + deprecatedNonStandardKeys.push(f.id); + } } - return [...frequencyMap.entries()] - .sort( - ([sizeA, frequencyA], [sizeB, frequencyB]) => frequencyA - frequencyB, - ) - .pop()[0]; - })(), -}; - -console.log(JSON.stringify(stats, undefined, 2)); - -const todoKeys = [...new Compat().walk()] - .filter((f) => !f.id.startsWith("webextensions") && !f.deprecated) - .map((f) => f.id); - -const doneKeys = Object.values(features).flatMap( - (f) => f.compat_features ?? [], -); - -let symDifference = todoKeys - .filter((x) => !doneKeys.includes(x)) - .concat(doneKeys.filter((x) => !todoKeys.includes(x))); -console.dir(symDifference, { maxArrayLength: null }); + } + + const featureSizes = Object.values(features) + .map((feature) => (feature.compat_features ?? []).length) + .sort((a, b) => a - b); + + const result = { + features: featureCount, + compatKeys: doneKeys.length, + compatKeysUnmapped: toDoKeys.length, + compatCoverage: doneKeys.length / keys.length, + compatKeysPerFeatureMean: doneKeys.length / featureCount, + compatKeysPerFeatureMedian: (() => { + const sizes = featureSizes; + const middle = Math.floor(sizes.length / 2); + return sizes.length % 2 + ? sizes[middle] + : (sizes[middle - 1] + sizes[middle]) / 2; + })(), + compatKeysPerFeatureMode: (() => { + const frequencyMap = new Map(); + for (const size of featureSizes) { + frequencyMap.set(size, (frequencyMap.get(size) ?? 0) + 1); + } + return [...frequencyMap.entries()] + .sort( + ([sizeA, frequencyA], [sizeB, frequencyB]) => frequencyA - frequencyB, + ) + .pop()[0]; + })(), + toBeMapped: undefined, + }; + + if (detailed) { + result.toBeMapped = toDoKeys; + } + + return result; +} + +if (import.meta.url.startsWith("file:")) { + if (process.argv[1] === fileURLToPath(import.meta.url)) { + console.log(JSON.stringify(stats(argv.verbose), undefined, 2)); + } +}