copy(web): replace em dashes in public copy #155

Merged
tudor merged 1 commits from copy/remove-em-dashes into main 2026-09-24 21:11:15 +00:00
Owner

Replaces every em dash in visitor-facing copy with the punctuation that fits what the dash was doing: a colon before a list or explanation, a comma for an add-on, a full stop between two ideas, or parentheses for a mid-sentence aside. No en dashes or spaced hyphens were swapped in.

Scope (about 90 strings in 34 files, found by walking the TypeScript AST so comments are excluded):

  • SEO: site and home meta descriptions, OG/Twitter text, the titles of the compare, place and local-authority pages, OG image alt, the generated school summary
  • Home, How it works, editorial blurb, search hint, admissions guide
  • School page: section headings, Ofsted notes, results and chart notes, closure banner, selective/faith badge, last-distance-offered copy, destinations footnote and tooltip
  • Compare page: section intros, measure labels and tips, admissions notes
  • Rankings subtitle, lib/metrics.ts labels, SUPPRESSED_TOOLTIP, the screen-reader suffix on Add to compare

Examples:

  • Reading — Expected Standard → Reading: Expected Standard
  • Schools in Surrey — Local Authority | schoolcompare → Schools in Surrey (Local Authority) | schoolcompare
  • 0.04 miles away — inside the September 2026 cut-off… → 0.04 miles away, inside the September 2026 cut-off…

Two rewrites also fix the sentence around them:

  • the closure banner no longer says "Proposed to close" and then "this school is proposed for closure"
  • the cut-off caveat now reads "Places go first to children in care, EHCP places and siblings, and at faith schools by faith criteria"; the old version didn't parse

Kept on purpose: the lone — that marks a missing value in table cells and stat slots (utils formatValue, PlaceView, search rows, compare cells, destinations "does not apply"). That's a table convention rather than prose, and existing tests assert it. Also kept: one thrown developer error message.

Not covered: blog posts and other Payload CMS content in the database.

Guard: new __tests__/components/noEmDashCopy.test.ts parses app/, components/ and lib/ and fails on any em dash in a string literal, template chunk or JSX text node. It allows the lone empty-value marker and new Error(...) messages.

Tests: four assertions that pinned the old wording were updated. Jest: 56 suites, 476 tests pass. tsc --noEmit is clean. E2E journeys already match on regexes like /Primary.*KS2 SATs/ that still hold, so no journey changes were needed.

🤖 Generated with Claude Code

Replaces every em dash in visitor-facing copy with the punctuation that fits what the dash was doing: a colon before a list or explanation, a comma for an add-on, a full stop between two ideas, or parentheses for a mid-sentence aside. No en dashes or spaced hyphens were swapped in. **Scope** (about 90 strings in 34 files, found by walking the TypeScript AST so comments are excluded): - SEO: site and home meta descriptions, OG/Twitter text, the titles of the compare, place and local-authority pages, OG image alt, the generated school summary - Home, How it works, editorial blurb, search hint, admissions guide - School page: section headings, Ofsted notes, results and chart notes, closure banner, selective/faith badge, last-distance-offered copy, destinations footnote and tooltip - Compare page: section intros, measure labels and tips, admissions notes - Rankings subtitle, `lib/metrics.ts` labels, `SUPPRESSED_TOOLTIP`, the screen-reader suffix on Add to compare Examples: - `Reading — Expected Standard` → `Reading: Expected Standard` - `Schools in Surrey — Local Authority | schoolcompare` → `Schools in Surrey (Local Authority) | schoolcompare` - `0.04 miles away — inside the September 2026 cut-off…` → `0.04 miles away, inside the September 2026 cut-off…` Two rewrites also fix the sentence around them: - the closure banner no longer says "Proposed to close" and then "this school is proposed for closure" - the cut-off caveat now reads "Places go first to children in care, EHCP places and siblings, and at faith schools by faith criteria"; the old version didn't parse **Kept on purpose:** the lone `—` that marks a missing value in table cells and stat slots (utils `formatValue`, PlaceView, search rows, compare cells, destinations "does not apply"). That's a table convention rather than prose, and existing tests assert it. Also kept: one thrown developer error message. **Not covered:** blog posts and other Payload CMS content in the database. **Guard:** new `__tests__/components/noEmDashCopy.test.ts` parses `app/`, `components/` and `lib/` and fails on any em dash in a string literal, template chunk or JSX text node. It allows the lone empty-value marker and `new Error(...)` messages. **Tests:** four assertions that pinned the old wording were updated. Jest: 56 suites, 476 tests pass. `tsc --noEmit` is clean. E2E journeys already match on regexes like `/Primary.*KS2 SATs/` that still hold, so no journey changes were needed. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
tudor added 1 commit 2026-09-24 21:04:42 +00:00
copy(web): replace em dashes in public copy
PR Checks / Frontend Typecheck + Tests (pull_request) Successful in 1m14s
PR Checks / Backend Smoke (pull_request) Successful in 10s
PR Checks / Build Backend (no push) (pull_request) Successful in 19s
PR Checks / Build Frontend (no push) (pull_request) Successful in 1m19s
PR Checks / Build Pipeline (no push) (pull_request) Successful in 11s
PR Checks / AI Code Review (Claude) (pull_request) Successful in 1m20s
d1688ac150
Rewrites every visitor-facing string that used an em dash, choosing the
punctuation for what the dash was doing: a colon before a list or
explanation, a comma for an aside, a full stop between two thoughts,
parentheses for an aside mid-sentence. Covers page titles and meta
descriptions, the home and admissions guide copy, school page headings
and notes, the compare page, metric labels and tooltips.

Two rewrites also fix the sentence around them: the closure banner no
longer repeats "proposed for closure", and the cut-off caveat's list of
priorities now parses.

A lone dash marking a missing value in a table cell stays: it is a data
convention, not prose. A Jest guard walks the source with the TypeScript
parser and fails on any other em dash in a string or JSX text node.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

🤖 AI Code Review (Claude Code)

This PR mechanically replaces em dashes with periods, commas, colons, or parentheses across all visitor-facing copy in the Next.js frontend, updates the corresponding unit/characterization tests to match the new punctuation, and adds a new AST-based test that fails the build if an em dash reappears in scanned public copy. All string/JSX changes and their paired test assertions line up correctly (verified via grep across app/components/lib that no non-comment, non-exempt em dash remains), and the new lint test correctly exempts comments, thrown Error messages, and the single-dash 'no value' placeholder convention.

✅ No issues found.

## 🤖 AI Code Review (Claude Code) This PR mechanically replaces em dashes with periods, commas, colons, or parentheses across all visitor-facing copy in the Next.js frontend, updates the corresponding unit/characterization tests to match the new punctuation, and adds a new AST-based test that fails the build if an em dash reappears in scanned public copy. All string/JSX changes and their paired test assertions line up correctly (verified via grep across app/components/lib that no non-comment, non-exempt em dash remains), and the new lint test correctly exempts comments, thrown Error messages, and the single-dash 'no value' placeholder convention. ✅ No issues found.
tudor merged commit 343b40c645 into main 2026-09-24 21:11:15 +00:00
Sign in to join this conversation.
No Reviewers
No labels
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: tudor/school_compare#155