Commit Graph

4 Commits

Author SHA1 Message Date
prosolis
2ea5f7a6f7 Strip inline scripts from reader body extraction
Datawrapper embed resizers (and other inline scripts) were leaking into
reader mode as literal text. Two extraction paths were affected:

- parser.go extractContentText/extractLede stripped only script tags via
  htmlTagRe, leaving the JS body behind. This is the path that usually
  wins for feeds shipping full content:encoded (e.g. Politico).
- article.go goquery paths call .Text(), which concatenates script source.

Both now drop whole <script>/<style>/<noscript> elements before pulling
text. Paywall detection (JSON-LD) still runs before the goquery strip.
2026-07-07 21:33:35 -07:00
prosolis
55aa167151 Add feed/reader mode with full-article capture at ingest
Reader mode presents the stories on a page one at a time in a focused
overlay, marking each read as it's shown. Left/right arrows (or the header
book button / `f`) page through them; read stories dim on the grid. Read
state is device-local in localStorage.

Backing this required actually capturing article bodies, which Pete wasn't
doing — it kept only the RSS <description> lede and discarded content:encoded:

- stories.content column (idempotent migration; old rows fall back to lede)
- parser keeps content:encoded as paragraph-preserving text
- article fetch already done for paywall detection now also returns its body,
  so ingest stores the richer of feed-content vs scraped body with no extra
  request (prefers the archive snapshot body for paywalled stories)
- GET /api/article?id= serves the stored text; card queries now select id and
  expose it as data-id for the reader

Tests cover content extraction, the storage round-trip, and the article
endpoint + card rendering end to end.
2026-07-06 22:46:14 -07:00
prosolis
7d469cf8c5 Fix glued-together RSS ledes; parse per-item language
Two ingestion changes:

- extractLede replaced HTML tags with empty string, so adjacent
  block tags like </p><p> fused words across paragraphs. Replace
  tags with a space and collapse whitespace.
- Pull each item's <language> tag (or dc:language) into FeedItem
  so the poller can filter on it. Politico Europe publishes the
  same story in en / fr / de side-by-side and we want to keep
  only one language per source.
2026-05-26 23:03:00 -07:00
prosolis
652d6dfa38 Initial commit 2026-05-22 17:25:27 -07:00