Skip to content

Commit cefb713

Browse files
committed
Add a script to list unmapped compat keys
1 parent 141d128 commit cefb713

File tree

1 file changed

+116
-0
lines changed

1 file changed

+116
-0
lines changed

scripts/unmapped-compat-keys.ts

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
import { Temporal } from "@js-temporal/polyfill";
2+
import { coreBrowserSet } from "compute-baseline";
3+
import { Compat, Feature } from "compute-baseline/browser-compat-data";
4+
import winston from "winston";
5+
import yargs from "yargs";
6+
import { features } from "../index.js";
7+
import { support } from "../packages/compute-baseline/dist/baseline/support.js";
8+
import { isOrdinaryFeatureData } from "../type-guards.js";
9+
10+
const compat = new Compat();
11+
const browsers = coreBrowserSet.map((b) => compat.browser(b));
12+
const today = Temporal.Now.plainDateISO();
13+
14+
const argv = yargs(process.argv.slice(2))
15+
.scriptName("unmapped-compat-keys")
16+
.usage(
17+
"$0",
18+
"Print keys from mdn/browser-compat-data not assigned to a feature",
19+
)
20+
.option("format", {
21+
choices: ["json", "yaml"],
22+
default: "yaml",
23+
describe:
24+
"Choose the output format. JSON has more detail, while YAML is suited to pasting into feature files.",
25+
})
26+
.option("verbose", {
27+
alias: "v",
28+
describe: "Show more information",
29+
type: "count",
30+
default: 0,
31+
defaultDescription: "warn",
32+
}).argv;
33+
34+
const logger = winston.createLogger({
35+
level: argv.verbose > 0 ? "debug" : "warn",
36+
format: winston.format.combine(
37+
winston.format.colorize(),
38+
winston.format.simple(),
39+
),
40+
transports: new winston.transports.Console(),
41+
});
42+
43+
const mappedCompatKeys = (() => {
44+
return new Set(
45+
Object.values(features).flatMap((f) => {
46+
if (isOrdinaryFeatureData(f)) {
47+
return f.compat_features ?? [];
48+
}
49+
return [];
50+
}),
51+
);
52+
})();
53+
54+
const compatFeatures: Map<Feature, number> = (() => {
55+
const map = new Map();
56+
for (const f of compat.walk()) {
57+
if (f.id.startsWith("webextensions")) {
58+
continue;
59+
}
60+
if (mappedCompatKeys.has(f.id)) {
61+
logger.debug(`${f.id} skipped, already mapped to a feature`);
62+
continue;
63+
}
64+
65+
map.set(f, cumulativeDaysShipped(f));
66+
}
67+
return map;
68+
})();
69+
70+
const byAge = [...compatFeatures.entries()].sort(
71+
([aFeature, aDays], [bFeature, bDays]) => aDays - bDays,
72+
);
73+
74+
if (argv.format === "yaml") {
75+
for (const [f, days] of byAge) {
76+
console.log(` - ${f.id}`);
77+
}
78+
}
79+
80+
if (argv.format === "json") {
81+
console.log(
82+
JSON.stringify(
83+
byAge.map(([f, days]) => ({
84+
key: f.id,
85+
cumulativeDaysShipped: days,
86+
deprecated: f.deprecated,
87+
})),
88+
undefined,
89+
2,
90+
),
91+
);
92+
}
93+
94+
/**
95+
* Returns the sum of days that this compat key has been shipping in each
96+
* browser in the Baseline core browser set.
97+
*
98+
* Like the Baseline calculation, this excludes features that are partially
99+
* implemented, prefixed, behind flags, or in not-yet-stable releases.
100+
*
101+
* @param {Feature} feature a compat feature object
102+
* @return {number} an integer
103+
*/
104+
function cumulativeDaysShipped(feature: Feature) {
105+
const results = support(feature, browsers);
106+
return [...results.values()]
107+
.filter((r) => r !== undefined)
108+
.map(
109+
(r) =>
110+
r.release.date.until(today, {
111+
largestUnit: "days",
112+
smallestUnit: "days",
113+
}).days,
114+
)
115+
.reduce((prev, curr) => prev + curr, 0);
116+
}

0 commit comments

Comments
 (0)