From 9ba9cb45bce789a2077faca12cc72046eb5c91cb Mon Sep 17 00:00:00 2001 From: Francois Daoust Date: Tue, 28 Nov 2023 18:56:45 +0100 Subject: [PATCH 1/5] Add AOM specs AVIF had already been added to the list. This adds remaining specs from the Alliance for Open Media related to AV1. Logic also updated to find more info about these specs automatically. Fixes #1088. --- specs.json | 31 ++++++++++++++++++++++++++++++- src/compute-repository.js | 1 + src/fetch-groups.js | 11 +++++++++++ test/fetch-groups.js | 9 +++++++++ 4 files changed, 51 insertions(+), 1 deletion(-) diff --git a/specs.json b/specs.json index 033a03da..908722b1 100644 --- a/specs.json +++ b/specs.json @@ -1,7 +1,7 @@ [ + "https://aomediacodec.github.io/afgs1-spec/", { "url": "https://aomediacodec.github.io/av1-avif/", - "organization": "Alliance for Open Media", "groups": [ { "name": "Storage and Transport Formats Working Group", @@ -9,6 +9,35 @@ } ] }, + "https://aomediacodec.github.io/av1-hdr10plus/", + { + "url": "https://aomediacodec.github.io/av1-isobmff/", + "groups": [ + { + "name": "Storage and Transport Formats Working Group", + "url": "https://aomedia.org/about/#storage-and-transport-formats-working-group" + } + ] + }, + { + "url": "https://aomediacodec.github.io/av1-mpeg2-ts/", + "groups": [ + { + "name": "Storage and Transport Formats Working Group", + "url": "https://aomedia.org/about/#storage-and-transport-formats-working-group" + } + ] + }, + { + "url": "https://aomediacodec.github.io/av1-rtp-spec/", + "groups": [ + { + "name": "Storage and Transport Formats Working Group", + "url": "https://aomedia.org/about/#storage-and-transport-formats-working-group" + } + ] + }, + "https://aomediacodec.github.io/av1-spec/", { "url": "https://compat.spec.whatwg.org/", "nightly": { diff --git a/src/compute-repository.js b/src/compute-repository.js index 52d02d65..8b8f33bd 100644 --- a/src/compute-repository.js +++ b/src/compute-repository.js @@ -130,6 +130,7 @@ module.exports = async function (specs, options) { "index.src.html", "index.bs", "spec.bs", + "index.md", "index.html" ); diff --git a/src/fetch-groups.js b/src/fetch-groups.js index 04b4a253..060ad76a 100644 --- a/src/fetch-groups.js +++ b/src/fetch-groups.js @@ -126,6 +126,17 @@ module.exports = async function (specs, options) { }]; } + // For the Alliance for Open Media (AOM), let's consider that the Codec WG + // is the default group, noting that it is not super clear which AOM group + // develops which spec in practice: https://aomedia.org/about/ + if (info && info.owner === "aomediacodec") { + spec.organization = spec.organization ?? "Alliance for Open Media"; + spec.groups = spec.groups ?? [{ + name: "Codec Working Group", + url: "https://aomedia.org/about/#codec-working-group" + }] + } + // All specs that remain should be developed by some W3C group. spec.organization = spec.organization ?? "W3C"; diff --git a/test/fetch-groups.js b/test/fetch-groups.js index d5b6df1c..f0b7fc9b 100644 --- a/test/fetch-groups.js +++ b/test/fetch-groups.js @@ -93,6 +93,15 @@ describe("fetch-groups module (without API keys)", function () { }]); }); + it("handles AOM specs", async () => { + const res = await fetchGroupsFor("https://aomediacodec.github.io/afgs1-spec/"); + assert.equal(res.organization, "Alliance for Open Media"); + assert.deepStrictEqual(res.groups, [{ + name: "Codec Working Group", + url: "https://aomedia.org/about/#codec-working-group" + }]); + }); + it("preserves provided info", async () => { const spec = { url: "https://url.spec.whatwg.org/", From e4477bf1dc48b314099875e58bb7fd69d5940c98 Mon Sep 17 00:00:00 2001 From: Francois Daoust Date: Wed, 29 Nov 2023 11:34:25 +0100 Subject: [PATCH 2/5] Skip "(Draft)" and "(vX.Y)" when computing the short title This is useful for AOM specs. The update also makes the regular expression case-insensitive, which will bring a handful of updates to short titles in the list, e.g., dropping "proposal" from the short titles of some TC39 proposals. --- src/compute-shorttitle.js | 24 ++++++++++++++---------- test/compute-shorttitle.js | 12 ++++++++++++ 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/compute-shorttitle.js b/src/compute-shorttitle.js index b13d7d7d..af0bedd2 100644 --- a/src/compute-shorttitle.js +++ b/src/compute-shorttitle.js @@ -28,16 +28,20 @@ module.exports = function (title) { const level = title.match(/\s(\d+(\.\d+)?)$/); const shortTitle = title - .replace(/\s/g, ' ') // Replace non-breaking spaces - .replace(/ \d+(\.\d+)?$/, '') // Drop level number for now - .replace(/( -)? Level$/, '') // Drop "Level" - .replace(/ Module$/, '') // Drop "Module" (now followed by level) - .replace(/ Proposal$/, '') // Drop "Proposal" (TC39 proposals) - .replace(/ Specification$/, '') // Drop "Specification" - .replace(/ Standard$/, '') // Drop "Standard" and "Living Standard" - .replace(/ Living$/, '') - .replace(/ \([^\)]+ Edition\)/, '') // Drop edition indication - .replace(/^.*\(([^\)]+)\).*$/, '$1'); // Use abbr between parentheses + .trim() + .replace(/\s/g, ' ') // Replace non-breaking spaces + .replace(/ \d+(\.\d+)?$/, '') // Drop level number for now + .replace(/( -)? Level$/i, '') // Drop "Level" + .replace(/ \(\v\d+(\.\d+)?\)/i, '') // Drop "(vx.y)" + .replace(/\(Draft\)/i, '') // Drop "(Draft)" indication + .replace(/ Module$/i, '') // Drop "Module" (now followed by level) + .replace(/ Proposal$/i, '') // Drop "Proposal" (TC39 proposals) + .replace(/ Specification$/i, '') // Drop "Specification" + .replace(/ Standard$/i, '') // Drop "Standard" and "Living Standard" + .replace(/ Living$/i, '') + .replace(/ \([^\)]+ Edition\)/i, '') // Drop edition indication + .replace(/^.*\(([^\)]+)\).*$/, '$1') // Use abbr between parentheses + .trim(); if (level) { return shortTitle + " " + level[1]; diff --git a/test/compute-shorttitle.js b/test/compute-shorttitle.js index f718a853..192c20fb 100644 --- a/test/compute-shorttitle.js +++ b/test/compute-shorttitle.js @@ -79,6 +79,12 @@ describe("compute-shorttitle module", () => { "Foo Bar"); }); + it("drops '(Draft)' from title", () => { + assertTitle( + "(Draft) Beer", + "Beer"); + }); + it("preserves title when needed", () => { assertTitle( "Edition Module Standard Foo", @@ -96,4 +102,10 @@ describe("compute-shorttitle module", () => { "Hypertext Transfer Protocol (HTTP/1.1): Foo bar", "HTTP/1.1 Foo bar") }); + + it("applies rules in order", () => { + assertTitle( + " AOMedia Film Grain Synthesis (v1.0) (AFGS1) specification (Draft) ", + "AFGS1") + }); }); From 5a9cf9c89e720676b9f72a634ddfbcf3732d51ee Mon Sep 17 00:00:00 2001 From: Francois Daoust Date: Wed, 29 Nov 2023 11:37:23 +0100 Subject: [PATCH 3/5] Remove AV1 film grain synthesis from the browser category The spec actually builds on the film grain synthesis *in* AV1, which should thus be supported by browsers, but its core purpose is to make it reusable in other codecs, and I'm not clear yet that this is being supported anywhere. --- specs.json | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/specs.json b/specs.json index 908722b1..3eebd42e 100644 --- a/specs.json +++ b/specs.json @@ -1,5 +1,10 @@ [ - "https://aomediacodec.github.io/afgs1-spec/", + { + "url": "https://aomediacodec.github.io/afgs1-spec/", + "categories": [ + "-browser" + ] + }, { "url": "https://aomediacodec.github.io/av1-avif/", "groups": [ From 008bb6ed1656dbe18806b06956096204fafe4d22 Mon Sep 17 00:00:00 2001 From: Francois Daoust Date: Wed, 29 Nov 2023 15:52:35 +0100 Subject: [PATCH 4/5] Better support AOM specs: spec status and PDF release AOM specs will now be flagged with an AOM status, which can be one of "Draft Deliverable" or "Final Deliverable". There is unfortunately no good way to detect that an AOM is a "Final Deliverable", this has to be specified in `specs.json`. The code now also automatically creates a `release` property when the canonical URL of an AOM spec is a PDF. Now, as far as I can tell, the main AV1 spec is the only one that points at its PDF version as being the authoritative representation. Other final deliverables do not say anything about the published PDF. I'm sticking to the HTML URLs as a result. --- schema/definitions.json | 5 ++++- specs.json | 19 ++++++++++++++++--- src/determine-filename.js | 2 +- src/fetch-info.js | 19 ++++++++++++++++++- test/determine-filename.js | 8 +++++++- test/fetch-info.js | 16 ++++++++++++++++ 6 files changed, 62 insertions(+), 7 deletions(-) diff --git a/schema/definitions.json b/schema/definitions.json index 1d0f044f..668f5f7c 100644 --- a/schema/definitions.json +++ b/schema/definitions.json @@ -10,7 +10,7 @@ "filename": { "type": "string", - "pattern": "^[\\w\\-\\.]+\\.html$" + "pattern": "^[\\w\\-\\.]+\\.(html|pdf)$" }, "relativePath": { @@ -75,6 +75,7 @@ "Discontinued Draft", "Draft Note", "Draft Registry", + "Final Deliverable", "First Public Working Draft", "Note", "Proposed Recommendation", @@ -101,10 +102,12 @@ "enum": [ "A Collection of Interesting Ideas", "Draft Community Group Report", + "Draft Deliverable", "Draft Finding", "Draft Registry", "Editor's Draft", "Experimental", + "Final Deliverable", "Informational", "Internet Standard", "Living Standard", diff --git a/specs.json b/specs.json index 3eebd42e..3a5df423 100644 --- a/specs.json +++ b/specs.json @@ -12,9 +12,17 @@ "name": "Storage and Transport Formats Working Group", "url": "https://aomedia.org/about/#storage-and-transport-formats-working-group" } - ] + ], + "nightly": { + "status": "Final Deliverable" + } + }, + { + "url": "https://aomediacodec.github.io/av1-hdr10plus/", + "nightly": { + "status": "Final Deliverable" + } }, - "https://aomediacodec.github.io/av1-hdr10plus/", { "url": "https://aomediacodec.github.io/av1-isobmff/", "groups": [ @@ -42,7 +50,12 @@ } ] }, - "https://aomediacodec.github.io/av1-spec/", + { + "url": "https://aomediacodec.github.io/av1-spec/av1-spec.pdf", + "nightly": { + "url": "https://aomediacodec.github.io/av1-spec/" + } + }, { "url": "https://compat.spec.whatwg.org/", "nightly": { diff --git a/src/determine-filename.js b/src/determine-filename.js index 78bf40f4..ef0339d6 100644 --- a/src/determine-filename.js +++ b/src/determine-filename.js @@ -11,7 +11,7 @@ module.exports = async function (url) { // Extract filename directly from the URL when possible - const match = url.match(/\/([^/]+\.html)$/); + const match = url.match(/\/([^/]+\.(html|pdf))$/); if (match) { return match[1]; } diff --git a/src/fetch-info.js b/src/fetch-info.js index 10c81cc5..763e36cf 100644 --- a/src/fetch-info.js +++ b/src/fetch-info.js @@ -558,10 +558,27 @@ async function fetchInfoFromSpecs(specs, options) { throw new Error(titleAndStatus.error + `, in ${url} for ${spec.shortname}`); } else { - return { + const res = { nightly: { url, status: titleAndStatus.status }, title: titleAndStatus.title }; + + // The AOM has Draft Deliverables and Final Deliverables. Most AOM + // specs don't say what they are, we'll assume that they are drafts. + if (spec.organization === "Alliance for Open Media") { + if (res.nightly.status === "Editor's Draft" || + res.nightly.status === "AOM Working Group Draft") { + res.nightly.status = "Draft Deliverable"; + } + if (spec.nightly?.url && spec.url !== spec.nightly.url) { + res.release = { + url: spec.url, + status: "Final Deliverable" + }; + } + } + + return res; } } finally { diff --git a/test/determine-filename.js b/test/determine-filename.js index c76987b3..78cafb29 100644 --- a/test/determine-filename.js +++ b/test/determine-filename.js @@ -6,12 +6,18 @@ describe("determine-filename module", function () { this.slow(5000); this.timeout(30000); - it("extracts filename from URL", async () => { + it("extracts filename from URL (.html)", async () => { const url = "https://example.org/spec/filename.html"; const filename = await determineFilename(url); assert.equal(filename, "filename.html"); }); + it("extracts filename from URL (.pdf)", async () => { + const url = "https://example.org/spec/filename.pdf"; + const filename = await determineFilename(url); + assert.equal(filename, "filename.pdf"); + }); + it("finds index.html filenames", async () => { const url = "https://w3c.github.io/presentation-api/"; const filename = await determineFilename(url); diff --git a/test/fetch-info.js b/test/fetch-info.js index e59c75b9..522b913d 100644 --- a/test/fetch-info.js +++ b/test/fetch-info.js @@ -198,6 +198,22 @@ describe("fetch-info module", function () { assert.equal(info[spec.shortname].nightly.status, "Editor's Draft"); assert.equal(info[spec.shortname].title, "Intl.Segmenter Proposal"); }); + + it("creates a release for final AOM deliverables published as PDF", async () => { + const spec = { + url: "https://aomediacodec.github.io/av1-spec/av1-spec.pdf", + shortname: "av1-spec", + nightly: { + url: "https://aomediacodec.github.io/av1-spec/" + } + }; + const info = await fetchInfo([spec]); + assert.ok(info[spec.shortname]); + assert.equal(info[spec.shortname].source, "spec"); + assert.equal(info[spec.shortname].nightly.url, spec.nightly.url); + assert.equal(info[spec.shortname].release.url, spec.url); + assert.equal(info[spec.shortname].release.status, "Final Deliverable"); + }); }); describe("fetch from W3C API", () => { From 1e7d9ec48464e0544122e549538e3e8709096229 Mon Sep 17 00:00:00 2001 From: Francois Daoust Date: Wed, 29 Nov 2023 16:11:53 +0100 Subject: [PATCH 5/5] Fix fetch-info test on AOM spec --- test/fetch-info.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/fetch-info.js b/test/fetch-info.js index 522b913d..4edbec13 100644 --- a/test/fetch-info.js +++ b/test/fetch-info.js @@ -201,6 +201,7 @@ describe("fetch-info module", function () { it("creates a release for final AOM deliverables published as PDF", async () => { const spec = { + organization: "Alliance for Open Media", url: "https://aomediacodec.github.io/av1-spec/av1-spec.pdf", shortname: "av1-spec", nightly: { @@ -211,6 +212,7 @@ describe("fetch-info module", function () { assert.ok(info[spec.shortname]); assert.equal(info[spec.shortname].source, "spec"); assert.equal(info[spec.shortname].nightly.url, spec.nightly.url); + assert.ok(info[spec.shortname].release); assert.equal(info[spec.shortname].release.url, spec.url); assert.equal(info[spec.shortname].release.status, "Final Deliverable"); });