/**
 * PDF sidecar text → readable note body — the PDF extraction heuristics,
 * isolated from the authoritative convert pipeline (../convert-service.ts).
 *
 * This is best-effort, frequently-tuned "make the extracted text readable"
 * code with NO graph/storage side effects: text in → text out, deterministic,
 * no LLM. PDF text extraction yields hard-wrapped lines and split hyphens; this
 * rejoins wrapped prose + wrapped bullets, de-hyphenates line-end splits, and
 * drops stray empty list markers, while preserving real paragraph/block breaks.
 */
/** Reflow PDF-extracted text: de-hyphenate, unwrap soft-wrapped lines (prose and
 *  bullets), drop empty-bullet artifacts, and collapse blank-line runs. */
export function convertPdfToNoteText(sidecarText) {
    const text = sidecarText.trim();
    if (!text)
        return '';
    // De-hyphenate line-end splits before any line joining: "infor-\nmation".
    const dehyphenated = text.replace(/([A-Za-z])-\n(?=[a-z])/g, '$1');
    // A line that OPENS a block (bullet/number item or heading): never merged into
    // the previous line, but CAN receive following continuation lines.
    const startsBlock = (l) => /^\s*([-*+•]|\d+[.)])\s/.test(l) || /^\s*#{1,6}\s/.test(l);
    // A line that is ONLY a list marker with no content — a PDF extraction artifact.
    const isEmptyBullet = (l) => /^\s*([-*+•]|\d+[.)])\s*$/.test(l);
    // A line whose end is a real sentence/clause boundary — don't unwrap onto it.
    const endsSentence = (l) => /[.!?:;]["'”’)]?\s*$/.test(l.trim());
    // A short, punctuation-less, Title-Case or ALL-CAPS line reads as a heading
    // ("Executive Summary", "ESTIMATED FEES") — don't unwrap the next line ONTO it.
    // The Title-Case test requires EVERY word to start uppercase, so a wrapped
    // prose line like "The quick brown" (lowercase "quick"/"brown") still joins.
    const looksLikeHeading = (l) => {
        const t = l.trim();
        if (!t || endsSentence(t))
            return false;
        const words = t.split(/\s+/);
        if (words.length > 8)
            return false; // headings are short
        const hasLetters = /[A-Za-z]/.test(t);
        const allCaps = hasLetters && t === t.toUpperCase();
        const titleCase = hasLetters && words.every((w) => !/[a-z]/.test(w) || /^[^a-z]*[A-Z]/.test(w));
        return allCaps || titleCase;
    };
    const out = [];
    for (const raw of dehyphenated.split('\n')) {
        if (isEmptyBullet(raw))
            continue; // drop stray "-" artifacts
        const cur = raw.trim();
        if (cur === '') {
            out.push('');
            continue;
        } // blank = paragraph break
        if (startsBlock(raw)) {
            out.push(cur);
            continue;
        }
        // Continuation line: unwrap onto the previous line — prose OR a bullet — so a
        // wrapped bullet's tail rejoins its marker. Skip when the previous line is a
        // paragraph break, already ended a sentence/clause, or reads as a heading.
        const prev = out.length ? out[out.length - 1] : undefined;
        if (prev !== undefined && prev !== '' && !endsSentence(prev) && !looksLikeHeading(prev)) {
            out[out.length - 1] = `${prev} ${cur}`;
        }
        else {
            out.push(cur);
        }
    }
    // Collapse 3+ blank lines to a single paragraph break.
    return out.join('\n').replace(/\n{3,}/g, '\n\n').trim();
}
//# sourceMappingURL=pdf.js.map