Add cover refinements design spec
Spec for three cover generation improvements: omit obituaries from headlines, increase font size, and use pixel-width truncation. Made-with: Cursor
This commit is contained in:
@@ -0,0 +1,63 @@
|
|||||||
|
# Cover Refinements Design
|
||||||
|
|
||||||
|
**Date:** 2026-04-06
|
||||||
|
**Scope:** Three targeted changes to the weekly newspaper cover generation
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
The cover is a 480×800 JPEG with a masthead bar at the top and a translucent headline strip at the bottom. Headlines are currently rendered at font size 14 and truncated by character count (45 chars), which doesn't correspond to actual pixel width — causing text to be cut short before filling the available space. Obituary articles also appear in the headline list, which is undesirable.
|
||||||
|
|
||||||
|
## Changes
|
||||||
|
|
||||||
|
### 1. Omit Obituaries from Cover Headlines
|
||||||
|
|
||||||
|
**Problem:** Obituary articles appear as cover headlines alongside news stories.
|
||||||
|
|
||||||
|
**Solution:** Filter articles whose `categories` JSON array contains `"Obituaries"` when building the `headlines` list. This applies at the three call sites that construct headlines before calling `generate_cover`:
|
||||||
|
|
||||||
|
- `src/routes/publish.py` — manual publish
|
||||||
|
- `src/routes/issues.py` — regenerate issue cover
|
||||||
|
- `src/scheduler.py` — auto-publish
|
||||||
|
|
||||||
|
Each site already iterates articles to build `categories_list` for AI prompt selection. The obituary filter will be applied when building both `headlines` and `categories_list` (excluding "Obituaries" from the prompt category pool is harmless since it has no matching prompt entry).
|
||||||
|
|
||||||
|
**Identification:** Category string match on `"Obituaries"` (case-sensitive, matching the RSS feed tag).
|
||||||
|
|
||||||
|
### 2. Increase Headline Font Size
|
||||||
|
|
||||||
|
**Problem:** Font size 14 is too small to read comfortably on the cover.
|
||||||
|
|
||||||
|
**Solution:** In `_draw_text_overlays` in `src/cover.py`:
|
||||||
|
|
||||||
|
- Headline font: `_get_font(14)` → `_get_font(18)`
|
||||||
|
- Line spacing: `22px` → `26px`
|
||||||
|
- Strip height formula: `28 + max_headlines * 22` → `28 + max_headlines * 26`
|
||||||
|
|
||||||
|
### 3. Dynamic Pixel-Width Truncation
|
||||||
|
|
||||||
|
**Problem:** Character-count truncation (`len(text) > 45`) doesn't account for variable-width font glyphs. Headlines get truncated well before reaching the edge of the 480px canvas.
|
||||||
|
|
||||||
|
**Solution:** Replace character-count truncation with pixel-width measurement using Pillow's `textbbox`:
|
||||||
|
|
||||||
|
- Compute `max_width = width - 32` (16px left padding + 16px right margin)
|
||||||
|
- For each headline string (with bullet prefix), measure its rendered width via `draw.textbbox((0, 0), text, font=headline_font)`
|
||||||
|
- If it exceeds `max_width`, find the longest prefix that fits (iterating from the end) and append `"…"`
|
||||||
|
- The ellipsis itself must be included in the width measurement
|
||||||
|
|
||||||
|
This makes truncation adapt to actual font metrics and canvas dimensions automatically.
|
||||||
|
|
||||||
|
## Files Modified
|
||||||
|
|
||||||
|
| File | Change |
|
||||||
|
|------|--------|
|
||||||
|
| `src/cover.py` | Font size 14→18, line spacing 22→26, strip height formula, replace char truncation with pixel-width truncation |
|
||||||
|
| `src/routes/publish.py` | Filter obituaries from headlines list |
|
||||||
|
| `src/routes/issues.py` | Filter obituaries from headlines list |
|
||||||
|
| `src/scheduler.py` | Filter obituaries from headlines list |
|
||||||
|
| `tests/test_cover.py` | Update tests for new truncation behavior |
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
- Existing cover generation tests updated to reflect new font/spacing values
|
||||||
|
- Verify pixel-width truncation produces headlines that fill available width without overflow
|
||||||
|
- Verify obituary articles are excluded from cover headlines
|
||||||
Reference in New Issue
Block a user