/**
 * Whitespace reconciliation for AI text edits.
 *
 * AI models return replacement/insert text without the boundary whitespace of
 * the location it lands in: double-click selections include the trailing
 * space of a word, and cursor insertions sit directly between two characters.
 * Splicing the model output in verbatim glues words together ("HelloWorld").
 */
const LEADING_WHITESPACE_REGEX = /^\s/;
const TRAILING_WHITESPACE_REGEX = /\s$/;
const WORD_CHAR_REGEX = /[\p{L}\p{N}]/u;
// A char before the insertion point that still needs a gap before prose:
// word chars, sentence punctuation and closing brackets/quotes.
const NEEDS_GAP_AFTER_CHAR_REGEX = /[\p{L}\p{N}.,;:!?)\]}»%"']/u;
// Replacement beginnings that attach directly to the previous char.
const ATTACHES_LEFT_REGEX = /^[.,;:!?)\]}»%…]/;
// Replacement endings that attach directly to the following char.
const ATTACHES_RIGHT_REGEX = /[([{«]$/;
function isWhitespace(char) {
    return /\s/.test(char);
}
/**
 * Re-attach the leading/trailing whitespace of the original selected text to
 * a replacement that lacks it, so replacing e.g. "world " (double-click
 * selection) with "planet" does not glue "planet" to the following word.
 */
export function preserveSelectionBoundaryWhitespace(originalText, replacementText) {
    if (!originalText)
        return replacementText;
    const leading = originalText.match(/^\s+/)?.[0] ?? "";
    const trailing = originalText.match(/\s+$/)?.[0] ?? "";
    // Deletion: keep a single boundary so the neighbours don't collapse together.
    if (!replacementText) {
        return leading || trailing;
    }
    let result = replacementText;
    if (leading && !LEADING_WHITESPACE_REGEX.test(result)) {
        result = leading + result;
    }
    if (trailing && !TRAILING_WHITESPACE_REGEX.test(result)) {
        result = result + trailing;
    }
    return result;
}
/**
 * Pad text inserted at a collapsed cursor with the spaces required by its
 * immediate neighbours, e.g. inserting "new text" at "Hello|world" yields
 * " new text " rather than "Hellonew textworld". Markup characters (<, >, =)
 * never trigger padding, so raw HTML field values stay untouched.
 */
export function padInsertedTextWhitespace(newText, charBefore, charAfter) {
    if (!newText.trim())
        return newText;
    let result = newText;
    if (charBefore &&
        !isWhitespace(charBefore) &&
        NEEDS_GAP_AFTER_CHAR_REGEX.test(charBefore) &&
        !LEADING_WHITESPACE_REGEX.test(result) &&
        !ATTACHES_LEFT_REGEX.test(result)) {
        result = " " + result;
    }
    if (charAfter &&
        !isWhitespace(charAfter) &&
        WORD_CHAR_REGEX.test(charAfter) &&
        !ATTACHES_RIGHT_REGEX.test(result) &&
        !TRAILING_WHITESPACE_REGEX.test(result)) {
        result = result + " ";
    }
    return result;
}
//# sourceMappingURL=textInsertionWhitespace.js.map