3.0 KiB
Tapas source — implementation plan
For agentic workers: superpowers:executing-plans (native, the user's standing choice). Checkbox steps.
Goal: a tapas Source (comics and novels) registered next to webtoons.
Architecture: src/core/sources/tapas/{urls,parse,index}.ts mirroring webtoons/; one registry line; host
lists; source-neutral copy. Spec: docs/specs/003-tapas.md.
Global constraints
src/corepure (no DOM/Bun/node/GM). Tests offline, fixtures captured (done:test/fixtures/tapas/*,test/fixtures/wayback/tapas-villains-*). No new dependencies.
Review focus
- Wayback rows for
<slug>-novelmust not count as the comic. → Task 1 same-series test, Task 3 history test. - Age-gated series must not fail the run. → Task 3 test.
- CloudFront URLs from 2020 normalise to
us-a.tapas.iowithout the size suffix. → Task 1 test. - Episode links resolve to the series. → Task 3 test.
- Capitalised/underscored slugs (
RU_Screwed) parse. → Task 1 test.
Task 1: URLs (tapas/urls.ts)
Produces: TAPAS_HOSTS, IMAGE_HOST = "us-a.tapas.io", IMAGE_HOSTS, parseTapasUrl(url): TapasRef
({ kind: "series", key: string /* slug or id */ } | { kind: "episode", id: string }), isTapasUrl(url),
infoUrl(key), normalizeImageUrl(raw), isSameTapasSeries(linkUrl, slug, id), slugOf(canonicalUrl).
- Tests: every link form; non-series paths rejected (
/comics,/series/); normalisation (cloudfront → us-a,_z/_mdropped, query dropped, other hosts untouched); same-series by slug (case-insensitive,/info, trailing slash), by id,-novelrejected. RED → implement → GREEN → commit.
Task 2: Parsing (tapas/parse.ts)
Produces: parseInfoPage(html, pageUrl): { id, title, canonicalUrl, novel, covers }, extractCovers(html, pageUrl), episodeSeriesId(html), ageGateTarget(html): string | null.
- Tests on fixtures: comic (id 186414, title, not novel, poster 960×1440 URL, banner), novel (266599, novel),
2020 archive (cloudfront poster + banner normalised), reader page (
seriesId186414), age check (fromURL). RED → implement → GREEN → commit.
Task 3: Source (tapas/index.ts) and registry
- Tests through
FakeTransport: info link;/series/<id>(fake redirect = info page served for id URL); episode link (two fetches); age check (mature, no covers, warning via aSourceSeriesflag read by the pipeline → addageGatedflag and pipeline warning); Wayback history over the CDX fixture keeps only the comic rows. Register inSOURCES; hosts. RED → implement → GREEN → commit.
Task 4: Copy, userscript @connect, docs
- Link hint, "No rehosting" warning, userscript description/@connect (+ gm test), README sources section, ARCHITECTURE map, DECISIONS entry. Commit.
Task 5: Verify
- Real run in headless Chrome: comic and novel (no Wayback), and one with Wayback every 12 months; final review; remove this plan; merge; push.