/** * Table bridge — JSON-LD → Table (TS model). * * Wire format: * * { * "@type": "gl:Table", * "gl:id": "{id}", * "gl:identifier": "Table 2", * "gl:caption": { ... }, * "gl:description": { ... }, * "gl:content": { * "gl:type": "structured" | "markup", * "gl:headers": [ { "eng": "..." }, ... ], // structured * "gl:rows": [ [ { "eng": "..." }, ... ], ... ], // structured * "gl:markup": { "eng": "...
" } // markup * }, * "gl:format": "html" | "markdown" | "asciidoc", * "gl:source": [ ... ] * } */ import { Table } from 'glossarist'; import type { TableContent } from './types'; import { isType, pickField, localized } from './prefix'; import { sourcesFromJsonLd } from './source-bridge'; const FORMAT_SET: ReadonlySet = new Set(['html', 'markdown', 'asciidoc']); function isLocalizedObj(v: unknown): v is Record { if (!v || typeof v !== 'object' || Array.isArray(v)) return false; return Object.values(v).every(x => typeof x === 'string'); } function contentFromJsonLd(raw: unknown): TableContent | null { if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return null; const c = raw as Record; const typeRaw = (pickField(c, 'type') ?? '').toLowerCase(); if (typeRaw === 'markup') { const markup = localized(c, 'markup'); if (!markup) return null; return { kind: 'markup', markup }; } if (typeRaw === 'structured' || !typeRaw) { const headersRaw = pickField(c, 'headers'); const rowsRaw = pickField(c, 'rows'); if (!Array.isArray(headersRaw) || !Array.isArray(rowsRaw)) return null; const headers: Record[] = []; for (const h of headersRaw) { if (isLocalizedObj(h)) headers.push(h); } if (headers.length === 0) return null; const rows: Record[][] = []; for (const r of rowsRaw) { if (!Array.isArray(r)) continue; const cells: Record[] = []; for (const cell of r) { if (isLocalizedObj(cell)) cells.push(cell); } if (cells.length) rows.push(cells); } if (rows.length === 0) return null; return { kind: 'structured', headers, rows }; } return null; } export function tableFromJsonLd(doc: Record): Table | null { if (!isType(doc, 'Table')) return null; const id = pickField(doc, 'id') ?? ''; if (!id) return null; const identifier = pickField(doc, 'identifier'); const caption = localized(doc, 'caption'); const description = localized(doc, 'description'); const content = contentFromJsonLd(pickField(doc, 'content')); if (!content) return null; const formatRaw = (pickField(doc, 'format') ?? '').toLowerCase(); const format = FORMAT_SET.has(formatRaw) ? formatRaw : undefined; const sources = sourcesFromJsonLd(pickField(doc, 'source')); return new Table({ id, content: content as any, ...(identifier && { identifier }), ...(caption && { caption }), ...(description && { description }), ...(format && { format }), ...(sources.length && { sources }), } as any); }