From 3fe0145a787f71e0fd002554cb17a93a62c6f8f0 Mon Sep 17 00:00:00 2001 From: Laurent Senta Date: Wed, 13 Sep 2023 11:45:49 +0200 Subject: [PATCH 1/7] feat: add specs during generation --- munge_aggregates.js | 123 +++++++++++++++++- munge_sql.js | 29 +++++ www/content/_index.md | 5 +- www/content/specs/_index.md | 4 - .../layouts/shortcodes/specs-links.html | 13 +- .../conformance/layouts/specs/list.html | 52 ++++++++ 6 files changed, 217 insertions(+), 9 deletions(-) delete mode 100644 www/content/specs/_index.md create mode 100644 www/themes/conformance/layouts/specs/list.html diff --git a/munge_aggregates.js b/munge_aggregates.js index 732e9cd42..d008ba3dc 100644 --- a/munge_aggregates.js +++ b/munge_aggregates.js @@ -18,6 +18,51 @@ if (!dbFile || !hugoOutput) { process.exit(1); } +/** + * @param {string} u a spec URL like "specs.ipfs.tech/http-gateways/path-gateway/#if-none-match-request-header" + * @returns the spec's parent, or "null" if it's a top-level spec + */ +const computeParent = (u) => { + const url = new URL(u); + const segments = url.pathname.split('/').filter(Boolean); + + // if there's a hash, consider it as a segment + if (url.hash) segments.push(url.hash.substring(1)); + + if (segments.length <= 1) { + return "null"; + } + + const parent = segments.slice(0, -1).join('/'); + return `${url.protocol}//${url.host}/${parent}` +}; + +/** + * @param {string} u a spec URL like "specs.ipfs.tech/http-gateways/path-gateway/#if-none-match-request-header" + * @returns the spec's name, or the hash if it's a top-level spec and whether it was found in a hash + */ +const computeName = (u) => { + const url = new URL(u); + + if (url.hash) { + return { + isHashed: true, + name: url.hash.substring(1), + }; + } + + const segments = url.pathname.split('/').filter(Boolean); + + if (segments.length === 0) { + throw new Error(`Invalid spec URL: ${u}`); + } + + return { + isHashed: false, + name: segments[segments.length - 1], + }; +}; + const main = async () => { let db = new sqlite3.Database(dbFile, (err) => { if (err) { @@ -70,6 +115,72 @@ const main = async () => { } outputJSON("data/testgroups.json", groups); + // Query to fetch all test specs + const specsQuery = ` + SELECT + spec_url as full_name, + GROUP_CONCAT(DISTINCT test_run_version) AS versions + FROM TestSpecs + GROUP BY full_name + ORDER BY full_name + `; + const specsRows = await all(specsQuery); + const specs = {}; + + for (const row of specsRows) { + const { versions, full_name } = row; + let current = `https://${full_name}`; + + while (current !== "null") { + const slug = slugify(current); + const parent = computeParent(current); + const { name, isHashed } = computeName(current) + + if (!specs[parent]) { + specs[parent] = {}; + } + + specs[parent][current] = { + versions: versions?.split(',') || [], + full_name: current, + slug, + name, + isHashed, + }; + + current = parent; + } + } + outputJSON("data/specs.json", specs); + + const descendTheSpecsTree = (current, path) => { + Object.entries(specs[current] || {}) + .forEach(([key, spec]) => { + // To reproduce the structure of URLs and hashes, + // we update existing pages + if (spec.isHashed) { + const p = path.join("/"); + outputFrontmatter( + `content/specs/${p}/_index.md`, + (current) => ({ ...current, hashes: [...(current.hashes || []), spec.name] })); + // assume there are no children for hashes + return + } + + const newPath = [...path, spec.name]; + const p = newPath.join("/"); + + outputFrontmatter(`content/specs/${p}/_index.md`, { + ...spec, + title: spec.name, + }); + + descendTheSpecsTree(key, newPath); + }) + } + + descendTheSpecsTree("null", []) + // Query to fetch all stdouts const logsQuery = ` SELECT @@ -269,6 +380,7 @@ const slugify = (str) => { .replace(/_+/g, '_') // remove consecutive underscores .replace(/[\/]/g, "__") .replace(/[^a-z0-9 -]/g, '-') // remove non-alphanumeric characters + .replace(/-+/g, '-') // remove consecutive dashes } const outputJSON = (p, data) => { @@ -283,7 +395,7 @@ const outputJSON = (p, data) => { fs.writeFileSync(fullPath, json); } -const outputFrontmatter = (p, data) => { +const outputFrontmatter = (p, dataOrUpdate) => { const fullPath = `${hugoOutput}/${p}`; // TODO: implement update frontmatter @@ -303,7 +415,12 @@ const outputFrontmatter = (p, data) => { content.content = existing.content; content.data = existing.data; } - content.data = { ...content.data, ...data }; + + if (typeof dataOrUpdate === "function") { + content.data = dataOrUpdate(content.data); + } else { + content.data = { ...content.data, ...dataOrUpdate }; + } const md = matter.stringify(content.content, content.data); fs.writeFileSync(fullPath, md); @@ -322,4 +439,4 @@ main() .catch((e) => { console.error(e); process.exit(1); - }) \ No newline at end of file + }) diff --git a/munge_sql.js b/munge_sql.js index c45773f44..89f385812 100644 --- a/munge_sql.js +++ b/munge_sql.js @@ -100,6 +100,28 @@ const main = async () => { ); `) + // Create the SPECS + await run(` + CREATE TABLE IF NOT EXISTS TestSpecs ( + test_run_implementation_id TEXT, + test_run_version TEXT, + test_full_name TEXT, + + spec_url TEXT, + + PRIMARY KEY (test_run_implementation_id, test_run_version, test_full_name, spec_url), + + -- test run + FOREIGN KEY (test_run_implementation_id, test_run_version) + REFERENCES TestRun (implementation_id, version), + + -- test result + FOREIGN KEY (test_run_implementation_id, test_run_version, test_full_name) + REFERENCES TestResult (test_run_implementation_id, test_run_version, full_name) + ); + `); + + for (const file of files) { const fileName = file.split("/").slice(-1)[0].split(".")[0]; const implemId = fileName; @@ -146,6 +168,13 @@ const main = async () => { VALUES (?, ?, ?, ?) `, [implemId, version, fullName, test.output]); + const specsArray = test.meta?.specs || []; + for (const specUrl of specsArray) { + await run(` + INSERT INTO TestSpecs (test_run_implementation_id, test_run_version, test_full_name, spec_url) + VALUES (?, ?, ?, ?) + `, [implemId, version, fullName, specUrl]); + } } } diff --git a/www/content/_index.md b/www/content/_index.md index 631f9a21f..2180b4b53 100644 --- a/www/content/_index.md +++ b/www/content/_index.md @@ -30,7 +30,10 @@ menu: ## List of Specs Tested -{{< specs-links >}} +}}" + class="no-underline bg-blue-200 hover:bg-blue-600 text-blue-800 hover:text-blue-200 text-xl px-8 py-4 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-200 focus:ring-offset-2"> + Specs + ## Related Projects: diff --git a/www/content/specs/_index.md b/www/content/specs/_index.md deleted file mode 100644 index 5820da4cb..000000000 --- a/www/content/specs/_index.md +++ /dev/null @@ -1,4 +0,0 @@ ---- ---- - -This is the entry-point for the conformance gateway dashboard when coming from the specs. \ No newline at end of file diff --git a/www/themes/conformance/layouts/shortcodes/specs-links.html b/www/themes/conformance/layouts/shortcodes/specs-links.html index a0990367e..dc6f4169e 100644 --- a/www/themes/conformance/layouts/shortcodes/specs-links.html +++ b/www/themes/conformance/layouts/shortcodes/specs-links.html @@ -1 +1,12 @@ -TBD + diff --git a/www/themes/conformance/layouts/specs/list.html b/www/themes/conformance/layouts/specs/list.html new file mode 100644 index 000000000..464c56954 --- /dev/null +++ b/www/themes/conformance/layouts/specs/list.html @@ -0,0 +1,52 @@ +{{define "main"}} + +
+

{{.Title}}

+ + {{.TableOfContents}} + + {{.Content}} + + {{ with .Params.hashes }} +

Hashes

+ + {{ end }} + + {{ if (gt (len .Data.Pages) 0) }} +

Children

+ + {{ end }} +
+ + + + + +{{with .PrevInSection}}Prev {{.Title}}{{end}} +{{with .NextInSection}}Next {{.Title}}{{end}} + + +{{$related := .Site.RegularPages.Related . | first 5}} {{with $related}} +

See Also

+ +{{end}} {{end}} From 80aeda39fc69534892045da48af3232902026054 Mon Sep 17 00:00:00 2001 From: Laurent Senta Date: Wed, 13 Sep 2023 15:56:44 +0200 Subject: [PATCH 2/7] feat: complete specs generation --- munge_aggregates.js | 55 +++++++++-- munge_sql.js | 5 +- www/themes/conformance/assets/style.css | 99 +++++++++++++++++++ .../layouts/partials/result-table.html | 14 ++- .../conformance/layouts/specs/list.html | 40 +++++--- 5 files changed, 192 insertions(+), 21 deletions(-) diff --git a/munge_aggregates.js b/munge_aggregates.js index d008ba3dc..26cbc52f4 100644 --- a/munge_aggregates.js +++ b/munge_aggregates.js @@ -103,6 +103,8 @@ const main = async () => { `; const testsRows = await all(testsQuery); const groups = {}; + const flatTestGroups = {}; // used for specs generation. + for (const row of testsRows) { const { versions, full_name, name, parent_test_full_name } = row; const slug = slugify(full_name); @@ -111,7 +113,10 @@ const main = async () => { groups[parent_test_full_name] = {}; } - groups[parent_test_full_name][full_name] = { versions: versions?.split(',') || [], name, full_name, slug }; + const g = { versions: versions?.split(',') || [], name, full_name, slug }; + + groups[parent_test_full_name][full_name] = g; + flatTestGroups[full_name] = g; } outputJSON("data/testgroups.json", groups); @@ -126,10 +131,11 @@ const main = async () => { `; const specsRows = await all(specsQuery); const specs = {}; + const flatSpecs = {}; for (const row of specsRows) { const { versions, full_name } = row; - let current = `https://${full_name}`; + let current = full_name; while (current !== "null") { const slug = slugify(current); @@ -140,9 +146,11 @@ const main = async () => { specs[parent] = {}; } + flatSpecs[current] = true + specs[parent][current] = { versions: versions?.split(',') || [], - full_name: current, + spec_full_name: current, slug, name, isHashed, @@ -156,14 +164,20 @@ const main = async () => { const descendTheSpecsTree = (current, path) => { Object.entries(specs[current] || {}) .forEach(([key, spec]) => { - // To reproduce the structure of URLs and hashes, - // we update existing pages + const addSpecs = (current) => { + let hashes = [...(current.specs || []), spec.name]; + hashes = [...new Set(hashes)]; // deduplicate + return { ...current, hashes } + }; + + // To reproduce the structure of URLs and hashes, we update existing specs pages if (spec.isHashed) { const p = path.join("/"); outputFrontmatter( `content/specs/${p}/_index.md`, - (current) => ({ ...current, hashes: [...(current.hashes || []), spec.name] })); - // assume there are no children for hashes + addSpecs + ); + // We assume there are no recursion / children for hashes return } @@ -181,6 +195,33 @@ const main = async () => { descendTheSpecsTree("null", []) + // Aggregate test results per specs + const specsTestGroups = {}; + + for (const fullName of Object.keys(flatSpecs)) { + // list all the test names for a given spec. + // we prefix search the database for spec_urls starting with the spec name + const specsQuery = ` + SELECT + test_full_name + FROM TestSpecs + WHERE spec_url LIKE ? + ORDER BY test_full_name + `; + const tests = await all(specsQuery, [fullName + '%']); + + const s = tests.map(x => x.test_full_name) + .reduce((acc, name) => { + return { + ...acc, + [name]: flatTestGroups[name] + } + }, {}); + specsTestGroups[fullName] = s; + } + + outputJSON("data/specsgroups.json", specsTestGroups); + // Query to fetch all stdouts const logsQuery = ` SELECT diff --git a/munge_sql.js b/munge_sql.js index 89f385812..601cdefe7 100644 --- a/munge_sql.js +++ b/munge_sql.js @@ -170,10 +170,13 @@ const main = async () => { const specsArray = test.meta?.specs || []; for (const specUrl of specsArray) { + // add `https://` if the specs don't have it + const cleanSpecUrl = specUrl.startsWith("http") ? specUrl : `https://${specUrl}`; + await run(` INSERT INTO TestSpecs (test_run_implementation_id, test_run_version, test_full_name, spec_url) VALUES (?, ?, ?, ?) - `, [implemId, version, fullName, specUrl]); + `, [implemId, version, fullName, cleanSpecUrl]); } } } diff --git a/www/themes/conformance/assets/style.css b/www/themes/conformance/assets/style.css index c399cc1ac..f261640fe 100644 --- a/www/themes/conformance/assets/style.css +++ b/www/themes/conformance/assets/style.css @@ -573,6 +573,14 @@ video { margin-bottom: auto; } +.mb-3 { + margin-bottom: 0.75rem; +} + +.mb-4 { + margin-bottom: 1rem; +} + .ml-4 { margin-left: 1rem; } @@ -589,6 +597,14 @@ video { margin-top: 4rem; } +.mt-2 { + margin-top: 0.5rem; +} + +.mt-8 { + margin-top: 2rem; +} + .block { display: block; } @@ -609,6 +625,10 @@ video { display: table; } +.grid { + display: grid; +} + .hidden { display: none; } @@ -669,6 +689,10 @@ video { table-layout: fixed; } +.grid-cols-1 { + grid-template-columns: repeat(1, minmax(0, 1fr)); +} + .flex-col { flex-direction: column; } @@ -685,6 +709,10 @@ video { justify-content: space-between; } +.gap-4 { + gap: 1rem; +} + .gap-x-2 { -moz-column-gap: 0.5rem; column-gap: 0.5rem; @@ -802,6 +830,10 @@ video { padding: 0.375rem; } +.p-4 { + padding: 1rem; +} + .p-6 { padding: 1.5rem; } @@ -884,6 +916,16 @@ video { text-align: right; } +.text-2xl { + font-size: 1.5rem; + line-height: 2rem; +} + +.text-3xl { + font-size: 1.875rem; + line-height: 2.25rem; +} + .text-sm { font-size: 0.875rem; line-height: 1.25rem; @@ -899,6 +941,10 @@ video { line-height: 1rem; } +.font-bold { + font-weight: 700; +} + .font-medium { font-weight: 500; } @@ -920,6 +966,11 @@ video { color: rgb(245 158 11 / var(--tw-text-opacity)); } +.text-blue-500 { + --tw-text-opacity: 1; + color: rgb(59 130 246 / var(--tw-text-opacity)); +} + .text-blue-800 { --tw-text-opacity: 1; color: rgb(30 64 175 / var(--tw-text-opacity)); @@ -969,12 +1020,32 @@ video { text-decoration-line: none; } +.shadow-md { + --tw-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); + --tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} + .shadow-sm { --tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05); --tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color); box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); } +.shadow-xl { + --tw-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1); + --tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} + +.transition { + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + article { line-height: 1.625; --tw-text-opacity: 1; @@ -1169,6 +1240,11 @@ article th { background-color: rgb(37 99 235 / var(--tw-bg-opacity)); } +.hover\:bg-gray-100:hover { + --tw-bg-opacity: 1; + background-color: rgb(243 244 246 / var(--tw-bg-opacity)); +} + .hover\:bg-slate-200:hover { --tw-bg-opacity: 1; background-color: rgb(226 232 240 / var(--tw-bg-opacity)); @@ -1179,6 +1255,11 @@ article th { color: rgb(191 219 254 / var(--tw-text-opacity)); } +.hover\:text-blue-700:hover { + --tw-text-opacity: 1; + color: rgb(29 78 216 / var(--tw-text-opacity)); +} + .hover\:text-gray-500:hover { --tw-text-opacity: 1; color: rgb(107 114 128 / var(--tw-text-opacity)); @@ -1224,11 +1305,29 @@ article th { } } +@media (min-width: 768px) { + .md\:grid-cols-1 { + grid-template-columns: repeat(1, minmax(0, 1fr)); + } + + .md\:grid-cols-2 { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } +} + @media (min-width: 1024px) { .lg\:mt-24 { margin-top: 6rem; } + .lg\:grid-cols-1 { + grid-template-columns: repeat(1, minmax(0, 1fr)); + } + + .lg\:grid-cols-4 { + grid-template-columns: repeat(4, minmax(0, 1fr)); + } + .lg\:px-8 { padding-left: 2rem; padding-right: 2rem; diff --git a/www/themes/conformance/layouts/partials/result-table.html b/www/themes/conformance/layouts/partials/result-table.html index 46378a927..7a6efb0f5 100644 --- a/www/themes/conformance/layouts/partials/result-table.html +++ b/www/themes/conformance/layouts/partials/result-table.html @@ -19,6 +19,18 @@ {{ $requestedTestGroup := (default "null" .full_name) }} {{ $requestedVersion := (default "" .version) }} {{ $requestedImplem := (default "" .implementation_id) }} +{{ $requestedSpecs := (default "" .spec_full_name) }} + +{{ $testGroups := (index site.Data.testgroups $requestedTestGroup) }} + +{{/* When you have a request specs, list all the test groups it defines */}} +{{ if (isset . "spec_full_name") }} + {{ if (isset . "full_name") }} + {{ errorf "Cannot specify both 'full_name' and 'spec_full_name' in the same shortcode" }} + {{ end }} + + {{ $testGroups = (index site.Data.specsgroups $requestedSpecs) }} +{{ end }} @@ -95,7 +107,7 @@ {{ end }} {{ end }} - {{ range $name, $content := (index site.Data.testgroups $requestedTestGroup) }} + {{ range $name, $content := $testGroups }}
{{.Title}} {{.Content}} + {{ $params := .Params }} + + {{ with .Params.hashes }} -

Hashes

-
    +
    + {{ range . }} -
  • - {{ . }} -
  • +
    +

    + #{{ . }} +

    + {{ $newSpec := (printf "%s/#%s" $params.spec_full_name .) }} + {{ partial "result-table.html" (merge $params (dict "spec_full_name" $newSpec))}} +
    {{ end }} -
+ {{ end }} + {{ if (gt (len .Data.Pages) 0) }} -

Children

- + {{ end }} + + +

Main Dashboard

+
+ {{ partial "result-table.html" .Params }} +
+ From 1f18eebf58c2e785b8d6faab59bb973858f8a20b Mon Sep 17 00:00:00 2001 From: Laurent Senta Date: Wed, 13 Sep 2023 16:22:50 +0200 Subject: [PATCH 3/7] feat: finalize ui and homepage --- www/content/_index.md | 29 +++--- www/themes/conformance/assets/style.css | 5 + .../layouts/partials/breadcrumbs.html | 91 ++++++++----------- .../conformance/layouts/specs/list.html | 6 +- 4 files changed, 60 insertions(+), 71 deletions(-) diff --git a/www/content/_index.md b/www/content/_index.md index 2180b4b53..9f3d9c2a5 100644 --- a/www/content/_index.md +++ b/www/content/_index.md @@ -11,31 +11,26 @@ menu: }}" class="w-32 h-32" />

- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed tincidunt sagittis arcu, in tempus nisi molestie at. Suspendisse imperdiet viverra fringilla. Sed eleifend elementum sem. Phasellus orci lectus, laoreet in sapien vulputate, bibendum cursus neque. Quisque luctus dictum ligula, sit amet sagittis lacus consectetur eget. Phasellus non diam sem. Duis pellentesque tellus quis dolor sodales, vitae faucibus nulla ornare. Proin eget odio eu orci tristique volutpat. Nunc non vehicula neque. Maecenas volutpat mollis sem eget vestibulum. -

+ +IPFS Gateway Conformance - a vendor-agnostic gateway conformance test suite for users and implementers of IPFS Gateways. We ensure compliance with [specs.ipfs.tech](https://specs.ipfs.tech/http-gateways/). Find us on [Github](https://github.com/ipfs/gateway-conformance). + +

-
+ -## List of Gateway Implementation Tested - -{{< gateways-links >}} - -## List of Specs Tested - -}}" - class="no-underline bg-blue-200 hover:bg-blue-600 text-blue-800 hover:text-blue-200 text-xl px-8 py-4 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-200 focus:ring-offset-2"> - Specs - - -## Related Projects: +## Related - [Conformance Test Suite](https://github.com/ipfs/gateway-conformance) - [IPFS Specs](https://specs.ipfs.tech) diff --git a/www/themes/conformance/assets/style.css b/www/themes/conformance/assets/style.css index f261640fe..27f7e4cfd 100644 --- a/www/themes/conformance/assets/style.css +++ b/www/themes/conformance/assets/style.css @@ -926,6 +926,11 @@ video { line-height: 2.25rem; } +.text-5xl { + font-size: 3rem; + line-height: 1; +} + .text-sm { font-size: 0.875rem; line-height: 1.25rem; diff --git a/www/themes/conformance/layouts/partials/breadcrumbs.html b/www/themes/conformance/layouts/partials/breadcrumbs.html index 04ff8e9a5..bf6652897 100644 --- a/www/themes/conformance/layouts/partials/breadcrumbs.html +++ b/www/themes/conformance/layouts/partials/breadcrumbs.html @@ -1,60 +1,49 @@ -
-
+ +{{ end }} + +
+
diff --git a/www/themes/conformance/layouts/specs/list.html b/www/themes/conformance/layouts/specs/list.html index 1422ec7dd..eb716b502 100644 --- a/www/themes/conformance/layouts/specs/list.html +++ b/www/themes/conformance/layouts/specs/list.html @@ -1,7 +1,7 @@ {{define "main"}}
-

{{.Title}}

+

{{.Title}}

{{.TableOfContents}} @@ -27,7 +27,7 @@

{{ if (gt (len .Data.Pages) 0) }} -

Sub-Specs

+

Sub-Specs

{{ range .Data.Pages }} @@ -39,7 +39,7 @@

Sub-Specs

{{ end }} -

Main Dashboard

+

Main Dashboard

{{ partial "result-table.html" .Params }}
From ef2499d459119e8a5b34d5c2648715a07afa2bb7 Mon Sep 17 00:00:00 2001 From: Laurent Senta Date: Wed, 13 Sep 2023 16:24:25 +0200 Subject: [PATCH 4/7] fix: use complete url in specs --- tests/path_gateway_dag_test.go | 6 +++--- tests/path_gateway_tar_test.go | 2 +- tests/path_gateway_unixfs_test.go | 12 ++++++------ tests/redirects_file_test.go | 8 ++++---- tests/trustless_gateway_car_test.go | 2 +- tests/trustless_gateway_raw_test.go | 2 +- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/tests/path_gateway_dag_test.go b/tests/path_gateway_dag_test.go index 9c4d5e42a..2c4c9828e 100644 --- a/tests/path_gateway_dag_test.go +++ b/tests/path_gateway_dag_test.go @@ -42,7 +42,7 @@ func TestGatewayJsonCbor(t *testing.T) { }, { Name: "GET UnixFS file with JSON bytes is returned with application/json Content-Type - with headers", - Spec: "specs.ipfs.tech/http-gateways/path-gateway/#accept-request-header", + Spec: "https://specs.ipfs.tech/http-gateways/path-gateway/#accept-request-header", Hint: ` ## Quick regression check for JSON stored on UnixFS: ## it has nothing to do with DAG-JSON and JSON codecs, @@ -479,7 +479,7 @@ func TestNativeDag(t *testing.T) { Response: Expect(). Headers( Header("Content-Type").Hint("expected Content-Type").Equals("application/vnd.ipld.dag-{{format}}", row.Format), - Header("Content-Length").Spec("specs.ipfs.tech/http-gateways/path-gateway/#content-disposition-response-header").Hint("includes Content-Length").Equals("{{length}}", len(dagTraversal.RawData())), + Header("Content-Length").Spec("https://specs.ipfs.tech/http-gateways/path-gateway/#content-disposition-response-header").Hint("includes Content-Length").Equals("{{length}}", len(dagTraversal.RawData())), Header("Content-Disposition").Hint("includes Content-Disposition").Contains(`{{disposition}}; filename="{{cid}}.{{format}}"`, row.Disposition, dagTraversalCID, row.Format), Header("X-Content-Type-Options").Hint("includes nosniff hint").Contains("nosniff"), ), @@ -553,7 +553,7 @@ func TestNativeDag(t *testing.T) { }, { Name: Fmt("HEAD {{name}} with only-if-cached for missing block returns HTTP 412 Precondition Failed", row.Name), - Spec: "specs.ipfs.tech/http-gateways/path-gateway/#only-if-cached", + Spec: "https://specs.ipfs.tech/http-gateways/path-gateway/#only-if-cached", Request: Request(). Path("/ipfs/{{cid}}", missingCID). Header("Cache-Control", "only-if-cached"). diff --git a/tests/path_gateway_tar_test.go b/tests/path_gateway_tar_test.go index d6131d0c7..15f5c3805 100644 --- a/tests/path_gateway_tar_test.go +++ b/tests/path_gateway_tar_test.go @@ -76,7 +76,7 @@ func TestTar(t *testing.T) { }, { Name: "GET TAR with explicit ?filename= succeeds with modified Content-Disposition header", - Spec: "specs.ipfs.tech/http-gateways/path-gateway/#content-disposition-response-header", + Spec: "https://specs.ipfs.tech/http-gateways/path-gateway/#content-disposition-response-header", Request: Request(). Path("/ipfs/{{cid}}", dirCID). Query("filename", "testтест.tar"). diff --git a/tests/path_gateway_unixfs_test.go b/tests/path_gateway_unixfs_test.go index c0e6fc500..ae3705d82 100644 --- a/tests/path_gateway_unixfs_test.go +++ b/tests/path_gateway_unixfs_test.go @@ -202,7 +202,7 @@ func TestGatewayCache(t *testing.T) { // ========== { Name: "GET for /ipfs/ file with matching Etag in If-None-Match returns 304 Not Modified", - Spec: "specs.ipfs.tech/http-gateways/path-gateway/#if-none-match-request-header", + Spec: "https://specs.ipfs.tech/http-gateways/path-gateway/#if-none-match-request-header", Request: Request(). Path("/ipfs/{{cid}}/root2/root3/root4/index.html", fixture.MustGetCid()). Headers( @@ -213,7 +213,7 @@ func TestGatewayCache(t *testing.T) { }, { Name: "GET for /ipfs/ dir with index.html file with matching Etag in If-None-Match returns 304 Not Modified", - Spec: "specs.ipfs.tech/http-gateways/path-gateway/#if-none-match-request-header", + Spec: "https://specs.ipfs.tech/http-gateways/path-gateway/#if-none-match-request-header", Request: Request(). Path("/ipfs/{{cid}}/root2/root3/root4/", fixture.MustGetCid()). Headers( @@ -224,7 +224,7 @@ func TestGatewayCache(t *testing.T) { }, { Name: "GET for /ipfs/ file with matching third Etag in If-None-Match returns 304 Not Modified", - Spec: "specs.ipfs.tech/http-gateways/path-gateway/#if-none-match-request-header", + Spec: "https://specs.ipfs.tech/http-gateways/path-gateway/#if-none-match-request-header", Request: Request(). Path("/ipfs/{{cid}}/root2/root3/root4/index.html", fixture.MustGetCid()). Headers( @@ -235,7 +235,7 @@ func TestGatewayCache(t *testing.T) { }, { Name: "GET for /ipfs/ file with matching weak Etag in If-None-Match returns 304 Not Modified", - Spec: "specs.ipfs.tech/http-gateways/path-gateway/#if-none-match-request-header", + Spec: "https://specs.ipfs.tech/http-gateways/path-gateway/#if-none-match-request-header", Request: Request(). Path("/ipfs/{{cid}}/root2/root3/root4/index.html", fixture.MustGetCid()). Headers( @@ -246,7 +246,7 @@ func TestGatewayCache(t *testing.T) { }, { Name: "GET for /ipfs/ file with wildcard Etag in If-None-Match returns 304 Not Modified", - Spec: "specs.ipfs.tech/http-gateways/path-gateway/#if-none-match-request-header", + Spec: "https://specs.ipfs.tech/http-gateways/path-gateway/#if-none-match-request-header", Request: Request(). Path("/ipfs/{{cid}}/root2/root3/root4/index.html", fixture.MustGetCid()). Headers( @@ -257,7 +257,7 @@ func TestGatewayCache(t *testing.T) { }, { Name: "GET for /ipfs/ dir listing with matching weak Etag in If-None-Match returns 304 Not Modified", - Spec: "specs.ipfs.tech/http-gateways/path-gateway/#if-none-match-request-header", + Spec: "https://specs.ipfs.tech/http-gateways/path-gateway/#if-none-match-request-header", Request: Request(). Path("/ipfs/{{cid}}/root2/root3/", fixture.MustGetCid()). Headers( diff --git a/tests/redirects_file_test.go b/tests/redirects_file_test.go index 9322c74ff..64e46d246 100644 --- a/tests/redirects_file_test.go +++ b/tests/redirects_file_test.go @@ -15,7 +15,7 @@ import ( ) func TestRedirectsFileSupport(t *testing.T) { - tooling.LogSpecs(t, "specs.ipfs.tech/http-gateways/web-redirects-file/") + tooling.LogSpecs(t, "https://specs.ipfs.tech/http-gateways/web-redirects-file/") fixture := car.MustOpenUnixfsCar("redirects_file/redirects.car") redirectDir := fixture.MustGetNode("examples") redirectDirCID := redirectDir.Base32Cid() @@ -166,8 +166,8 @@ func TestRedirectsFileSupport(t *testing.T) { Contains("could not parse _redirects:"), Contains(`forced redirects (or "shadowing") are not supported`), ), - ).Spec("specs.ipfs.tech/http-gateways/web-redirects-file/#no-forced-redirects"), - Spec: "specs.ipfs.tech/http-gateways/web-redirects-file/#error-handling", + ).Spec("https://specs.ipfs.tech/http-gateways/web-redirects-file/#no-forced-redirects"), + Spec: "https://specs.ipfs.tech/http-gateways/web-redirects-file/#error-handling", }, { Name: "invalid file: request for $TOO_LARGE_REDIRECTS_DIR_HOSTNAME/not-found returns error about too large redirects file", @@ -182,7 +182,7 @@ func TestRedirectsFileSupport(t *testing.T) { Contains("redirects file size cannot exceed"), ), ), - Spec: "specs.ipfs.tech/http-gateways/web-redirects-file/#max-file-size", + Spec: "https://specs.ipfs.tech/http-gateways/web-redirects-file/#max-file-size", }, }...) diff --git a/tests/trustless_gateway_car_test.go b/tests/trustless_gateway_car_test.go index 5a5114c63..5f0aa7e3a 100644 --- a/tests/trustless_gateway_car_test.go +++ b/tests/trustless_gateway_car_test.go @@ -408,7 +408,7 @@ func TestTrustlessCarDagScopeAll(t *testing.T) { func TestTrustlessCarEntityBytes(t *testing.T) { tooling.LogTestGroup(t, GroupBlockCar) - tooling.LogSpecs(t, "specs.ipfs.tech/http-gateways/trustless-gateway/#entity-bytes-request-query-parameter") + tooling.LogSpecs(t, "https://specs.ipfs.tech/http-gateways/trustless-gateway/#entity-bytes-request-query-parameter") singleLayerHamtMultiBlockFilesFixture := car.MustOpenUnixfsCar("trustless_gateway_car/single-layer-hamt-with-multi-block-files.car") subdirWithMixedBlockFiles := car.MustOpenUnixfsCar("trustless_gateway_car/subdir-with-mixed-block-files.car") diff --git a/tests/trustless_gateway_raw_test.go b/tests/trustless_gateway_raw_test.go index 8bef78ea4..2ba80f869 100644 --- a/tests/trustless_gateway_raw_test.go +++ b/tests/trustless_gateway_raw_test.go @@ -14,7 +14,7 @@ import ( func TestTrustlessRaw(t *testing.T) { tooling.LogTestGroup(t, GroupBlockCar) - tooling.LogSpecs(t, "specs.ipfs.tech/http-gateways/trustless-gateway/#block-responses-application-vnd-ipld-raw") + tooling.LogSpecs(t, "https://specs.ipfs.tech/http-gateways/trustless-gateway/#block-responses-application-vnd-ipld-raw") fixture := car.MustOpenUnixfsCar("gateway-raw-block.car") From e1745f0ab63f48839280c4328baa50a112725c4c Mon Sep 17 00:00:00 2001 From: Laurent Senta Date: Wed, 13 Sep 2023 16:50:13 +0200 Subject: [PATCH 5/7] feat: add specs links --- www/themes/conformance/assets/style.css | 23 +++++++++++++++++++ .../conformance/layouts/specs/list.html | 20 ++++++++++++++-- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/www/themes/conformance/assets/style.css b/www/themes/conformance/assets/style.css index 27f7e4cfd..4fd839cdb 100644 --- a/www/themes/conformance/assets/style.css +++ b/www/themes/conformance/assets/style.css @@ -764,6 +764,10 @@ video { border-radius: 0.25rem; } +.rounded-full { + border-radius: 9999px; +} + .rounded-lg { border-radius: 0.5rem; } @@ -976,6 +980,11 @@ video { color: rgb(59 130 246 / var(--tw-text-opacity)); } +.text-blue-700 { + --tw-text-opacity: 1; + color: rgb(29 78 216 / var(--tw-text-opacity)); +} + .text-blue-800 { --tw-text-opacity: 1; color: rgb(30 64 175 / var(--tw-text-opacity)); @@ -1043,6 +1052,20 @@ video { box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); } +.ring-1 { + --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); + --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color); + box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); +} + +.ring-inset { + --tw-ring-inset: inset; +} + +.ring-blue-700\/10 { + --tw-ring-color: rgb(29 78 216 / 0.1); +} + .transition { transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter; transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter; diff --git a/www/themes/conformance/layouts/specs/list.html b/www/themes/conformance/layouts/specs/list.html index eb716b502..2e5cc2af3 100644 --- a/www/themes/conformance/layouts/specs/list.html +++ b/www/themes/conformance/layouts/specs/list.html @@ -1,3 +1,13 @@ +{{ define "specpill" }} + + specs + +{{ end }} + + {{define "main"}}
@@ -14,11 +24,14 @@

{{.Title}}

{{ range . }} + {{ $newSpec := (printf "%s/#%s" $params.spec_full_name .) }} +

#{{ . }} + {{ template "specpill" $newSpec }}

- {{ $newSpec := (printf "%s/#%s" $params.spec_full_name .) }} + {{ partial "result-table.html" (merge $params (dict "spec_full_name" $newSpec))}}
{{ end }} @@ -39,7 +52,10 @@

Sub-Specs

{{ end }} -

Main Dashboard

+

+ Main Dashboard + {{ template "specpill" .Params.spec_full_name }} +

{{ partial "result-table.html" .Params }}
From d4a2ffd428aa506e4a7ba36643bf5d64b61fd62f Mon Sep 17 00:00:00 2001 From: Laurent Senta Date: Wed, 13 Sep 2023 16:56:16 +0200 Subject: [PATCH 6/7] fix: link root specs --- www/themes/conformance/layouts/specs/list.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/themes/conformance/layouts/specs/list.html b/www/themes/conformance/layouts/specs/list.html index 2e5cc2af3..1fd86b036 100644 --- a/www/themes/conformance/layouts/specs/list.html +++ b/www/themes/conformance/layouts/specs/list.html @@ -54,7 +54,7 @@

Sub-Specs

Main Dashboard - {{ template "specpill" .Params.spec_full_name }} + {{ template "specpill" (default "https://specs.ipfs.tech/" .Params.spec_full_name) }}

{{ partial "result-table.html" .Params }} From 42ad1c6ac851dcd3a19ec48682e93b2151e5b6f6 Mon Sep 17 00:00:00 2001 From: Laurent Senta Date: Fri, 15 Sep 2023 10:17:32 +0200 Subject: [PATCH 7/7] feat: rework specs names and links --- www/content/specs/_index.md | 3 +++ www/themes/conformance/layouts/specs/list.html | 6 ++++-- 2 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 www/content/specs/_index.md diff --git a/www/content/specs/_index.md b/www/content/specs/_index.md new file mode 100644 index 000000000..0ac06476f --- /dev/null +++ b/www/content/specs/_index.md @@ -0,0 +1,3 @@ +--- +title: Specification Dashboard +--- diff --git a/www/themes/conformance/layouts/specs/list.html b/www/themes/conformance/layouts/specs/list.html index 1fd86b036..8fb9a618b 100644 --- a/www/themes/conformance/layouts/specs/list.html +++ b/www/themes/conformance/layouts/specs/list.html @@ -11,7 +11,10 @@ {{define "main"}}
-

{{.Title}}

+

+ {{.Title}} + {{ template "specpill" (default "https://specs.ipfs.tech/" .Params.spec_full_name) }} +

{{.TableOfContents}} @@ -54,7 +57,6 @@

Sub-Specs

Main Dashboard - {{ template "specpill" (default "https://specs.ipfs.tech/" .Params.spec_full_name) }}

{{ partial "result-table.html" .Params }}