Files
mangabaka-seeder/docs/plans/003-tapas.md
T

48 lines
3.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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`](../specs/003-tapas.md).
## Global constraints
- `src/core` pure (no DOM/Bun/node/GM). Tests offline, fixtures captured (done: `test/fixtures/tapas/*`,
`test/fixtures/wayback/tapas-villains-*`). No new dependencies.
## Review focus
1. Wayback rows for `<slug>-novel` must not count as the comic. → Task 1 same-series test, Task 3 history test.
2. Age-gated series must not fail the run. → Task 3 test.
3. CloudFront URLs from 2020 normalise to `us-a.tapas.io` without the size suffix. → Task 1 test.
4. Episode links resolve to the series. → Task 3 test.
5. 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)`.
- [x] Tests: every link form; non-series paths rejected (`/comics`, `/series/`); normalisation (cloudfront → us-a,
`_z`/`_m` dropped, query dropped, other hosts untouched); same-series by slug (case-insensitive, `/info`,
trailing slash), by id, `-novel` rejected. 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`.
- [x] 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 (`seriesId` 186414), age check (`from` URL).
RED → implement → GREEN → commit.
### Task 3: Source (`tapas/index.ts`) and registry
- [x] 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 a `SourceSeries` flag read by the
pipeline → add `ageGated` flag and pipeline warning); Wayback history over the CDX fixture keeps only the
comic rows. Register in `SOURCES`; hosts. RED → implement → GREEN → commit.
### Task 4: Copy, userscript @connect, docs
- [x] Link hint, "No rehosting" warning, userscript description/@connect (+ gm test), README sources section,
ARCHITECTURE map, DECISIONS entry. Commit.
### Task 5: Verify
- [x] Real run in headless Chrome: comic and novel (no Wayback), and one with Wayback every 12 months; final
review; remove this plan; merge; push.