Skip to content
Merged
Show file tree
Hide file tree
Changes from 42 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
9846b90
Demonstrate JSON Schema as source of truth
ddbeck May 20, 2025
1012068
Replace types with newly generated types
ddbeck May 26, 2025
77bf8f9
Add new types to web-features package build
ddbeck May 26, 2025
7742c64
Format types.ts
ddbeck May 27, 2025
7f7aa98
Fix schema key sort order
ddbeck May 26, 2025
459ac43
Add redirect feature schema types
ddbeck May 27, 2025
758e77a
Update scripts to use redirects
ddbeck May 27, 2025
2294698
Split webcodecs
ddbeck May 27, 2025
eaf208d
Rename `numeric-seperators`
ddbeck May 27, 2025
dc4974b
Prevent double and circular redirects
ddbeck May 27, 2025
95bf898
Merge branch 'main' into 91-jsonschema-source-of-truth
ddbeck Jun 10, 2025
b2b6762
Add unintentionally missing required fields
ddbeck Jun 10, 2025
dd23730
Add more property constraints to reduce any in TS
ddbeck Jun 10, 2025
a8b6ba1
Merge branch 'main' into 91-jsonschema-source-of-truth
ddbeck Jun 30, 2025
6e383ff
Drop tsup and export our types directly
ddbeck Jun 30, 2025
036bdaf
Merge branch '91-jsonschema-source-of-truth' into 91-redirects
ddbeck Jun 30, 2025
cf6fad8
Merge branch 'main' into 91-jsonschema-source-of-truth
ddbeck Jul 16, 2025
0d54e06
Fix bad Quicktype command parsing
ddbeck Jul 16, 2025
c01bba1
Merge branch '91-jsonschema-source-of-truth' into 91-redirects
ddbeck Jul 16, 2025
7f7c96f
Provide discriminator property on feature data
ddbeck Jul 22, 2025
9b276f0
Use single-color-gradients as split demonstrator feature
ddbeck Jul 22, 2025
66adbd4
fixup! Use single-color-gradients as split demonstrator feature
ddbeck Jul 22, 2025
6ad4e80
Set `kind: feature` at runtime, for author convenience
ddbeck Jul 22, 2025
7845c1a
Fix switch statement exhaustiveness check
ddbeck Jul 22, 2025
0c20225
Merge branch 'main' into 91-jsonschema-source-of-truth
ddbeck Aug 7, 2025
8f02fec
Merge branch '91-jsonschema-source-of-truth' into 91-redirects
ddbeck Aug 7, 2025
d457d4d
Add `redirect_created_date` field on redirects
ddbeck Aug 7, 2025
16a5cb6
Merge branch 'main' into 91-jsonschema-source-of-truth
ddbeck Aug 18, 2025
f88369b
Fix out of date package-lock.json
ddbeck Aug 18, 2025
b133873
Merge branch '91-jsonschema-source-of-truth' into 91-redirects
ddbeck Aug 18, 2025
0074415
Merge branch 'v3.0' into 91-jsonschema-source-of-truth
ddbeck Sep 3, 2025
9de2f6c
Fix bad `package.json` merge
ddbeck Sep 3, 2025
5ae8ec4
Upgrade quicktype
ddbeck Sep 3, 2025
2bcab6c
Fix typo
ddbeck Sep 5, 2025
707c6f5
Fix Quicktype's overly permissive type for `baseline: "high" | "low" …
ddbeck Sep 5, 2025
4990926
Fix top-level `snapshots` as optional in the JSON Schema
ddbeck Sep 5, 2025
64de65d
Fix Quicktype's overly permissive type for `baseline: "high" | "low" …
ddbeck Sep 5, 2025
710f949
Merge branch '91-jsonschema-source-of-truth' into 91-redirects
ddbeck Sep 8, 2025
1717294
Merge branch 'v3.0' into 91-redirects
ddbeck Sep 8, 2025
ea6a67d
Remove redirect dating
ddbeck Sep 8, 2025
320ca18
Undo unintended change to snapshot schema
ddbeck Sep 8, 2025
27b90eb
Don't expose intermediate cleanup type
ddbeck Sep 8, 2025
0de21c7
Add tests for `assertValidFeatureReference`
ddbeck Sep 11, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions features/conic-gradients.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ status:
compat_features:
- css.types.gradient.conic-gradient
- css.types.gradient.conic-gradient.doubleposition
- css.types.gradient.conic-gradient.single_color_stop
- css.types.gradient.repeating-conic-gradient
12 changes: 12 additions & 0 deletions features/conic-gradients.yml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,15 @@ compat_features:
# safari: "12.1"
# safari_ios: "12.2"
- css.types.gradient.conic-gradient.doubleposition

# baseline: low
# baseline_low_date: 2025-04-04
# support:
# chrome: "135"
# chrome_android: "135"
# edge: "135"
# firefox: "136"
# firefox_android: "136"
# safari: "18.4"
# safari_ios: "18.4"
- css.types.gradient.conic-gradient.single_color_stop
4 changes: 4 additions & 0 deletions features/gradients.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,22 @@ compat_features:
- css.types.gradient.linear-gradient.interpolation_hints
- css.types.gradient.linear-gradient.premultiplied_gradients
- css.types.gradient.linear-gradient.to
- css.types.gradient.linear-gradient.single_color_stop
- css.types.gradient.linear-gradient.unitless_0_angle
- css.types.gradient.repeating-linear-gradient
- css.types.gradient.repeating-linear-gradient.doubleposition
- css.types.gradient.repeating-linear-gradient.interpolation_hints
- css.types.gradient.repeating-linear-gradient.to
- css.types.gradient.repeating-linear-gradient.single_color_stop
- css.types.gradient.repeating-linear-gradient.unitless_0_angle
- css.types.gradient.radial-gradient
- css.types.gradient.radial-gradient.at
- css.types.gradient.radial-gradient.doubleposition
- css.types.gradient.radial-gradient.interpolation_hints
- css.types.gradient.radial-gradient.premultiplied_gradients
- css.types.gradient.radial-gradient.single_color_stop
- css.types.gradient.repeating-radial-gradient
- css.types.gradient.repeating-radial-gradient.at
- css.types.gradient.repeating-radial-gradient.doubleposition
- css.types.gradient.repeating-radial-gradient.interpolation_hints
- css.types.gradient.repeating-radial-gradient.single_color_stop
15 changes: 15 additions & 0 deletions features/gradients.yml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -145,3 +145,18 @@ compat_features:
# safari_ios: "15"
- css.types.gradient.linear-gradient.premultiplied_gradients
- css.types.gradient.radial-gradient.premultiplied_gradients

# baseline: low
# baseline_low_date: 2025-04-04
# support:
# chrome: "135"
# chrome_android: "135"
# edge: "135"
# firefox: "136"
# firefox_android: "136"
# safari: "18.4"
# safari_ios: "18.4"
- css.types.gradient.linear-gradient.single_color_stop
- css.types.gradient.radial-gradient.single_color_stop
- css.types.gradient.repeating-linear-gradient.single_color_stop
- css.types.gradient.repeating-radial-gradient.single_color_stop
6 changes: 6 additions & 0 deletions features/numeric-separators.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
name: Numeric separators
description: To improve readability for numeric literals, underscores (`_`) can be used as separators. For example, `1_050.95` is equivalent to `1050.95`.
spec: https://tc39.es/ecma262/multipage/ecmascript-language-lexical-grammar.html#prod-NumericLiteralSeparator
group: javascript
compat_features:
- javascript.grammar.numeric_separators
17 changes: 17 additions & 0 deletions features/numeric-separators.yml.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Generated from: numeric-separators.yml
# Do not edit this file by hand. Edit the source file instead!

status:
baseline: high
baseline_low_date: 2020-07-28
baseline_high_date: 2023-01-28
support:
chrome: "75"
chrome_android: "75"
edge: "79"
firefox: "70"
firefox_android: "79"
safari: "13"
safari_ios: "13"
compat_features:
- javascript.grammar.numeric_separators
8 changes: 2 additions & 6 deletions features/numeric-seperators.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,2 @@
name: Numeric separators
description: To improve readability for numeric literals, underscores (`_`) can be used as separators. For example, `1_050.95` is equivalent to `1050.95`.
spec: https://tc39.es/ecma262/multipage/ecmascript-language-lexical-grammar.html#prod-NumericLiteralSeparator
group: javascript
compat_features:
- javascript.grammar.numeric_separators
kind: moved
redirect_target: numeric-separators
19 changes: 4 additions & 15 deletions features/numeric-seperators.yml.dist
Original file line number Diff line number Diff line change
@@ -1,17 +1,6 @@
# Generated from: numeric-seperators.yml
# Do not edit this file by hand. Edit the source file instead!
# This file intentionally left blank.
# Do not edit this file.
# The data for this feature has moved to numeric-separators.yml

status:
baseline: high
baseline_low_date: 2020-07-28
baseline_high_date: 2023-01-28
support:
chrome: "75"
chrome_android: "75"
edge: "79"
firefox: "70"
firefox_android: "79"
safari: "13"
safari_ios: "13"
compat_features:
- javascript.grammar.numeric_separators
{}
15 changes: 4 additions & 11 deletions features/single-color-gradients.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,4 @@
name: Single color stop gradients
description: A single color stop can be provided to the `linear-gradient()`, `radial-gradient()`, and `conic-gradient()` CSS functions, and their repeating counterparts, to create a solid color background.
spec: https://drafts.csswg.org/css-images-4/#color-stop-syntax
group: gradients
compat_features:
- css.types.gradient.conic-gradient.single_color_stop
- css.types.gradient.linear-gradient.single_color_stop
- css.types.gradient.radial-gradient.single_color_stop
- css.types.gradient.repeating-conic-gradient.single_color_stop
- css.types.gradient.repeating-linear-gradient.single_color_stop
- css.types.gradient.repeating-radial-gradient.single_color_stop
kind: split
redirect_targets:
- gradients
- conic-gradients
25 changes: 6 additions & 19 deletions features/single-color-gradients.yml.dist
Original file line number Diff line number Diff line change
@@ -1,21 +1,8 @@
# Generated from: single-color-gradients.yml
# Do not edit this file by hand. Edit the source file instead!
# This file intentionally left blank.
# Do not edit this file.
# The data for this feature has moved to:
# - gradients.yml
# - conic-gradients.yml

status:
baseline: low
baseline_low_date: 2025-04-04
support:
chrome: "135"
chrome_android: "135"
edge: "135"
firefox: "136"
firefox_android: "136"
safari: "18.4"
safari_ios: "18.4"
compat_features:
- css.types.gradient.conic-gradient.single_color_stop
- css.types.gradient.linear-gradient.single_color_stop
- css.types.gradient.radial-gradient.single_color_stop
- css.types.gradient.repeating-conic-gradient.single_color_stop
- css.types.gradient.repeating-linear-gradient.single_color_stop
- css.types.gradient.repeating-radial-gradient.single_color_stop
{}
45 changes: 38 additions & 7 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ import { Temporal } from '@js-temporal/polyfill';
import { fdir } from 'fdir';
import YAML from 'yaml';
import { convertMarkdown } from "./text";
import { FeatureData, GroupData, SnapshotData, WebFeaturesData } from './types';
import { GroupData, SnapshotData, WebFeaturesData } from './types';

import { BASELINE_LOW_TO_HIGH_DURATION, coreBrowserSet, parseRangedDateString } from 'compute-baseline';
import { Compat } from 'compute-baseline/browser-compat-data';
import { isMoved, isSplit } from './type-guards';

// The longest name allowed, to allow for compact display.
const nameMaxLength = 80;
Expand Down Expand Up @@ -120,7 +121,7 @@ function* identifiers(value) {
// Map from BCD keys/paths to web-features identifiers.
const bcdToFeatureId: Map<string, string> = new Map();

const features: { [key: string]: FeatureData } = {};
const features: WebFeaturesData["features"] = {};
for (const [key, data] of yamlEntries('features')) {
// Draft features reserve an identifier but aren't complete yet. Skip them.
if (data[draft]) {
Expand All @@ -130,6 +131,11 @@ for (const [key, data] of yamlEntries('features')) {
continue;
}

// Attach `kind: feature` to ordinary features
if (!isMoved(data) && !isSplit(data)) {
data.kind = "feature";
}

// Convert markdown to text+HTML.
if (data.description) {
const { text, html } = convertMarkdown(data.description);
Expand Down Expand Up @@ -185,12 +191,37 @@ for (const [key, data] of yamlEntries('features')) {
features[key] = data;
}

// Assert that discouraged feature's alternatives are valid
for (const [id, feature] of Object.entries(features)) {
for (const alternative of feature.discouraged?.alternatives ?? []) {
if (!(alternative in features)) {
throw new Error(`${id}'s alternative "${alternative}" is not a valid feature ID`);
// Assert that feature references are valid

function assertValidReference(sourceID: string, targetID: string): void {
if (targetID in features) {
if (isMoved(features[targetID]) || isSplit(features[targetID])) {
throw new Error(`${sourceID} references a redirect "${targetID}" instead of an ordinary feature ID`);
}
return;
}
throw new Error(`${sourceID}'s reference to "${targetID}" is not a valid feature ID`);
}

for (const [id, feature] of Object.entries(features)) {
const { kind } = feature;
switch (kind) {
case "feature":
for (const alternative of feature.discouraged?.alternatives ?? []) {
assertValidReference(id, alternative);
}
break;
case "moved":
assertValidReference(id, feature.redirect_target);
break;
case "split":
for (const target of feature.redirect_targets) {
assertValidReference(id, target);
}
break;
default:
kind satisfies never;
throw new Error(`Unhandled feature kind ${kind}}`);
}
}

Expand Down
117 changes: 84 additions & 33 deletions schemas/data.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,18 @@
"description": "Feature identifiers and data",
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/FeatureData"
"oneOf": [
{
"$ref": "#/definitions/FeatureData"
},
{
"$ref": "#/definitions/FeatureMovedData"
},
{
"$ref": "#/definitions/FeatureSplitData"
}
],
"$comment": "Use the `kind` property as a discriminator."
}
},
"groups": {
Expand Down Expand Up @@ -102,6 +113,9 @@
"description": "A feature data entry",
"type": "object",
"properties": {
"kind": {
"const": "feature"
},
"name": {
"description": "Short name",
"type": "string"
Expand Down Expand Up @@ -143,7 +157,44 @@
"$ref": "#/definitions/Discouraged"
}
},
"required": ["name", "description", "description_html", "spec", "status"],
"required": [
"kind",
"name",
"description",
"description_html",
"spec",
"status"
],
"additionalProperties": false
},
"FeatureMovedData": {
"description": "A feature has permanently moved to exactly one other ID",
"type": "object",
"properties": {
"kind": {
"const": "moved"
},
"redirect_target": {
"description": "The new ID for this feature",
"type": "string"
}
},
"required": ["kind", "redirect_target"],
"additionalProperties": false
},
"FeatureSplitData": {
"description": "A feature has split into two or more other features",
"type": "object",
"properties": {
"kind": {
"const": "split"
},
"redirect_targets": {
"description": "The new IDs for this feature",
"$ref": "#/definitions/Strings"
}
},
"required": ["kind", "redirect_targets"],
"additionalProperties": false
},
"GroupData": {
Expand All @@ -161,6 +212,37 @@
"required": ["name"],
"additionalProperties": false
},
"Release": {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note to other reviewers: I alphabetized these sort of on accident. This not real change for Release or SnapshotData. Please tell me if you'd rather that I revert this.

"description": "Browser release information",
"type": "object",
"properties": {
"version": {
"description": "The version string, as in \"10\" or \"17.1\"",
"type": "string"
},
"date": {
"description": " The release date, as in \"2023-12-11\"",
"type": "string"
}
},
"required": ["version", "date"],
"additionalProperties": false
},
"SnapshotData": {
"type": "object",
"properties": {
"name": {
"description": "Short name",
"type": "string"
},
"spec": {
"description": "Specification",
"type": "string"
}
},
"required": ["name", "spec"],
"additionalProperties": false
},
"Status": {
"type": "object",
"properties": {
Expand Down Expand Up @@ -226,37 +308,6 @@
"required": ["baseline", "support"],
"additionalProperties": false
},
"Release": {
"description": "Browser release information",
"type": "object",
"properties": {
"version": {
"description": "The version string, as in \"10\" or \"17.1\"",
"type": "string"
},
"date": {
"description": " The release date, as in \"2023-12-11\"",
"type": "string"
}
},
"required": ["version", "date"],
"additionalProperties": false
},
"SnapshotData": {
"type": "object",
"properties": {
"name": {
"description": "Short name",
"type": "string"
},
"spec": {
"description": "Specification",
"$ref": "#/definitions/URL"
}
},
"required": ["name", "spec"],
"additionalProperties": false
},
"StringOrStrings": {
"oneOf": [
{
Expand Down
Loading