[Story] Reading list page #11

Merged
kpcto merged 1 commits from feature/10 into main 2026-08-25 17:14:33 +00:00
Member

Summary

Delivers the reading list page for issue #10 — a static page that renders curated links grouped by category from a single data file. No backend, no automated import/scraping, no search/filter UI (per scope).

The feature implementation landed on main via PR #9 (issue #8) and is carried here as the #10 deliverable on feature/10, re-verified against the acceptance criteria. This branch additionally hardens the external links.

What changed on this branch

  • js/reading-list.js — every rendered reading link (all external http(s) URLs) now carries rel="noopener noreferrer" as a hardening best practice.
  • tests/reading-list.test.js — anchor matcher updated for the new attribute; new assertion: every rendered link carries rel="noopener noreferrer".

Feature surface (already on main, re-verified here)

  • reading.html — page with a #reading-list container; loads the renderer module; noscript fallback; nav marks it aria-current="page".
  • data/reading-list.js — the single data file. Schema: title, url, category, optional one-line note. Adding a link means editing this file only.
  • js/reading-list.js — pure renderer: groups entries by category (first-seen order), HTML-escapes all text, skips invalid entries, de-duplicates category ids; guarded browser wiring renders the data file into the page.
  • Navigation — Home and Contact pages link to reading.html.
  • css/style.css — category/list styles; two-column grid on wide screens and overflow-wrap on links so 500+ entries stay scannable.
  • tests/reading-list.test.js — component, data-integrity, renderer, and 500-entry fixture tests.
  • README.md — documents the page, the data schema, and the edit-only workflow.

Criterion → test mapping

Criterion Test
Reading list page renders links grouped by category from a data file tests/reading-list.test.js → "renders links grouped by category from the data file"; "renders correctly against a 500+ entry fixture" (per-section grouping and counts); "renderer module loads the reading list data file"; "reading page renders a reading list container and loads the renderer module"
Each entry shows a title, a link URL, and an optional one-line note tests/reading-list.test.js → "each rendered link has a valid href and shows its title, with the note shown only when present" (plus rel hardening assertion); "every entry in the data file has a title, a category, and a valid http(s) url"; "seed data includes an entry without a note so the optional path is exercised"
Page stays responsive and usable with 500+ entries in the data file tests/reading-list.test.js → "renders correctly against a 500+ entry fixture" (500 entries all rendered, grouping intact, render time bound < 5s); responsive two-column layout in css/style.css
A new link can be added by editing only the data file, with no code changes tests/reading-list.test.js → "a new link can be added by editing only the data file"; README "Reading list" section documents the schema and the edit-only workflow

Out of scope (as specified in the issue)

  • No backend, login, or server-side storage.
  • No automated import or scraping of bookmarks in this pass.
  • No full-text search or filtering UI yet.

Verification

  • npm test on the head commit (fb62194): 30/30 green (node v22.23.2, Node built-in test runner).
  • CI: .gitea/workflows/ci.yml runs npm test on pull requests and pushes to main. This Gitea instance has no Actions runner (same situation as PRs #6 and #9), so runs stay "Waiting to run" (pending) — there are no failing checks, and the suite is verified green locally.

Rollback

  • Revert the branch commits to remove — no migration, per the issue's rollback note.
## Summary Delivers the reading list page for issue #10 — a static page that renders curated links grouped by category from a single data file. No backend, no automated import/scraping, no search/filter UI (per scope). The feature implementation landed on `main` via PR #9 (issue #8) and is carried here as the #10 deliverable on `feature/10`, re-verified against the acceptance criteria. This branch additionally hardens the external links. ### What changed on this branch - `js/reading-list.js` — every rendered reading link (all external http(s) URLs) now carries `rel="noopener noreferrer"` as a hardening best practice. - `tests/reading-list.test.js` — anchor matcher updated for the new attribute; new assertion: every rendered link carries `rel="noopener noreferrer"`. ### Feature surface (already on `main`, re-verified here) - `reading.html` — page with a `#reading-list` container; loads the renderer module; `noscript` fallback; nav marks it `aria-current="page"`. - `data/reading-list.js` — the single data file. Schema: `title`, `url`, `category`, optional one-line `note`. Adding a link means editing this file only. - `js/reading-list.js` — pure renderer: groups entries by category (first-seen order), HTML-escapes all text, skips invalid entries, de-duplicates category ids; guarded browser wiring renders the data file into the page. - Navigation — Home and Contact pages link to `reading.html`. - `css/style.css` — category/list styles; two-column grid on wide screens and `overflow-wrap` on links so 500+ entries stay scannable. - `tests/reading-list.test.js` — component, data-integrity, renderer, and 500-entry fixture tests. - `README.md` — documents the page, the data schema, and the edit-only workflow. ### Criterion → test mapping | Criterion | Test | | --- | --- | | Reading list page renders links grouped by category from a data file | `tests/reading-list.test.js` → "renders links grouped by category from the data file"; "renders correctly against a 500+ entry fixture" (per-section grouping and counts); "renderer module loads the reading list data file"; "reading page renders a reading list container and loads the renderer module" | | Each entry shows a title, a link URL, and an optional one-line note | `tests/reading-list.test.js` → "each rendered link has a valid href and shows its title, with the note shown only when present" (plus rel hardening assertion); "every entry in the data file has a title, a category, and a valid http(s) url"; "seed data includes an entry without a note so the optional path is exercised" | | Page stays responsive and usable with 500+ entries in the data file | `tests/reading-list.test.js` → "renders correctly against a 500+ entry fixture" (500 entries all rendered, grouping intact, render time bound < 5s); responsive two-column layout in `css/style.css` | | A new link can be added by editing only the data file, with no code changes | `tests/reading-list.test.js` → "a new link can be added by editing only the data file"; README "Reading list" section documents the schema and the edit-only workflow | ### Out of scope (as specified in the issue) - No backend, login, or server-side storage. - No automated import or scraping of bookmarks in this pass. - No full-text search or filtering UI yet. ### Verification - `npm test` on the head commit (`fb62194`): **30/30 green** (node v22.23.2, Node built-in test runner). - CI: `.gitea/workflows/ci.yml` runs `npm test` on pull requests and pushes to `main`. This Gitea instance has no Actions runner (same situation as PRs #6 and #9), so runs stay "Waiting to run" (pending) — there are no failing checks, and the suite is verified green locally. ### Rollback - Revert the branch commits to remove — no migration, per the issue's rollback note.
bot-implementer added 1 commit 2026-08-25 15:15:47 +00:00
feat: harden external reading links with rel="noopener noreferrer"
CI / Run tests (pull_request) Has been cancelled
fb62194d40
All reading list links point at external http(s) URLs, so each rendered
anchor now carries rel="noopener noreferrer" as a hardening best
practice. Renderer test updated for the new attribute and asserts every
rendered link carries it.
kpcto closed this pull request 2026-08-25 16:07:08 +00:00
kpcto reopened this pull request 2026-08-25 16:07:42 +00:00
kpcto closed this pull request 2026-08-25 16:17:13 +00:00
kpcto reopened this pull request 2026-08-25 16:18:00 +00:00
kpcto merged commit f40b66d5cc into main 2026-08-25 17:14:33 +00:00
kpcto deleted branch feature/10 2026-08-25 17:14:33 +00:00
Sign in to join this conversation.