// THE TIMELINE — a report's dated entries (report.json `entries`): small // cited blocks appended over time, read newest first, each its own anchor on // the page and its own item in the report's feeds (./feeds.ts). // // The one order every reader shares — the page, the slides, the citation // numbering (./uses.ts), the exports, the feeds, MCP: newest first by date; // entries of the same instant keep their order in the document. // // Pure, no imports: the browser and the validator read the one copy. const DAY_RE = /^\d{4}-\d{2}-\d{2}$/; // A report date (`YYYY-MM-DD`, midnight UTC, or an ISO 8601 date-time with a // zone) as epoch milliseconds; NaN for anything else. export function reportDateMs(v: string | undefined): number { if (!v) return Number.NaN; return Date.parse(DAY_RE.test(v) ? `${v}T00:00:00Z` : v); } // The source indexes of `entries`, newest first. A date that does not parse // sorts last (a published report has none: the validator refuses it). export function entryOrder(entries: readonly { date: string }[]): number[] { const at = entries.map((e) => { const ms = reportDateMs(e.date); return Number.isNaN(ms) ? Number.NEGATIVE_INFINITY : ms; }); return entries.map((_e, i) => i).sort((a, b) => at[b] - at[a] || a - b); } export function entriesNewestFirst(entries: readonly T[]): T[] { return entryOrder(entries).map((i) => entries[i]); } // When the report last changed, its timeline counted: the latest of its own // `updated` and every entry's `date` and `updated` — when that is after // `published`. Else `updated` as given (an entry dated before the report was // published does not make it "updated"). export function effectiveUpdated(report: { published?: string; updated?: string; entries?: readonly { date: string; updated?: string }[]; }): string | undefined { let best = report.updated; let bestMs = reportDateMs(best); for (const e of report.entries ?? []) { for (const d of [e.date, e.updated]) { const ms = reportDateMs(d); if (!Number.isNaN(ms) && (Number.isNaN(bestMs) || ms > bestMs)) { best = d; bestMs = ms; } } } if (best === report.updated) return report.updated; const published = reportDateMs(report.published); return !Number.isNaN(published) && bestMs <= published ? report.updated : best; }