import type { ItemSource, UnifiedItem } from "../shared/types.js"; export const LINE_WIDTH = 60; export const PAGE_BODY_LINES = 24; export function renderList(items: UnifiedItem[]): string { const lines: string[] = [`COUNT:${items.length}`, "==="]; for (const it of items) { lines.push(`ID:${it.id}`); lines.push(`S:${it.source}`); lines.push(`R:${it.read ? 1 : 0}`); lines.push(`D:${it.fetchedAt}`); lines.push(`T:${singleLine(it.title)}`); if (it.publication) lines.push(`F:${singleLine(it.publication)}`); lines.push("==="); } return lines.join("\n") + "\n"; } export function renderItem( id: string, source: ItemSource, title: string, url: string, fetchedAt: number, body: string, page: number, publication?: string, ): string { const wrapped = wrapLines(body, LINE_WIDTH); const totalPages = Math.max(1, Math.ceil(wrapped.length / PAGE_BODY_LINES)); const p = clamp(page, 1, totalPages); const start = (p - 1) * PAGE_BODY_LINES; const pageLines = wrapped.slice(start, start + PAGE_BODY_LINES); const header = [ `ID:${id}`, `S:${source}`, `T:${singleLine(title)}`, `U:${singleLine(url)}`, `D:${fetchedAt}`, `P:${p}/${totalPages}`, ]; if (publication) header.push(`F:${singleLine(publication)}`); return [...header, "---", ...pageLines, ""].join("\n"); } function singleLine(s: string): string { return s.replace(/[\r\n]+/g, " ").trim(); } function clamp(n: number, lo: number, hi: number): number { return Math.max(lo, Math.min(hi, n)); } export function wrapLines(text: string, width: number): string[] { const paragraphs = text.split("\n"); const out: string[] = []; for (const p of paragraphs) { const trimmed = p.trim(); if (!trimmed) { out.push(""); continue; } out.push(...wrapParagraph(trimmed, width)); } return out; } function wrapParagraph(p: string, width: number): string[] { const words = p.split(/\s+/); const out: string[] = []; let cur = ""; for (const w of words) { const cand = cur ? cur + " " + w : w; if (cand.length > width && cur) { out.push(cur); cur = w; } else { cur = cand; } } if (cur) out.push(cur); return out; }