Skip to content

Commit 55f2870

Browse files
authored
Add a script to list unmapped compat keys (#3525)
1 parent e4de450 commit 55f2870

File tree

2 files changed

+120
-23
lines changed

2 files changed

+120
-23
lines changed

scripts/stats.ts

Lines changed: 4 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,11 @@ import yargs from "yargs";
44
import { features } from "../index.js";
55
import { isOrdinaryFeatureData } from "../type-guards.js";
66

7-
const argv = yargs(process.argv.slice(2))
7+
yargs(process.argv.slice(2))
88
.scriptName("stats")
9-
.usage("$0", "Generate statistics")
10-
.option("verbose", {
11-
alias: "v",
12-
describe: "Show more detailed stats",
13-
type: "count",
14-
default: 0,
15-
}).argv;
9+
.usage("$0", "Generate statistics").argv;
1610

17-
export function stats(detailed: boolean = false) {
11+
export function stats() {
1812
const featureCount = Object.values(features).filter(
1913
isOrdinaryFeatureData,
2014
).length;
@@ -30,17 +24,10 @@ export function stats(detailed: boolean = false) {
3024
}),
3125
),
3226
);
33-
const toDoKeys = [];
3427

3528
for (const f of new Compat().walk()) {
3629
if (!f.id.startsWith("webextensions")) {
3730
keys.push(f.id);
38-
39-
if (!f.deprecated && f.standard_track) {
40-
if (!doneKeys.includes(f.id)) {
41-
toDoKeys.push(f.id);
42-
}
43-
}
4431
}
4532
}
4633

@@ -71,19 +58,13 @@ export function stats(detailed: boolean = false) {
7158
.sort(([, frequencyA], [, frequencyB]) => frequencyA - frequencyB)
7259
.pop()[0];
7360
})(),
74-
currentBurndown: undefined,
75-
currentBurndownSize: toDoKeys.length,
7661
};
7762

78-
if (detailed) {
79-
result.currentBurndown = toDoKeys;
80-
}
81-
8263
return result;
8364
}
8465

8566
if (import.meta.url.startsWith("file:")) {
8667
if (process.argv[1] === fileURLToPath(import.meta.url)) {
87-
console.log(JSON.stringify(stats(argv.verbose), undefined, 2));
68+
console.log(JSON.stringify(stats(), undefined, 2));
8869
}
8970
}

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+
([, aDays], [, bDays]) => aDays - bDays,
72+
);
73+
74+
if (argv.format === "yaml") {
75+
for (const [f] 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)