import { $insertGeneratedNodes } from '@lexical/clipboard';
import { $generateNodesFromDOM } from '@lexical/html';
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
import { $createParagraphNode, $createTextNode, $getSelection, $isRangeSelection, COMMAND_PRIORITY_HIGH, PASTE_COMMAND, } from 'lexical';
import { useEffect } from 'react';
const LEXICAL_MIME_TYPE = 'application/x-lexical-editor';
const PRESENTATIONAL_ATTRIBUTES = ['class', 'id', 'style'];
const LEGACY_PRESENTATIONAL_ATTRIBUTES = ['align', 'bgcolor', 'color', 'face', 'size'];
const REMOVED_TAGS = ['link', 'meta', 'script', 'style'];
/**
 * Removes unsafe and presentational markup from pasted HTML.
 * @param doc Parsed clipboard HTML document.
 */
function sanitizePastedHTMLDocument(doc) {
    REMOVED_TAGS.forEach((tagName) => {
        doc.querySelectorAll(tagName).forEach((node) => node.remove());
    });
    doc.body.querySelectorAll('*').forEach((element) => {
        PRESENTATIONAL_ATTRIBUTES.forEach((attribute) => {
            element.removeAttribute(attribute);
        });
        if (element.tagName === 'FONT') {
            LEGACY_PRESENTATIONAL_ATTRIBUTES.forEach((attribute) => {
                element.removeAttribute(attribute);
            });
        }
    });
}
/**
 * Inserts pasted plain text as separate paragraphs when it contains line breaks.
 * @param text Plain text clipboard content.
 * @returns True when text was handled as multiple paragraphs.
 */
function insertMultilinePlainText(text) {
    if (!/\r|\n/.test(text)) {
        return false;
    }
    const selection = $getSelection();
    if (!$isRangeSelection(selection)) {
        return false;
    }
    const paragraphs = text
        .replace(/\r\n?/g, '\n')
        .split('\n')
        .map((line) => {
        const paragraph = $createParagraphNode();
        if (line.length > 0) {
            paragraph.append($createTextNode(line));
        }
        return paragraph;
    });
    selection.insertNodes(paragraphs);
    return true;
}
/**
 * Registers paste sanitization for the rich text editor.
 * @returns Null because the plugin only registers editor commands.
 */
export default function SanitizePastePlugin() {
    const [editor] = useLexicalComposerContext();
    useEffect(() => editor.registerCommand(PASTE_COMMAND, (event) => {
        if (!('clipboardData' in event) || event.clipboardData == null) {
            return false;
        }
        const { clipboardData } = event;
        if (clipboardData.types.includes(LEXICAL_MIME_TYPE)) {
            return false;
        }
        const text = clipboardData.getData('text/plain');
        if (/\r|\n/.test(text)) {
            event.preventDefault();
            return insertMultilinePlainText(text);
        }
        const html = clipboardData.getData('text/html');
        if (!html) {
            return false;
        }
        event.preventDefault();
        editor.update(() => {
            const selection = $getSelection();
            if (selection == null) {
                return;
            }
            const parser = new DOMParser();
            const doc = parser.parseFromString(html, 'text/html');
            sanitizePastedHTMLDocument(doc);
            const nodes = $generateNodesFromDOM(editor, doc);
            $insertGeneratedNodes(editor, nodes, selection);
        });
        return true;
    }, COMMAND_PRIORITY_HIGH), [editor]);
    return null;
}
//# sourceMappingURL=index.js.map