import { CHAPTER_FACE, CHAPTER_KIND } from "#configuration/constants/vocabulary.constants"; import type { ChapterSubject, Evidence, EvidenceSubject } from "#types/evidence.types"; import { pageFromPath, pagePath } from "#assets/link.assets"; import { ANCHOR_PREFIX } from "#configuration/constants/document.constants"; import type { EdgeRef } from "#types/link.types"; import { FACE_SEPARATOR } from "@govlab/constants"; import type { ReferenceTarget } from "#types/reference.types"; import { SITE_VOCABULARY } from "#configuration/strings/site.strings"; const CHAPTER_PREFIX = CHAPTER_FACE + FACE_SEPARATOR; const chapterHref = function chapterHref(target: ReferenceTarget): string | null { return target.face === CHAPTER_FACE && target.ref.startsWith(CHAPTER_PREFIX) ? target.ref.slice(CHAPTER_PREFIX.length) : null; }; const isChapterOf = function isChapterOf(subject: ChapterSubject, href: string): boolean { const cut = href.indexOf(ANCHOR_PREFIX); const section = cut === -1 ? "" : href.slice(cut + ANCHOR_PREFIX.length); return section === subject.section && pageFromPath(href, "") === subject.page; }; export const subjectMatches = function subjectMatches(subject: EvidenceSubject, target: ReferenceTarget): boolean { if (subject.kind === "record") { return subject.ref === target.ref; } const href = chapterHref(target); return href !== null && isChapterOf(subject, href); }; export const evidenceFor = function evidenceFor( target: ReferenceTarget, registry: readonly Evidence[], ): readonly Evidence[] { return registry.filter((entry) => subjectMatches(entry.subject, target)); }; export const chapterEdge = function chapterEdge(subject: ChapterSubject): EdgeRef | null { const head = CHAPTER_PREFIX + pagePath(subject.page); const tail = ANCHOR_PREFIX + subject.section; const entry = SITE_VOCABULARY.find( (candidate) => candidate.kind === CHAPTER_KIND && candidate.ref.startsWith(head) && candidate.ref.endsWith(tail), ); return entry === undefined ? null : { label: entry.phrase, ref: entry.ref }; };