import type { ReactNode } from "react"; const MARK_OPEN = ""; const MARK_CLOSE = ""; /** CommonMark backslash escape: `\` before any ASCII punctuation character. */ const MARKDOWN_ESCAPE = /\\([!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~])/g; /** Drop Markdown backslash escapes (`state.db\#` -> `state.db#`). */ export function unescapeMarkdown(text: string): string { return text.replace(MARKDOWN_ESCAPE, "$1"); } /** * Render a search snippet: FTS `` highlights become real * elements, everything else stays React text (never parsed as HTML). * Markdown backslash escapes are dropped because indexed text keeps them. */ export function renderSnippet(snippet: string): ReactNode[] { const parts: ReactNode[] = []; let remaining = snippet; let key = 0; while (remaining.length > 0) { const markStart = remaining.indexOf(MARK_OPEN); if (markStart === -1) { parts.push(unescapeMarkdown(remaining)); break; } if (markStart > 0) { parts.push(unescapeMarkdown(remaining.slice(0, markStart))); } const markEnd = remaining.indexOf(MARK_CLOSE, markStart); if (markEnd === -1) { parts.push(unescapeMarkdown(remaining.slice(markStart))); break; } parts.push( {unescapeMarkdown( remaining.slice(markStart + MARK_OPEN.length, markEnd) )} ); remaining = remaining.slice(markEnd + MARK_CLOSE.length); } return parts; }