import { describe, it, expect } from 'vitest'; import { readdirSync, readFileSync } from 'node:fs'; import { fileURLToPath } from 'node:url'; import { dirname, join } from 'node:path'; const timelineDir = dirname(fileURLToPath(import.meta.url)); /** * REQ-010 / CWE-79: inline event clustering renders curator event titles and import-derived * letter titles + sender/receiver text through every component under lib/timeline (the reused * LetterCard, the new EventCluster card, the existing pills/bands/strip). That text must always * render through Svelte's default `{...}` escaping — never `{@html}`. This grep gate fails loudly * the moment any timeline component reaches for the raw-HTML directive. */ describe('lib/timeline never uses {@html} (REQ-010)', () => { it('no timeline component contains the raw-HTML directive', () => { const components = readdirSync(timelineDir).filter((file) => file.endsWith('.svelte')); expect(components.length).toBeGreaterThan(0); const offenders = components.filter((file) => readFileSync(join(timelineDir, file), 'utf8').includes('{@html') ); expect(offenders).toEqual([]); }); });