export const createRemoveEmptyParagraphsPlugin = (enabled = false) => {
    return () => {
        if (!enabled) {
            return (tree) => tree;
        }
        return (tree) => {
            pruneEmptyParagraphs(tree, null);
            return tree;
        };
    };
};
const NBSP_REGEX = /\u00A0/g;
const ZERO_WIDTH_HEX_CODES = ['200B', '200C', '200D', 'FEFF'];
const MEANINGFUL_VOID_ELEMENTS = new Set([
    'audio',
    'canvas',
    'embed',
    'iframe',
    'img',
    'input',
    'object',
    'svg',
    'video',
]);
const TREAT_AS_EMPTY_ELEMENTS = new Set(['br']);
const stripZeroWidthCharacters = (text) => {
    let cleaned = text;
    for (const hexCode of ZERO_WIDTH_HEX_CODES) {
        const character = String.fromCodePoint(Number.parseInt(hexCode, 16));
        cleaned = cleaned.split(character).join('');
    }
    return cleaned;
};
const pruneEmptyParagraphs = (node, parent) => {
    if (!node || typeof node !== 'object') {
        return;
    }
    if (node.type === 'element' &&
        node.tagName === 'p' &&
        parent &&
        isParagraphEffectivelyEmpty(node) &&
        Array.isArray(parent.children)) {
        const index = parent.children.indexOf(node);
        if (index !== -1) {
            parent.children.splice(index, 1);
            return;
        }
    }
    if (!Array.isArray(node.children) || node.children.length === 0) {
        return;
    }
    for (let i = node.children.length - 1; i >= 0; i--) {
        pruneEmptyParagraphs(node.children[i], node);
    }
};
const isParagraphEffectivelyEmpty = (element) => {
    if (!Array.isArray(element.children) || element.children.length === 0) {
        return true;
    }
    return element.children.every((child) => isNodeEffectivelyEmpty(child));
};
const isNodeEffectivelyEmpty = (node) => {
    if (!node) {
        return true;
    }
    if (node.type === 'text') {
        return isWhitespace(typeof node.value === 'string' ? node.value : '');
    }
    if (node.type === 'comment') {
        return true;
    }
    if (node.type === 'element') {
        const element = node;
        const tagName = element.tagName;
        if (typeof tagName !== 'string') {
            return true;
        }
        if (isMeaningfulElement(tagName)) {
            return false;
        }
        if (TREAT_AS_EMPTY_ELEMENTS.has(tagName)) {
            return true;
        }
        if (!Array.isArray(element.children) || element.children.length === 0) {
            return true;
        }
        return element.children.every((child) => isNodeEffectivelyEmpty(child));
    }
    return true;
};
/**
 * Returns true if the tag name belongs to a custom element (web component).
 * Per the HTML spec, custom element names must contain a hyphen.
 * @param tagName
 */
const isCustomElement = (tagName) => {
    return tagName.includes('-');
};
/**
 * Returns true for elements that are meaningful even without children.
 * Includes standard void elements (img, video, etc.) and custom elements
 * (web components), which render their own shadow DOM content.
 * @param tagName
 */
const isMeaningfulElement = (tagName) => {
    return MEANINGFUL_VOID_ELEMENTS.has(tagName) || isCustomElement(tagName);
};
const isWhitespace = (value) => {
    if (!value) {
        return true;
    }
    const normalized = stripZeroWidthCharacters(value.replaceAll(NBSP_REGEX, ' '));
    return normalized.trim() === '';
};
