From 583231af37a9837d90ebab006d71913cea664c23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20de=20Courville?= Date: Mon, 24 Aug 2026 22:26:41 +0200 Subject: [PATCH 01/31] Zine library initial implementation --- .../guide-print.pdf | Bin 0 -> 77 bytes .../guide-small.pdf | Bin 0 -> 77 bytes .../zine-integration-test-fixture/index.md | 5 + .../metadata.json | 18 +++ .github/scripts/zine-build.test.mjs | 60 ++++++++++ .github/scripts/zines.test.mjs | 76 ++++++++++++ AGENTS.md | 13 +- TEST.md | 15 ++- netlify.toml | 10 ++ .../src/components/ActivityGuideGrid.astro | 41 +++++++ .../ActivityGuideSubmitButton.astro | 10 ++ pcd-website/src/config.ts | 26 ++++ pcd-website/src/content.config.ts | 8 ++ .../activity-guides/contribute-a-guide.md | 26 +--- .../organizer-kit/activity-guides/library.md | 16 +++ .../what-are-activity-guides.md | 12 -- .../activity-guides/zine-library.md | 9 -- .../getting-started/minimum-viable-pcd.md | 2 +- pcd-website/src/content/zines/README.md | 19 +++ pcd-website/src/lib/zine-metadata.d.ts | 27 +++++ pcd-website/src/lib/zine-metadata.js | 98 +++++++++++++++ pcd-website/src/lib/zines.ts | 112 ++++++++++++++++++ .../src/pages/activity-guide/[id].astro | 77 ++++++++++++ .../src/pages/organize/[...slug].astro | 11 +- pcd-website/src/styles/docs/components.css | 99 ++++++++++++++++ scripts/run-tests.sh | 4 + 26 files changed, 746 insertions(+), 48 deletions(-) create mode 100644 .github/scripts/fixtures/zines/zine-integration-test-fixture/guide-print.pdf create mode 100644 .github/scripts/fixtures/zines/zine-integration-test-fixture/guide-small.pdf create mode 100644 .github/scripts/fixtures/zines/zine-integration-test-fixture/index.md create mode 100644 .github/scripts/fixtures/zines/zine-integration-test-fixture/metadata.json create mode 100644 .github/scripts/zine-build.test.mjs create mode 100644 .github/scripts/zines.test.mjs create mode 100644 pcd-website/src/components/ActivityGuideGrid.astro create mode 100644 pcd-website/src/components/ActivityGuideSubmitButton.astro create mode 100644 pcd-website/src/content/organizer-kit/activity-guides/library.md delete mode 100644 pcd-website/src/content/organizer-kit/activity-guides/what-are-activity-guides.md delete mode 100644 pcd-website/src/content/organizer-kit/activity-guides/zine-library.md create mode 100644 pcd-website/src/content/zines/README.md create mode 100644 pcd-website/src/lib/zine-metadata.d.ts create mode 100644 pcd-website/src/lib/zine-metadata.js create mode 100644 pcd-website/src/lib/zines.ts create mode 100644 pcd-website/src/pages/activity-guide/[id].astro diff --git a/.github/scripts/fixtures/zines/zine-integration-test-fixture/guide-print.pdf b/.github/scripts/fixtures/zines/zine-integration-test-fixture/guide-print.pdf new file mode 100644 index 0000000000000000000000000000000000000000..a2ccecc911d0a6eae548ba5102052b3d0ef38d04 GIT binary patch literal 77 zcmY!laB]+href="([^"]+)"[^>]*>${label}`)); + assert.ok(match, `expected a link labelled "${label}"`); + return match[1]; +} + +test('a populated zine collection emits linked assets and replaces its topic placeholder', () => { + assert.ok(!existsSync(DEST), `${DEST} already exists — refusing to overwrite`); + let created = true; + try { + cpSync(FIXTURE, DEST, { recursive: true }); + copyFileSync(join(WEBSITE, 'src/images/og-image.png'), join(DEST, 'cover.png')); + execFileSync('npm', ['run', 'build'], { cwd: WEBSITE, stdio: 'pipe' }); + + const pagePath = join(DIST, 'activity-guide', SLUG, 'index.html'); + assert.ok(existsSync(pagePath), 'the zine page should be generated'); + const page = readFileSync(pagePath, 'utf8'); + assert.match(page, /Loops with Shapes/); + assert.match(page, /View the original submission/); + + for (const label of ['Read on screen', 'Print and fold']) { + assert.ok(existsSync(emittedPath(hrefForLabel(page, label))), `${label} should resolve to an emitted PDF`); + } + const pageCover = page.match(/]+src="([^"]+)"/); + assert.ok(pageCover, 'the zine page should render a cover image'); + assert.ok(existsSync(emittedPath(pageCover[1])), 'the zine cover should be emitted'); + + const library = readFileSync(join(DIST, 'organize/activity-guides/library/index.html'), 'utf8'); + assert.match(library, new RegExp(`href="/activity-guide/${SLUG}/"`)); + assert.match(library, /A compact guide to making patterns with repeated shapes\./); + assert.doesNotMatch(library, /Loops<\/strong>\s*Guide wanted<\/span>/); + const grid = library.match(/