import { renderInline } from "../inline/render.js"; import { identifyBlocks, isBlockBoundary, leavesParagraphOpen, resolveBlockHandler, } from "./identify.js"; import { stripParagraphIndent } from "./paragraph.handler.js"; export function splitItemHead(itemRaw: string): [string, string[]] { const lines = itemRaw.split("\n"); return [lines[0], lines.slice(1)]; } export function joinItemLines(head: string, tail: readonly string[]): string { return tail.length > 0 ? [head, ...tail].join("\n") : head; } function dedentTail(itemRaw: string): string { const [head, tail] = splitItemHead(itemRaw); if (tail.length === 0) return itemRaw; let common = Number.POSITIVE_INFINITY; for (const line of tail) { if (line.trim() === "") continue; common = Math.min(common, line.length - line.trimStart().length); } if (!Number.isFinite(common) || common === 0) return itemRaw; return joinItemLines( head, tail.map((line) => line.slice(common)), ); } export function isLooseList(items: readonly string[]): boolean { return items.some((item) => /\n[ \t]*\n/.test(item) || /\n[ \t]*$/.test(item)); } export function renderItemContent(itemRaw: string, loose = false): string { if (!itemRaw.includes("\n")) { const text = renderInline(stripParagraphIndent(itemRaw)); return loose ? `

${text}

` : text; } const chunks = identifyBlocks(dedentTail(itemRaw)); return chunks .map((chunk, index) => { if (index === 0 && chunk.type === "paragraph" && !loose) return renderInline(stripParagraphIndent(chunk.raw)); const handler = resolveBlockHandler(chunk.type); return handler ? handler.render(chunk.raw, chunk.attrs) : ""; }) .join(""); } export function serializeItemTail(tail: readonly string[], head = ""): string[] { const out: string[] = []; let previous = head; for (const line of tail) { if (line.trim() === "") { out.push(""); previous = ""; continue; } const lazy = leavesParagraphOpen(previous) && !isBlockBoundary(line); out.push(lazy || /^[ \t]/.test(line) ? line : ` ${line}`); previous = line; } return out; }