Skip to content

Commit 766c75d

Browse files
committed
feat: Add schema validation and data combination script
This commit introduces two main features to improve data quality and ease of use: Schema Validation: A schemas.json file is added to define a strict schema for each of the mapping files. A new lint-schemas.js script validates the mapping files against these schemas. It also checks that all feature IDs exist in the web-features package. Combined Data: A new combine-mappings.js script aggregates data from all individual mapping files into a single web-features-mappings.combined.json file. This provides a single, convenient file for data consumers. The package.json has been updated with lint:schemas and combine scripts to run these new tools. The README and .gitignore have also been updated accordingly.
1 parent a0e17fc commit 766c75d

File tree

8 files changed

+537
-62
lines changed

8 files changed

+537
-62
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
node_modules
2+
wpt-repo
3+
surveys
4+
web-features-mappings.combined.json

README.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ Examples of data sources which already map to web-features IDs and for which we
4545

4646
## The scripts folder
4747

48-
The `/script/` folder contains the JavaScript files that are responsible for updating the mapping files.
48+
The `/scripts/` folder contains the JavaScript files that are responsible for updating the mapping files.
4949

5050
To run these scripts:
5151

@@ -63,6 +63,20 @@ The mappings are JSON files that are formatted as follows:
6363
}
6464
```
6565

66+
## Combined data
67+
68+
The `combine` script generates a `web-features-mappings.combined.json` file in the root of the repository. This file contains all the mapping data from the `mappings` folder, combined into a single file.
69+
70+
The format of the combined file is as follows:
71+
72+
```json
73+
{
74+
"chrome-use-counters": { ... },
75+
"interop": { ... },
76+
...
77+
}
78+
```
79+
6680
## TODO
6781

6882
* Add mapping to origin trials.

schemas.json

Lines changed: 303 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,303 @@
1+
{
2+
"$schema": "https://json-schema.org/draft/2020-12/schema",
3+
"title": "Web Feature Mappings Data",
4+
"description": "A collection of schemas for each of the web feature mapping files.",
5+
"type": "object",
6+
"properties": {
7+
"chrome-use-counters": {
8+
"$ref": "#/$defs/chromeUseCountersFile"
9+
},
10+
"interop": {
11+
"$ref": "#/$defs/interopFile"
12+
},
13+
"mdn-docs": {
14+
"$ref": "#/$defs/mdnDocsFile"
15+
},
16+
"standards-positions": {
17+
"$ref": "#/$defs/standardsPositionsFile"
18+
},
19+
"state-of-surveys": {
20+
"$ref": "#/$defs/stateOfSurveysFile"
21+
},
22+
"wpt": {
23+
"$ref": "#/$defs/wptFile"
24+
}
25+
},
26+
"$comment": "The properties are the file names of the files in the mapping directory",
27+
"additionalProperties": false,
28+
"$defs": {
29+
"chromeUseCountersFile": {
30+
"description": "Schema for chrome-use-counters.json. An object where keys are feature IDs and values are usage metrics.",
31+
"type": "object",
32+
"patternProperties": {
33+
".*": {
34+
"$ref": "#/$defs/useCounterValue"
35+
}
36+
},
37+
"additionalProperties": false
38+
},
39+
"interopFile": {
40+
"description": "Schema for interop.json. An object where keys are feature IDs and values are an array of interop records.",
41+
"type": "object",
42+
"patternProperties": {
43+
".*": {
44+
"$ref": "#/$defs/interopHistory"
45+
}
46+
},
47+
"additionalProperties": false
48+
},
49+
"mdnDocsFile": {
50+
"description": "Schema for mdn-docs.json. An object where keys are feature IDs and values are an array of MDN documentation links.",
51+
"type": "object",
52+
"patternProperties": {
53+
".*": {
54+
"$ref": "#/$defs/mdnLinkArray"
55+
}
56+
},
57+
"additionalProperties": false
58+
},
59+
"standardsPositionsFile": {
60+
"description": "Schema for standards-positions.json. An object where keys are feature IDs and values are an array of standards position records.",
61+
"type": "object",
62+
"patternProperties": {
63+
".*": {
64+
"$ref": "#/$defs/standardsPositionArray"
65+
}
66+
},
67+
"additionalProperties": false
68+
},
69+
"stateOfSurveysFile": {
70+
"description": "Schema for state-of-surveys.json. An object where keys are feature IDs and values are an array of survey records.",
71+
"type": "object",
72+
"patternProperties": {
73+
".*": {
74+
"$ref": "#/$defs/surveyRecordArray"
75+
}
76+
},
77+
"additionalProperties": false
78+
},
79+
"wptFile": {
80+
"description": "Schema for wpt.json. An object where keys are feature IDs and values are a record of Web Platform Tests.",
81+
"type": "object",
82+
"patternProperties": {
83+
".*": {
84+
"$ref": "#/$defs/wptRecord"
85+
}
86+
},
87+
"additionalProperties": false
88+
},
89+
"useCounterValue": {
90+
"type": "object",
91+
"description": "The usage metrics for a single web feature from chrome-use-counters.json.",
92+
"properties": {
93+
"percentageOfPageLoad": {
94+
"type": "number"
95+
},
96+
"url": {
97+
"type": "string",
98+
"format": "uri"
99+
}
100+
},
101+
"required": [
102+
"percentageOfPageLoad",
103+
"url"
104+
],
105+
"additionalProperties": false
106+
},
107+
"interopHistory": {
108+
"description": "An array of Interop records from interop.json.",
109+
"type": "array",
110+
"items": {
111+
"$ref": "#/$defs/interopRecord"
112+
},
113+
"minItems": 1
114+
},
115+
"interopRecord": {
116+
"type": "object",
117+
"properties": {
118+
"year": {
119+
"type": "integer"
120+
},
121+
"label": {
122+
"type": "string"
123+
},
124+
"url": {
125+
"type": "string",
126+
"format": "uri"
127+
}
128+
},
129+
"required": [
130+
"year",
131+
"label",
132+
"url"
133+
],
134+
"additionalProperties": false
135+
},
136+
"mdnLinkArray": {
137+
"description": "An array of MDN documentation links from mdn-docs.json.",
138+
"type": "array",
139+
"items": {
140+
"$ref": "#/$defs/mdnLink"
141+
},
142+
"minItems": 1
143+
},
144+
"mdnLink": {
145+
"type": "object",
146+
"properties": {
147+
"slug": {
148+
"type": "string"
149+
},
150+
"title": {
151+
"type": "string"
152+
},
153+
"anchor": {
154+
"type": [
155+
"string",
156+
"null"
157+
]
158+
},
159+
"url": {
160+
"type": "string",
161+
"format": "uri"
162+
}
163+
},
164+
"required": [
165+
"slug",
166+
"title",
167+
"anchor",
168+
"url"
169+
],
170+
"additionalProperties": false
171+
},
172+
"standardsPositionArray": {
173+
"description": "An array of standards position records from standards-positions.json.",
174+
"type": "array",
175+
"items": {
176+
"$ref": "#/$defs/standardsPositionRecord"
177+
},
178+
"minItems": 1
179+
},
180+
"standardsPositionRecord": {
181+
"type": "object",
182+
"properties": {
183+
"vendor": {
184+
"type": "string",
185+
"enum": [
186+
"mozilla",
187+
"webkit"
188+
]
189+
},
190+
"url": {
191+
"type": "string",
192+
"format": "uri"
193+
},
194+
"position": {
195+
"type": "string",
196+
"enum": [
197+
"",
198+
"blocked",
199+
"defer",
200+
"negative",
201+
"neutral",
202+
"oppose",
203+
"positive",
204+
"support"
205+
]
206+
},
207+
"concerns": {
208+
"type": "array",
209+
"items": {
210+
"type": "string",
211+
"enum": [
212+
"API design",
213+
"accessibility",
214+
"annoyance",
215+
"compatibility",
216+
"complexity",
217+
"dependencies",
218+
"device independence",
219+
"duplication",
220+
"integration",
221+
"internationalization",
222+
"interoperability",
223+
"maintenance",
224+
"performance",
225+
"portability",
226+
"power",
227+
"privacy",
228+
"security",
229+
"use cases",
230+
"venue"
231+
]
232+
}
233+
}
234+
},
235+
"required": [
236+
"vendor",
237+
"url",
238+
"position",
239+
"concerns"
240+
],
241+
"additionalProperties": false
242+
},
243+
"surveyRecordArray": {
244+
"description": "An array of survey records from state-of-surveys.json.",
245+
"type": "array",
246+
"items": {
247+
"$ref": "#/$defs/surveyRecord"
248+
},
249+
"minItems": 1
250+
},
251+
"surveyRecord": {
252+
"type": "object",
253+
"properties": {
254+
"name": {
255+
"type": "string"
256+
},
257+
"url": {
258+
"type": "string",
259+
"format": "uri"
260+
},
261+
"question": {
262+
"type": "string"
263+
},
264+
"subQuestion": {
265+
"type": "string"
266+
},
267+
"path": {
268+
"type": "string"
269+
}
270+
},
271+
"required": [
272+
"name",
273+
"url",
274+
"question",
275+
"subQuestion",
276+
"path"
277+
],
278+
"additionalProperties": false
279+
},
280+
"wptRecord": {
281+
"type": "object",
282+
"description": "A record of Web Platform Tests from wpt.json.",
283+
"properties": {
284+
"url": {
285+
"type": "string",
286+
"format": "uri"
287+
},
288+
"tests": {
289+
"type": "array",
290+
"items": {
291+
"type": "string"
292+
},
293+
"minItems": 1
294+
}
295+
},
296+
"required": [
297+
"url",
298+
"tests"
299+
],
300+
"additionalProperties": false
301+
}
302+
}
303+
}

scripts/.gitignore

Lines changed: 0 additions & 3 deletions
This file was deleted.

scripts/combine-mappings.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import fs from "fs/promises";
2+
import path from "path";
3+
import { glob } from "glob";
4+
import { fileURLToPath } from "url";
5+
6+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
7+
8+
async function main() {
9+
console.log("Combining mapping files...");
10+
11+
const mappingFiles = await glob(path.join(__dirname, "../mappings/*.json"));
12+
13+
const combinedData = {};
14+
15+
for (const file of mappingFiles) {
16+
const fileKey = path.basename(file, ".json");
17+
const data = JSON.parse(await fs.readFile(file, "utf-8"));
18+
combinedData[fileKey] = data;
19+
}
20+
21+
const outputFile = path.join(__dirname, "../web-features-mappings.combined.json");
22+
await fs.writeFile(outputFile, JSON.stringify(combinedData, null, 2));
23+
24+
console.log(`Combined data written to ${outputFile}`);
25+
}
26+
27+
main().catch((err) => {
28+
console.error(err);
29+
process.exit(1);
30+
});

0 commit comments

Comments
 (0)