const TEXT_NODE = "text"; function textNode(text: string) { return { type: TEXT_NODE, text, }; } function paragraphNode(lines: string[]) { const content: Array<{ type: string; text?: string }> = []; lines.forEach((line, index) => { if (index > 0) { content.push({ type: "hardBreak" }); } if (line.length > 0) { content.push(textNode(line)); } }); return { type: "paragraph", ...(content.length > 0 ? { content } : {}), }; } export function markdownToAdf(input: string) { const lines = input.replace(/\r\n/g, "\n").split("\n"); const content: Array> = []; let index = 0; while (index < lines.length) { const current = lines[index]?.trimEnd() ?? ""; if (current.trim().length === 0) { index += 1; continue; } const heading = current.match(/^(#{1,6})\s+(.*)$/); if (heading) { content.push({ type: "heading", attrs: { level: heading[1].length }, content: [textNode(heading[2])], }); index += 1; continue; } if (/^[-*]\s+/.test(current)) { const items: Array> = []; while (index < lines.length && /^[-*]\s+/.test(lines[index] ?? "")) { items.push({ type: "listItem", content: [ { type: "paragraph", content: [textNode((lines[index] ?? "").replace(/^[-*]\s+/, ""))], }, ], }); index += 1; } content.push({ type: "bulletList", content: items, }); continue; } const paragraphLines: string[] = []; while (index < lines.length && (lines[index]?.trim().length ?? 0) > 0) { paragraphLines.push(lines[index] ?? ""); index += 1; } content.push(paragraphNode(paragraphLines)); } return { type: "doc", version: 1, content, }; }