A notes and TODOs app built on atproto
Something went wrong. Try again.
12345678910111213141516171819202122232425262728293031323334353637383940414243export type MarkdownBlock = Readonly<{ kind: "blank" | "check" | "heading" | "ordered" | "paragraph" | "unordered"; line: number; level?: number; checked?: boolean; text: string;}>;
export function parseMarkdownBlocks(markdown: string): readonly MarkdownBlock[] { return markdown.split("\n").map((source, line) => { if (!source.trim()) return { kind: "blank", line, text: "" }; const heading = /^(#{1,6})\s+(.*)$/.exec(source); if (heading) return { kind: "heading", line, level: heading[1]!.length, text: heading[2]! }; const check = /^\s*[-*+]\s+\[([ xX])\]\s*(.*)$/.exec(source); if (check) return { kind: "check", line, checked: check[1]!.toLowerCase() === "x", text: check[2]! }; const unordered = /^\s*[-*+]\s+(.*)$/.exec(source); if (unordered) return { kind: "unordered", line, text: unordered[1]! }; const ordered = /^\s*\d+\.\s+(.*)$/.exec(source); if (ordered) return { kind: "ordered", line, text: ordered[1]! }; return { kind: "paragraph", line, text: source }; });}
export function toggleMarkdownCheckbox(markdown: string, line: number): string { const lines = markdown.split("\n"); const source = lines[line]; if (source === undefined) return markdown; if (/^(\s*[-*+]\s+)\[ \]/.test(source)) lines[line] = source.replace(/^(\s*[-*+]\s+)\[ \]/, "$1[x]"); else if (/^(\s*[-*+]\s+)\[[xX]\]/.test(source)) lines[line] = source.replace(/^(\s*[-*+]\s+)\[[xX]\]/, "$1[ ]"); return lines.join("\n");}
export function prefixMarkdownLines(markdown: string, start: number, end: number, prefix: string) { const lineStart = markdown.lastIndexOf("\n", Math.max(0, start - 1)) + 1; const nextBreak = markdown.indexOf("\n", end); const lineEnd = nextBreak === -1 ? markdown.length : nextBreak; const selected = markdown.slice(lineStart, lineEnd); const replacement = selected.split("\n").map((line) => `${prefix}${line}`).join("\n"); const value = markdown.slice(0, lineStart) + replacement + markdown.slice(lineEnd); const added = replacement.length - selected.length; return { value, selectionStart: lineStart + prefix.length, selectionEnd: end + added } as const;}