"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.codeBlockLineNumbersPlugin = void 0;
const state_1 = require("../../../../../pm/state.js");
const utils_1 = require("../../../../../pm/utils.js");
const view_1 = require("../../../../../pm/view.js");
const CodeBlockSpecs_1 = require("../../CodeBlockSpecs/index.js");
const utils_2 = require("../utils.js");
const pluginKey = new state_1.PluginKey('code_block_line_numbers_decorations');
/** @internal */
const codeBlockLineNumbersPlugin = () => {
    return new state_1.Plugin({
        key: pluginKey,
        state: {
            init(_config, state) {
                const cache = new WeakSet();
                return { cache, decoSet: buildAllDecorations(state.doc, cache) };
            },
            apply(tr, { cache, decoSet }) {
                if (!tr.docChanged)
                    return { cache, decoSet };
                decoSet = (0, utils_2.processChangedCodeBlocks)(tr, decoSet, (node, pos, decoSet) => {
                    if (!(0, utils_2.isLineNumbersVisible)(node)) {
                        return decoSet.remove(decoSet.find(pos, pos + node.nodeSize));
                    }
                    if (cache.has(node)) {
                        // node has not changed, but decorations may be missing (after undo/redo)
                        if (!decoSet.find(pos, pos + node.nodeSize).length) {
                            return decoSet.add(tr.doc, buildNodeDecorations(node, pos));
                        }
                        return decoSet;
                    }
                    decoSet = decoSet.remove(decoSet.find(pos, pos + node.nodeSize));
                    cache.add(node);
                    return decoSet.add(tr.doc, buildNodeDecorations(node, pos));
                });
                return { cache, decoSet };
            },
        },
        props: {
            decorations(state) {
                return pluginKey.getState(state)?.decoSet;
            },
        },
    });
};
exports.codeBlockLineNumbersPlugin = codeBlockLineNumbersPlugin;
function buildAllDecorations(doc, cache) {
    const decos = [];
    for (const { node, pos } of (0, utils_1.findChildrenByType)(doc, (0, CodeBlockSpecs_1.codeBlockType)(doc.type.schema), true)) {
        if (!(0, utils_2.isLineNumbersVisible)(node))
            continue;
        const nodeDecos = buildNodeDecorations(node, pos);
        cache.add(node);
        decos.push(...nodeDecos);
    }
    return view_1.DecorationSet.create(doc, decos);
}
function buildNodeDecorations(node, pos) {
    const decos = [];
    const codeContent = node.textContent;
    const contentByLines = codeContent.split('\n');
    const maxDigits = String(contentByLines.length).length;
    let shift = 0;
    for (let i = 0; i < contentByLines.length; i++) {
        const line = contentByLines[i];
        const elem = document.createElement('span');
        elem.classList.add('yfm-line-number');
        elem.textContent = String(i + 1).padStart(maxDigits, ' ');
        decos.push(view_1.Decoration.widget(pos + shift + 1, elem, { side: 1, ignoreSelection: true }));
        shift += line.length + 1;
    }
    return decos;
}
//# sourceMappingURL=codeBlockLineNumbersPlugin.js.map
