import { CHAPTER_LAYOUT, PANEL_KINDS, PAYLOAD_BLOCKS_KEY, PAYLOAD_LAYOUT_KEY, PAYLOAD_SUBSECTIONS_KEY, TAG_FIELD_BY_KIND, } from "#configuration/constants/panel.constants"; import { PAYLOAD_CONTENT_KEY, PAYLOAD_ID_KEY, PAYLOAD_KIND_KEY, PAYLOAD_SECTIONS_KEY, PAYLOAD_TABS_KEY, WORD_SEPARATOR, } from "#configuration/constants/leak.constants"; import type { PanelSection, PayloadPanel } from "#types/panel.types"; import { payloadFileOf } from "#core/loaders/payload.loader"; import { readJsonOrNull } from "#core/persistence/report.persistence"; const isRecord = function isRecord(value: unknown): value is Record { return typeof value === "object" && value !== null; }; const listOf = function listOf(value: unknown): Record[] { return Array.isArray(value) ? value.filter(isRecord) : []; }; const isPanel = function isPanel(block: Record): boolean { return typeof block[PAYLOAD_KIND_KEY] === "string" && PANEL_KINDS.has(block[PAYLOAD_KIND_KEY]); }; const panelOf = function panelOf(block: Record): PayloadPanel { const kind = typeof block[PAYLOAD_KIND_KEY] === "string" ? block[PAYLOAD_KIND_KEY] : ""; const tag = block[TAG_FIELD_BY_KIND.get(kind) ?? ""]; return { kind, tag: typeof tag === "string" && tag.length > 0 ? tag : null }; }; const stringsOf = function stringsOf(value: unknown): string[] { if (typeof value === "string") { return [value]; } if (Array.isArray(value)) { return value.flatMap((entry: unknown) => stringsOf(entry)); } if (!isRecord(value) || isPanel(value)) { return []; } return Object.values(value).flatMap((entry) => stringsOf(entry)); }; const blocksOf = function blocksOf(section: Record): Record[] { return [ ...listOf(section[PAYLOAD_BLOCKS_KEY]), ...listOf(section[PAYLOAD_SUBSECTIONS_KEY]).flatMap((sub) => listOf(sub[PAYLOAD_BLOCKS_KEY])), ]; }; const sectionOf = function sectionOf(section: Record): PanelSection { const id = section[PAYLOAD_ID_KEY]; return { id: typeof id === "string" ? id : "", panels: blocksOf(section).filter(isPanel).map(panelOf), prose: stringsOf(section).join(WORD_SEPARATOR), }; }; const isChapterTab = function isChapterTab(tab: Record): boolean { return tab[PAYLOAD_LAYOUT_KEY] === undefined || tab[PAYLOAD_LAYOUT_KEY] === CHAPTER_LAYOUT; }; export const readPanelSections = function readPanelSections(page: string): PanelSection[] | null { const parsed = readJsonOrNull(payloadFileOf(page)); if (!isRecord(parsed) || !isRecord(parsed[PAYLOAD_CONTENT_KEY])) { return null; } const content = parsed[PAYLOAD_CONTENT_KEY]; if (content[PAYLOAD_LAYOUT_KEY] !== CHAPTER_LAYOUT) { return []; } return listOf(content[PAYLOAD_TABS_KEY]) .filter(isChapterTab) .flatMap((tab) => listOf(tab[PAYLOAD_SECTIONS_KEY])) .map(sectionOf); };