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
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
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>
This commit is contained in:
1 parent
271ffe92d4
commit
d1688ac150
39 files changed
+183
-111
No files matched your search
@@ -39,7 +39,7 @@ export function AddToCompareButton({ school }: { school: NearbySchool }) {
|
||||
aria-pressed={selected}
|
||||
>
|
||||
{selected ? '✓ Added to compare' : '+ Add to compare'}
|
||||
<span className={styles.srOnly}> — {school.school_name}</span>
|
||||
<span className={styles.srOnly}>: {school.school_name}</span>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
@@ -175,7 +175,7 @@ export function AdmissionsSection({
|
||||
<><strong>{admissions.first_preference_applications}</strong> families put it first for </>
|
||||
)}
|
||||
{admissions.places_offered != null && <><strong>{admissions.places_offered}</strong> places</>}
|
||||
{admissions.total_applications != null && ` — ${admissions.total_applications.toLocaleString()} applications in total`}.
|
||||
{admissions.total_applications != null && ` (${admissions.total_applications.toLocaleString()} applications in total)`}.
|
||||
</p>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -189,7 +189,7 @@ export function DestinationsView({
|
||||
data-group={card ?? 'none'}
|
||||
className={`${styles.segment} ${styles[seg.category]} ${dimmed(card) ? styles.dim : ''}`}
|
||||
style={{ width: `${seg.widthPct}%` }}
|
||||
title={`${CATEGORY_LABELS[seg.category]} — ${seg.labelPct}% (${seg.pupils} pupils)`}
|
||||
title={`${CATEGORY_LABELS[seg.category]}: ${seg.labelPct}% (${seg.pupils} pupils)`}
|
||||
>
|
||||
{seg.widthPct >= 9 ? `${seg.labelPct}%` : ''}
|
||||
</div>
|
||||
@@ -254,7 +254,7 @@ export function DestinationsView({
|
||||
<p className={styles.footnote}>
|
||||
Shares are rounded and may not add up to 100%. A pupil counted under a
|
||||
school sixth form may have moved to a different school's sixth
|
||||
form — the published data records the type of place, not which one.
|
||||
form. The published data records the type of place, not which one.
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -129,7 +129,7 @@ export function GcseSection({
|
||||
that comparison isn't meaningful. */}
|
||||
{!suppressComparison && latestResults.attainment_8_score != null && (
|
||||
<div className={styles.att8Viz}>
|
||||
<div className={styles.att8VizLabel}>Attainment 8 — school vs national</div>
|
||||
<div className={styles.att8VizLabel}>Attainment 8: school vs national</div>
|
||||
<div className={styles.att8VizTrack}>
|
||||
<div
|
||||
className={styles.att8VizFill}
|
||||
@@ -155,7 +155,7 @@ export function GcseSection({
|
||||
{/* Progress 8 number line with CI */}
|
||||
{latestResults.progress_8_score != null && !p8Suspended && (
|
||||
<div className={styles.p8Viz}>
|
||||
<div className={styles.p8VizLabel}>Progress 8 — relative to national baseline (0)</div>
|
||||
<div className={styles.p8VizLabel}>Progress 8: relative to national baseline (0)</div>
|
||||
{(() => {
|
||||
const p8 = latestResults.progress_8_score!;
|
||||
const lo = latestResults.progress_8_lower_ci ?? p8;
|
||||
|
||||
@@ -37,7 +37,7 @@ export function HistorySection({
|
||||
<>
|
||||
{hasKS2Results && (
|
||||
<>
|
||||
<h3 className={styles.subSectionTitle}>Primary — KS2 SATs</h3>
|
||||
<h3 className={styles.subSectionTitle}>Primary: KS2 SATs</h3>
|
||||
<div className={styles.chartContainer}>
|
||||
<PerformanceChart
|
||||
data={yearlyData}
|
||||
@@ -51,7 +51,7 @@ export function HistorySection({
|
||||
)}
|
||||
{hasKS4Results && (
|
||||
<>
|
||||
<h3 className={styles.subSectionTitle} style={{ marginTop: '1.5rem' }}>Secondary — GCSEs</h3>
|
||||
<h3 className={styles.subSectionTitle} style={{ marginTop: '1.5rem' }}>Secondary: GCSEs</h3>
|
||||
<div className={styles.chartContainer}>
|
||||
<PerformanceChart
|
||||
data={yearlyData}
|
||||
|
||||
@@ -114,14 +114,14 @@ export function OfstedSection({
|
||||
</div>
|
||||
<p className={styles.ofstedDisclaimer}>
|
||||
{ofsted.grade_source === 'ungraded_carried_forward'
|
||||
? 'This overall grade is carried forward from an earlier inspection — Ofsted has since visited without issuing a new overall grade. From September 2024, Ofsted no longer makes an overall effectiveness judgement.'
|
||||
? 'This overall grade is carried forward from an earlier inspection. Ofsted has since visited without issuing a new overall grade. From September 2024, Ofsted no longer makes an overall effectiveness judgement.'
|
||||
: isSecondary
|
||||
? 'From September 2024, Ofsted no longer makes an overall effectiveness judgement in inspections.'
|
||||
: 'From September 2024, Ofsted no longer makes an overall effectiveness judgement in inspections of state-funded schools.'}
|
||||
</p>
|
||||
{oeifAllSameGrade ? (
|
||||
<p className={styles.ofstedAllSame}>
|
||||
Rated <strong>{OFSTED_LABELS[ofsted.overall_effectiveness!]}</strong> across all inspected areas — Quality of Teaching, Behaviour, Pupils' Development and Leadership.
|
||||
Rated <strong>{OFSTED_LABELS[ofsted.overall_effectiveness!]}</strong> across all inspected areas: Quality of Teaching, Behaviour, Pupils' Development and Leadership.
|
||||
</p>
|
||||
) : (
|
||||
<div className={`${styles.metricsGrid} ${styles.gradeGrid}`}>
|
||||
|
||||
@@ -41,7 +41,7 @@ export function ResultsSection({
|
||||
? 'GCSE results for Year 11 pupils.'
|
||||
: 'End-of-primary-school tests taken by Year 6 pupils.')
|
||||
: isAllThrough
|
||||
? 'KS2 SATs (end of Year 6) and GCSE results (Year 11) — this school covers both. England averages shown for comparison.'
|
||||
? 'This school covers both KS2 SATs (end of Year 6) and GCSE results (Year 11). England averages shown for comparison.'
|
||||
: isSecondary
|
||||
? 'GCSE results for Year 11 pupils. England averages shown for comparison.'
|
||||
: 'End-of-primary-school tests taken by Year 6 pupils. England averages shown for comparison.'}
|
||||
@@ -56,7 +56,7 @@ export function ResultsSection({
|
||||
{hasKS2Results && (
|
||||
<>
|
||||
{isAllThrough && (
|
||||
<h3 className={styles.subSectionTitle}>Primary — KS2 SATs (Year 6)</h3>
|
||||
<h3 className={styles.subSectionTitle}>Primary: KS2 SATs (Year 6)</h3>
|
||||
)}
|
||||
<div className={styles.heroStatGrid}>
|
||||
{latestResults.rwm_expected_pct !== null && (
|
||||
@@ -208,7 +208,7 @@ export function ResultsSection({
|
||||
{hasKS4Results && (
|
||||
<>
|
||||
{isAllThrough && (
|
||||
<h3 className={styles.subSectionTitle} style={{ marginTop: '1.5rem' }}>Secondary — GCSEs (Year 11)</h3>
|
||||
<h3 className={styles.subSectionTitle} style={{ marginTop: '1.5rem' }}>Secondary: GCSEs (Year 11)</h3>
|
||||
)}
|
||||
<div className={styles.metricsGrid}>
|
||||
{latestResults.attainment_8_score !== null && (
|
||||
|
||||
@@ -229,8 +229,8 @@ export function SchoolDetailShell({
|
||||
</div>
|
||||
{isProposedToClose(schoolInfo) && (
|
||||
<div className={styles.closingStrip} role="note">
|
||||
<strong>⚠ Proposed to close</strong> — this school is proposed for closure,
|
||||
check with the local authority before applying.
|
||||
<strong>⚠ Proposed to close.</strong> Check with the local authority before
|
||||
applying.
|
||||
</div>
|
||||
)}
|
||||
{schoolInfo.address && (
|
||||
|
||||
@@ -46,10 +46,10 @@ export function SecondaryAdmissionsSection({
|
||||
|
||||
{admissionsTag && (
|
||||
<div className={`${styles.admissionsTypeBadge} ${admissionsTag === 'Selective' ? styles.admissionsSelective : styles.admissionsFaith}`}>
|
||||
<strong>{admissionsTag}</strong>{' '}
|
||||
<strong>{admissionsTag}:</strong>{' '}
|
||||
{admissionsTag === 'Selective'
|
||||
? '— Entry to this school is by selective examination (e.g. 11+).'
|
||||
: `— This school has a faith-based admissions priority (${schoolInfo.religious_denomination}).`}
|
||||
? 'entry to this school is by selective examination (e.g. 11+).'
|
||||
: `this school has a faith-based admissions priority (${schoolInfo.religious_denomination}).`}
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ export interface CutoffDisplay {
|
||||
/** What the cut-off measures, and what it does not. Identical on both templates. */
|
||||
export const CUTOFF_NOTE =
|
||||
'The furthest home offered a place, after higher priorities such as siblings, ' +
|
||||
'faith and EHCP were applied. It is not a fixed catchment — it moves every year ' +
|
||||
'faith and EHCP were applied. It is not a fixed catchment. It moves every year ' +
|
||||
'with the number of applications.';
|
||||
|
||||
/** Straight-line, because that is how councils measure it. */
|
||||
@@ -54,7 +54,7 @@ export function describeCutoff(
|
||||
entryYear: formatEntryYear(distance.year),
|
||||
routeNote:
|
||||
routes > 1
|
||||
? `Furthest of ${routes} admission routes at this school — the one that ` +
|
||||
? `Furthest of ${routes} admission routes at this school. The one that ` +
|
||||
'applies to your child may have had a shorter cut-off.'
|
||||
: null,
|
||||
};
|
||||
@@ -122,10 +122,10 @@ export function compareToCutoff(
|
||||
const cutoffPhrase = `the September ${year} cut-off of ${cutoffLabel}`;
|
||||
const headline =
|
||||
verdict === 'inside'
|
||||
? `${label} away — inside ${cutoffPhrase}.`
|
||||
? `${label} away, inside ${cutoffPhrase}.`
|
||||
: verdict === 'outside'
|
||||
? `${label} away — beyond ${cutoffPhrase}.`
|
||||
: `${label} away — too close to ${cutoffPhrase} to call.`;
|
||||
? `${label} away, beyond ${cutoffPhrase}.`
|
||||
: `${label} away, too close to ${cutoffPhrase} to call.`;
|
||||
|
||||
const detail =
|
||||
verdict === 'too-close'
|
||||
@@ -156,11 +156,11 @@ export function compareToCutoff(
|
||||
*/
|
||||
export const CUTOFF_CHECK_CAVEAT =
|
||||
'Distance is the last criterion applied. Places go first to children in care, '
|
||||
+ 'EHCP places, siblings and — at faith schools — on faith criteria, so a home '
|
||||
+ 'EHCP places and siblings, and at faith schools by faith criteria, so a home '
|
||||
+ 'inside the distance can still miss out. Figures are straight-line distances '
|
||||
+ 'and not a catchment boundary; some authorities measure a walking route '
|
||||
+ "instead, which is always longer for the same home. Next year's cut-off "
|
||||
+ "depends on next year's applicants — always check the school's own "
|
||||
+ "depends on next year's applicants, so always check the school's own "
|
||||
+ 'admissions policy.';
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
Reference in new issue
Block a user