From 4a20a12f665165701ffc17467aa454ea846d16d8 Mon Sep 17 00:00:00 2001 From: mARTin-B78 Date: Wed, 30 Sep 2026 10:26:27 +0200 Subject: [PATCH] feat(magazine): show sidebars in the reading view as labelled, never-narrated asides Co-Authored-By: Claude Sonnet 5.5 --- CHANGELOG.md | 1 + TODO.md | 6 ++-- architecture/magazine-ingestion.md | 9 ++++++ core/magazine.py | 33 ++++++++++++++++++++++ routes/magazine.py | 3 +- static/js/magazine.js | 21 ++++++++++++-- static/style.css | 6 ++++ tests/magazine.spec.js | 29 ++++++++++++++++++++ tests/test_magazine_routes.py | 44 ++++++++++++++++++++++++++++++ 9 files changed, 146 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c66ad23..279b3c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ Follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) · versioned wi ## [Unreleased] ### Added +- **Magazine reading view shows sidebars.** A sidebar was kept out of narration and therefore never shown at all. The article text endpoint now also returns `asides` and the reflowed view displays each one where it sits, labelled "Sidebar · not read aloud · p. N", as plain text that is neither a sentence nor highlighted. Only for pages the article alone occupies (on a shared page there is no telling which article a sidebar belongs to); not for advertisement pages; a sidebar you ticked into the narration stays narrated. - **Magazine review: extraction diff.** A region whose text you edited by hand is marked *Edited*, with *Show changes* (word-level comparison against the text as first recognised; removals struck through and marked "−", additions underlined and marked "+") and *Restore recognised text*. The first reading is kept in a new `ocr_text` field across repeated edits; re-reading the region or typing the original back clears it. - **"Continued from page N" now joins a feature's tail to its head.** Until now only the forward "continued on page N" reference linked pages. A tail that says "Fortsetzung von Seite 10" / "Continued from page 10" (found even when set as small furniture or sidebar text, on lines up to 160 characters) is attached to the single article on that page. Skipped when a contents entry anchors the tail, when the page is shared by several articles, or when the marker points forward or at an empty page. Articles gain a `continued_from` list. - **Magazine import from PNG/JPEG page images.** Choose or drop several scans or phone photos; they are checked by content (not by name), ordered by filename with natural numbering, turned into one scan-style PDF (page size from the image's own resolution, EXIF rotation applied, 72 dpi treated as unknown) and ingested like any scanned issue. Limits: 300 images, 25 MB and 60 megapixels each; a bad image rejects the whole upload and leaves nothing behind; an existing source is never replaced. Verified on real pages: OCR through the image path scored like the original PDF (F1 0.85 / 0.78). diff --git a/TODO.md b/TODO.md index 8adc75c..0a26a70 100644 --- a/TODO.md +++ b/TODO.md @@ -680,9 +680,9 @@ casting. The original PDF remains the visual source of truth while approved arti ### P1 — Magazine listening experience -- [~] Generate clean article HTML with headings, captions, figures, sidebars, and page links. - *(headings/byline/captions styled and page-linked, figures now shown during playback; sidebars are auto-excluded - from narration rather than rendered inline, per the P2 sidebar-exclusion item below)* +- [x] Generate clean article HTML with headings, captions, figures, sidebars, and page links. + *(headings/byline/captions styled and page-linked, figures shown during playback, and (2026-09-29) sidebars shown in + place as labelled, never-narrated asides)* - [x] Generate narrator audio per article with resume/progress and a play-all queue. - [x] Synchronize paragraph/sentence highlighting with playback and keep PDF and article views linked. *(sentence-level; clicking a sentence or switching to the original-page view jumps to its source bbox)* diff --git a/architecture/magazine-ingestion.md b/architecture/magazine-ingestion.md index 98da01c..bf71c29 100644 --- a/architecture/magazine-ingestion.md +++ b/architecture/magazine-ingestion.md @@ -283,6 +283,15 @@ it can drift on a sentence with heavy punctuation-driven pauses. A checkbox (measured, not estimated — it just waits for `audio.onended`) always still works regardless. +### Sidebars in the reading view + +`article_asides(layout, article, all_articles)` lists the sidebar regions on an article's own pages that are not part of +its narrated blocks; `GET .../articles/{id}/text` returns them as `asides` (`id, page, bbox, text, after`), where `after` +is the last narrated region before the sidebar in reading order (None = before the first on its page). A page that any +other article also lists is skipped, as are advertisement pages and empty boxes; jump cues are stripped. The client +inserts each as an `