-
Notifications
You must be signed in to change notification settings - Fork 102
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a script to generate a draft feature per spec (#1195)
One of the features, the Vibration API, is added to show what this will look like.
- Loading branch information
Showing
5 changed files
with
139 additions
and
1 deletion.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# Draft spec features | ||
|
||
This directory is for draft features organized by spec. These features require | ||
review before being added to web-features, as most specs define more than one | ||
feature and many features span specs. | ||
|
||
To help out, pick a feature and do the following: | ||
|
||
- Follow the spec link and make a judgment whether it's reasonable to describe | ||
this as a single features or if needs to be split up. | ||
- Review `baseline_low_date`, does it look plausible? If not, remove features | ||
from `compat_features` until the date and browser versions seem plausible. Run | ||
`npm run dist features/draft/spec` to regenerate dist. | ||
- Write a description for the feature. | ||
- Move the file into the main features/ directory and submit a PR with your | ||
changes. | ||
|
||
Happy YAMLing! |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
draft_date: 2024-06-07 | ||
name: Vibration API (Second Edition) | ||
description: TODO | ||
spec: https://w3c.github.io/vibration/ | ||
compat_features: | ||
- api.Navigator.vibrate |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# Generated from: vibration.yml | ||
# Do not edit this file by hand. Edit the source file instead! | ||
|
||
status: | ||
baseline: false | ||
support: | ||
chrome: "32" | ||
chrome_android: "32" | ||
edge: "79" | ||
firefox: "16" |
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
import { Compat } from "compute-baseline/browser-compat-data"; | ||
import fs from "node:fs/promises"; | ||
import { fileURLToPath } from "node:url"; | ||
import YAML from "yaml"; | ||
import webSpecs from 'web-specs' assert { type: 'json' }; | ||
import features from '../index.js'; | ||
|
||
function* getPages(spec): Generator<string> { | ||
yield spec.url; | ||
if (spec.nightly?.url) { | ||
yield spec.nightly.url; | ||
} | ||
if (spec.nightly?.pages) { | ||
yield* spec.nightly.pages; | ||
} | ||
} | ||
|
||
function normalize(page: string) { | ||
const url = new URL(page); | ||
// Remove any fragment. | ||
url.hash = ''; | ||
// Collapse HTML and ECMA-262 multipage into a single canonical page. | ||
const multipageIndex = url.pathname.indexOf('/multipage/'); | ||
if (multipageIndex !== -1) { | ||
url.pathname = url.pathname.substring(0, multipageIndex + 1); | ||
} | ||
// Strip levels from CSS specs. | ||
if (url.hostname.startsWith('drafts.')) { | ||
url.pathname = url.pathname.replace(/-\d+\/$/, '/'); | ||
} | ||
return String(url); | ||
} | ||
|
||
async function main() { | ||
const compat = new Compat(); | ||
|
||
// Build a set of used BCD keys. | ||
const usedFeatures = new Set<string>( | ||
Object.values(features).flatMap((data) => data.compat_features) | ||
); | ||
|
||
// Build a map from URLs to spec. | ||
const pageToSpec = new Map<string, object>(); | ||
for (const spec of webSpecs) { | ||
for (const page of getPages(spec)) { | ||
pageToSpec.set(normalize(page), spec); | ||
} | ||
} | ||
|
||
// Iterate BCD and group compat features by spec. | ||
const specToCompatFeatures = new Map<object, Set<string>>(); | ||
for (const feature of compat.walk()) { | ||
// Skip any BCD keys already used in web-features. | ||
if (usedFeatures.has(feature.id)) { | ||
continue; | ||
} | ||
|
||
// Skip deprecated and non-standard features. | ||
const status = feature.data.__compat.status; | ||
if (status?.deprecated || !status?.standard_track) { | ||
continue; | ||
} | ||
|
||
const spec_url = feature.data.__compat.spec_url; | ||
if (!spec_url) { | ||
continue; | ||
} | ||
|
||
const urls = Array.isArray(spec_url) ? spec_url : [spec_url]; | ||
for (const url of urls) { | ||
const spec = pageToSpec.get(normalize(url)); | ||
if (!spec) { | ||
console.warn(`${url} not matched to any spec`); | ||
continue; | ||
} | ||
const keys = specToCompatFeatures.get(spec); | ||
if (keys) { | ||
keys.add(feature.id); | ||
} else { | ||
specToCompatFeatures.set(spec, new Set([feature.id])); | ||
} | ||
} | ||
} | ||
|
||
for (const [spec, compatFeatures] of specToCompatFeatures.entries()) { | ||
// Write out draft feature per spec. | ||
const id = spec.shortname; | ||
|
||
const feature = { | ||
draft_date: new Date().toISOString().substring(0, 10), | ||
name: spec.title, | ||
description: 'TODO', | ||
spec: spec.nightly?.url ?? spec.url, | ||
compat_features: Array.from(compatFeatures).sort(), | ||
}; | ||
const yaml = YAML.stringify(feature); | ||
await fs.writeFile(`features/draft/spec/${id}.yml`, yaml); | ||
} | ||
} | ||
|
||
if (process.argv[1] === fileURLToPath(import.meta.url)) { | ||
await main(); | ||
} |