commit 96cc52eec74759ff0935e5a0ee92a4cf744e48de
parent b230836b0653a8cbc9d122d8cd2ce0240f7a32f7
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date: Mon, 5 Oct 2026 17:26:10 -0400
reports: the subject card's author, publisher and date each stay whole on a narrow screen
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Diffstat:
4 files changed, 17 insertions(+), 6 deletions(-)
diff --git a/common/lib/report/export.test.ts b/common/lib/report/export.test.ts
@@ -106,7 +106,7 @@ test("the heading: the series (else the title), the dates and revision, the docu
const html = reportExportHtml(view, opts);
assert.match(
html,
- /<header class="report-head"><h1>Demo Checks<\/h1>\n<p class="dates" data-report-dates="">2026-10-01 · updated 2026-10-04<\/p>\n<p class="subject" data-subject-source="s0" style="border-left-color:#aa3300"><a href="https:\/\/example\.org\/a">An article<\/a> <span class="meta">— A\. Writer · Example Gazette<\/span><\/p>\n<p class="subtitle">Two claims, tested<\/p><\/header>/,
+ /<header class="report-head"><h1>Demo Checks<\/h1>\n<p class="dates" data-report-dates="">2026-10-01 · updated 2026-10-04<\/p>\n<p class="subject" data-subject-source="s0" style="border-left-color:#aa3300"><a href="https:\/\/example\.org\/a">An article<\/a> <span class="meta">— <span style="white-space:nowrap">A\. Writer<\/span> · <span style="white-space:nowrap">Example Gazette<\/span><\/span><\/p>\n<p class="subtitle">Two claims, tested<\/p><\/header>/,
);
assert.match(html, /<title>Demo Checks: A demo fact-check<\/title>/, "the title stays the document's name");
assert.doesNotMatch(html, /data-report-attribution|data-report-byline|Under review|Fact-check by|class="eyebrow"/);
diff --git a/common/lib/report/exportHtml.ts b/common/lib/report/exportHtml.ts
@@ -605,7 +605,7 @@ export function reportExportHtml(view: ReportPageView, opts: ReportExportHtmlOpt
const dateLine = [...reportDateParts(view).map(escapeHtml), ...(revision ? [revision] : [])];
if (dateLine.length > 0) head.push(`<p class="dates" data-report-dates="">${dateLine.join(" · ")}</p>`);
if (subject) {
- const meta = subjectMetaParts(subject).map(escapeHtml).join(" · ");
+ const meta = subjectMetaParts(subject).map((x) => `<span style="white-space:nowrap">${escapeHtml(x)}</span>`).join(" · ");
head.push(
`<p class="subject" data-subject-source="${escapeHtml(subject.id)}"${railStyle(subject.accent)}>${sourceTitleHtml(subject)}` +
`${meta ? ` <span class="meta">— ${meta}</span>` : ""}</p>`,
diff --git a/export/app/components/reports/parts.tsx b/export/app/components/reports/parts.tsx
@@ -1,3 +1,4 @@
+import { Fragment } from "react";
import Link from "next/link";
import { ExternalLink } from "lucide-react";
import { sourceAnchor, subjectMetaParts, type SourceView } from "yt-dlp-transcript-common/lib/report/views";
@@ -85,7 +86,8 @@ export function SourceBlock({ source, label }: { source: SourceView; label: stri
// whose it is. It is the document's one place on the page, so it carries the
// anchor a citation's "from <title>" links to.
export function SubjectCard({ source }: { source: SourceView }) {
- const meta = subjectMetaParts(source).join(" · ");
+ // Each part stays whole on a narrow screen (a date never splits at its dashes).
+ const meta = subjectMetaParts(source);
const n = source.archives.length;
return (
<div
@@ -108,7 +110,16 @@ export function SubjectCard({ source }: { source: SourceView }) {
source.title
)}
</p>
- {meta && <p className="text-xs text-muted-foreground">{meta}</p>}
+ {meta.length > 0 && (
+ <p className="text-xs text-muted-foreground">
+ {meta.map((part, i) => (
+ <Fragment key={i}>
+ {i > 0 && " · "}
+ <span className="whitespace-nowrap">{part}</span>
+ </Fragment>
+ ))}
+ </p>
+ )}
{n > 0 && (
<details data-source-archives={n} className="text-xs">
<summary className="cursor-pointer text-muted-foreground hover:text-foreground">
diff --git a/export/app/lib/reports.test.ts b/export/app/lib/reports.test.ts
@@ -98,7 +98,7 @@ test("the report page: header, tally, sections and claims, inline cites, referen
const card = header.slice(header.indexOf('<div id="source-s0"'));
assert.match(card, /^<div id="source-s0" data-subject-source="s0" class="[^"]*border-l-4[^"]*" style="border-left-color:#8a6fb0">/);
assert.match(card, /<a href="https:\/\/example.org\/articles\/demo" target="_blank" rel="noopener noreferrer"[^>]*>An example article about a demo channel<\/a>/);
- assert.match(card, /<p[^>]*>A. Writer · Example Gazette · 2026-09-20<\/p>/);
+ assert.match(card, /<p[^>]*><span class="whitespace-nowrap">A. Writer<\/span> · <span class="whitespace-nowrap">Example Gazette<\/span> · <span class="whitespace-nowrap">2026-09-20<\/span><\/p>/);
assert.match(card, /<details data-source-archives="1"[^>]*><summary[^>]*>1 archive link<\/summary>/);
assert.ok(card.includes("as published on the day"));
assert.ok(!html.includes("Read in the edition published on the day"), "the subject's note is not in the card");
@@ -196,7 +196,7 @@ test("the report header: a series heads it in place of the title; an edited repo
assert.match(header, /<p data-report-dates=""[^>]*>2026-10-01 · <a [^>]*data-report-revision="2"[^>]*>edited since revision 2<\/a><\/p>/);
// without an accent the card's rail is the border colour; only the parts it has
assert.match(header, /<div id="source-s0" data-subject-source="s0" class="[^"]*border-l-4[^"]*border-border"(?! style)/);
- assert.match(header, /<p[^>]*>Example Gazette<\/p>/);
+ assert.match(header, /<p[^>]*><span class="whitespace-nowrap">Example Gazette<\/span><\/p>/);
});
test("a video moment: the clip, quote, verification, cue lines, original link, cited in", async () => {