"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CodeBlockSpecs = exports.codeBlockType = exports.codeBlockNodeName = exports.CodeBlockNodeAttr = void 0;
const schema_1 = require("../../../../utils/schema.js");
exports.CodeBlockNodeAttr = {
    Lang: 'data-language',
    Markup: 'data-markup',
};
exports.codeBlockNodeName = 'code_block';
exports.codeBlockType = (0, schema_1.nodeTypeFactory)(exports.codeBlockNodeName);
const getLangOfNode = (node) => {
    let result = node.getAttribute(exports.CodeBlockNodeAttr.Lang) || '';
    if (!result) {
        const firstElementChild = node.firstElementChild;
        if (firstElementChild &&
            firstElementChild.nodeName.toLowerCase() === 'code' &&
            firstElementChild.classList.contains('hljs')) {
            result = firstElementChild.getAttribute('class')?.split(' ')?.[1] || '';
        }
    }
    return result;
};
const CodeBlockSpecs = (builder, opts) => {
    builder.addNode(exports.codeBlockNodeName, () => ({
        view: opts.nodeview,
        spec: {
            attrs: {
                [exports.CodeBlockNodeAttr.Lang]: { default: '' },
                [exports.CodeBlockNodeAttr.Markup]: { default: '```' },
            },
            content: 'text*',
            group: 'block',
            code: true,
            marks: '',
            selectable: true,
            allowSelection: false,
            parseDOM: [
                {
                    tag: 'pre',
                    preserveWhitespace: 'full',
                    getAttrs: (node) => {
                        return {
                            [exports.CodeBlockNodeAttr.Lang]: getLangOfNode(node),
                        };
                    },
                },
            ],
            toDOM({ attrs }) {
                return ['pre', attrs, ['code', 0]];
            },
        },
        fromMd: {
            tokenSpec: {
                name: exports.codeBlockNodeName,
                type: 'block',
                noCloseToken: true,
                prepareContent: removeNewLineAtEnd, // content of code blocks contains extra \n at the end
            },
        },
        toMd: (state, node) => {
            const lang = node.attrs[exports.CodeBlockNodeAttr.Lang];
            const markup = node.attrs[exports.CodeBlockNodeAttr.Markup];
            state.write(markup + lang + '\n');
            state.text(node.textContent, false);
            // Add a newline to the current content before adding closing marker
            state.write('\n');
            state.write(markup);
            state.closeBlock(node);
        },
    }));
    builder.addNode('fence', () => ({
        //  we adding this node only for define specific 'fence' parser token,
        //  which parse fence md token to code_block node
        spec: {},
        fromMd: {
            tokenSpec: {
                name: exports.codeBlockNodeName,
                type: 'block',
                noCloseToken: true,
                getAttrs: (tok) => {
                    const attrs = {
                        [exports.CodeBlockNodeAttr.Markup]: tok.markup,
                    };
                    if (tok.info) {
                        // like in markdown-it
                        // https://github.com/markdown-it/markdown-it/blob/d07d585b6b15aaee2bc8f7a54b994526dad4dbc5/lib/renderer.mjs#L36-L37
                        attrs[exports.CodeBlockNodeAttr.Lang] = tok.info.split(/(\s+)/g)[0];
                    }
                    return attrs;
                },
                prepareContent: removeNewLineAtEnd, // content of fence blocks contains extra \n at the end
            },
        },
        toMd: () => {
            throw new Error('Unexpected toMd() call on fence node');
        },
    }));
    builder.addKeymap(() => ({
        Tab: (state, dispatch) => {
            const { $anchor, $head } = state.selection;
            if ($anchor.sameParent($head) && $anchor.parent.type.name === exports.codeBlockNodeName) {
                dispatch?.(state.tr.replaceSelectionWith(state.schema.text('\t')).scrollIntoView());
                return true;
            }
            return false;
        },
    }));
};
exports.CodeBlockSpecs = CodeBlockSpecs;
function removeNewLineAtEnd(content) {
    return content.endsWith('\n') ? content.slice(0, content.length - 1) : content;
}
//# sourceMappingURL=index.js.map
