Archilyzer · Source

archilyzer

Archilyzer
git clone https://archilyzer.pages.dev/source/archilyzer.git
Log | Files | Refs | README | LICENSE

commit b8dc5b801afba2eeb3ace3c53c436e08fe025a49
parent ac51e43166bbda046af9f034d386f9a8fa19fcf7
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date:   Sun, 27 Sep 2026 01:02:11 -0400

hub, homepage(e2e): review nits — the no-accent hub colour is the chart colour; the colour spec requires the chart

ArchiveShelf's comment no longer says seriesColor() at its index; useHubSites'
paragraph is rewrapped. instance-colours.spec derives "a chart is drawn" from
the fixture summary's monthly series and asserts the chart and all n legend
swatches whenever it is, instead of skipping the legend checks when the page
has none.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

Diffstat:
Mexport/app/components/hub/ArchiveShelf.tsx | 13+++++++------
Mexport/app/components/hub/useHubSites.ts | 15++++++++-------
Mhomepage/e2e/instance-colours.spec.ts | 38+++++++++++++++++++++-----------------
3 files changed, 36 insertions(+), 30 deletions(-)

diff --git a/export/app/components/hub/ArchiveShelf.tsx b/export/app/components/hub/ArchiveShelf.tsx @@ -18,12 +18,13 @@ // order its ArchiveCards and growth chart draw in), and each wears the colour // its homepage card wears (lib/siteColor.ts): its archive's OWN accent when the // site sets one (the tool has no colour, the archives do) — a named accent at -// its value on the base in force — and seriesColor() at its index in the -// summary when it sets none. Order and colour are useHubSites' -// (officialInstances), shared with the scope chips, the results' stripes and -// /ask, so an archive is one colour on every surface. With no summary the order -// is hub-sites.json's and the colour the card's place. An added archive with -// no accent wears the family's signal colour. +// its value on the base in force — and its homepage chart colour when it sets +// none (siteChartColors: the palette slot at its index in the summary, or the +// lowest free one when an accent's family holds that). Order and colour are +// useHubSites' (officialInstances), shared with the scope chips, the results' +// stripes and /ask, so an archive is one colour on every surface. With no +// summary the order is hub-sites.json's and the colour the card's place. An +// added archive with no accent wears the family's signal colour. import { X } from "lucide-react"; import { Badge } from "yt-dlp-transcript-common/components/ui/badge"; diff --git a/export/app/components/hub/useHubSites.ts b/export/app/components/hub/useHubSites.ts @@ -5,13 +5,14 @@ // and /ask: ONE order and ONE colour per archive, decided here. // // The official instances come in the homepage's order, each in the colour its -// homepage card wears — its own accent (a named one per base), else the chart -// palette's at its place (officialInstances, common/lib/hubSummary.ts). That order is /hub-summary.json's, so they are -// listed only once that file has settled — found, missing or unreadable — -// rather than in hub-sites.json's order first and reordered a moment later. -// Both files are small, same-origin and requested together, so the wait is the -// gap between two requests already in flight. The archives a visitor added -// follow, in the order they were added, each in its own accent or none. +// homepage card wears — its own accent (a named one per base), else its chart +// colour (officialInstances, common/lib/hubSummary.ts). That order is +// /hub-summary.json's, so they are listed only once that file has settled — +// found, missing or unreadable — rather than in hub-sites.json's order first +// and reordered a moment later. Both files are small, same-origin and +// requested together, so the wait is the gap between two requests already in +// flight. The archives a visitor added follow, in the order they were added, +// each in its own accent or none. import { useMemo } from "react"; import { diff --git a/homepage/e2e/instance-colours.spec.ts b/homepage/e2e/instance-colours.spec.ts @@ -18,11 +18,14 @@ import { FIXTURE_ACCENTS, FIXTURE_SUMMARY_NAME } from "./fixture-accents"; const BASE_KEY = "ytdlp-tb:base"; -function fixtureSites(): Array<{ accentId?: string }> | null { +// The fixture copy the dev server reads: its sites, and whether it has the +// monthly series the growth chart (and its legend) is drawn from. +function fixture(): { sites: Array<{ accentId?: string }>; chart: boolean } | null { try { const file = path.resolve(test.info().project.testDir, FIXTURE_SUMMARY_NAME); const s = JSON.parse(fs.readFileSync(file, "utf8")); - return Array.isArray(s?.sites) && s.sites.length ? s.sites : null; + if (!Array.isArray(s?.sites) || s.sites.length === 0) return null; + return { sites: s.sites, chart: Array.isArray(s.monthly) && s.monthly.length > 0 }; } catch { return null; } @@ -76,12 +79,13 @@ async function useBase(page: Page, base: "dark" | "light" | "sepia") { test("each instance card wears its site's accent on every base, in its chart layer's hue", async ({ page, }) => { - const sites = fixtureSites(); - test.skip(!sites, "no summary on disk — the page has no instance cards"); - const n = sites!.length; + const f = fixture(); + test.skip(!f, "no summary on disk — the page has no instance cards"); + const { sites, chart: hasChart } = f!; + const n = sites.length; expect(FIXTURE_ACCENTS[0].accentId).toBe("brass"); // The chart colours the page must wear, as the helper assigns them. - const chart = siteChartColors(sites!); + const chart = siteChartColors(sites); expect(chart[0]).toBe(`var(--chart-${ACCENT_CHART_SLOT.brass! + 1})`); expect(new Set(chart).size).toBe(n); await page.goto("/"); @@ -96,23 +100,23 @@ test("each instance card wears its site's accent on every base, in its chart lay const { stripes, legend } = await colours(page); expect(stripes).toHaveLength(n); - // The legend (and so each layer) wears each site's chart colour. - const hasChart = legend.length > 0; - if (hasChart) { - expect(legend).toHaveLength(n); - for (let i = 0; i < n; i++) { - expect(legend[i], `legend ${i}`).toBe(await resolve(page, chart[i])); - } + // The summary's monthly series draws the chart, legend and all: the + // legend (and so each layer) wears each site's chart colour. A summary + // with none draws no chart at all. + await expect( + page.getByRole("img", { name: /transcripts by the month/i }), + ).toHaveCount(hasChart ? 1 : 0); + expect(legend, "legend swatches").toHaveLength(hasChart ? n : 0); + for (let i = 0; i < legend.length; i++) { + expect(legend[i], `legend ${i}`).toBe(await resolve(page, chart[i])); } // Site 0: the NAMED accent at this base's value — not the published // on-dark hex on every base — and its legend swatch is the amber slot, // the same hue family (a few degrees apart), at a different value. expect(stripes[0]).toBe(await resolve(page, onBase[base])); - if (hasChart) { - expect(legend[0]).toBe(await resolve(page, "var(--chart-4)")); - expect(hueGap(stripes[0], legend[0]), "brass vs its layer").toBeLessThan(25); - } + expect(await resolve(page, chart[0])).toBe(await resolve(page, "var(--chart-4)")); + expect(hueGap(stripes[0], await resolve(page, chart[0])), "brass vs its layer").toBeLessThan(25); // Site 1 (when there is one): the custom hex as published. if (n > 1) expect(stripes[1]).toBe(await resolve(page, FIXTURE_ACCENTS[1].accent)); // Every other site has no accent: its chart colour, the same as its