"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.collapseListsPlugin = void 0;
exports.collapseEmptyListItems = collapseEmptyListItems;
const prosemirror_model_1 = require("prosemirror-model");
const prosemirror_state_1 = require("prosemirror-state");
// @ts-ignore // TODO: fix cjs build
const prosemirror_utils_1 = require("prosemirror-utils");
const utils_1 = require("../../../../utils/index.js");
const utils_2 = require("../utils.js");
const collapseListsPlugin = () => new prosemirror_state_1.Plugin({
    appendTransaction(trs, oldState, newState) {
        const docChanged = trs.some((tr) => tr.docChanged);
        if (!docChanged)
            return null;
        const hasParentList = (0, prosemirror_utils_1.hasParentNode)(utils_2.isListNode)(newState.selection) ||
            (0, prosemirror_utils_1.hasParentNode)(utils_2.isListNode)(oldState.selection);
        if (!hasParentList)
            return null;
        const { tr } = newState;
        let prevStepsCount = -1;
        let currentStepsCount = 0;
        // execute until there are no nested lists.
        while (prevStepsCount !== currentStepsCount) {
            const listNodes = (0, prosemirror_utils_1.findChildren)(tr.doc, utils_2.isListNode, true);
            prevStepsCount = currentStepsCount;
            currentStepsCount = collapseEmptyListItems(tr, listNodes);
        }
        return tr.docChanged ? tr : null;
    },
});
exports.collapseListsPlugin = collapseListsPlugin;
function collapseEmptyListItems(tr, nodes) {
    const stepsCountBefore = tr.steps.length;
    // TODO: fix cjs build
    nodes.reverse().forEach((list) => {
        const listNode = list.node;
        const listPos = list.pos;
        const childrenOfList = (0, utils_1.getChildrenOfNode)(listNode).reverse();
        childrenOfList.forEach(({ node: itemNode, offset }) => {
            if ((0, utils_2.isListItemNode)(itemNode)) {
                const { firstChild } = itemNode;
                const listItemNodePos = listPos + 1 + offset;
                // if the first child of a list element is a list,
                // then collapse is required
                if (firstChild && (0, utils_2.isListNode)(firstChild)) {
                    const nestedList = firstChild.content;
                    // nodes at the same level as the list
                    const remainingNodes = itemNode.content.content.slice(1);
                    const listItems = remainingNodes.length
                        ? nestedList.append(prosemirror_model_1.Fragment.from((0, utils_2.liType)(tr.doc.type.schema).create(null, remainingNodes)))
                        : nestedList;
                    const mappedStart = tr.mapping.map(listItemNodePos);
                    const mappedEnd = tr.mapping.map(listItemNodePos + itemNode.nodeSize);
                    tr.replaceWith(mappedStart, mappedEnd, listItems);
                    const closestTextNodePos = findClosestTextNodePos(tr.doc, mappedStart + nestedList.size);
                    if (closestTextNodePos) {
                        tr.setSelection(prosemirror_state_1.TextSelection.create(tr.doc, closestTextNodePos));
                    }
                }
            }
        });
    });
    return tr.steps.length - stepsCountBefore;
}
function findClosestTextNodePos(doc, pos) {
    while (pos < doc.content.size) {
        const node = doc.nodeAt(pos);
        if (node && node.isText) {
            return pos;
        }
        pos++;
    }
    return null;
}
//# sourceMappingURL=CollapseListsPlugin.js.map
