"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.setHeadingId = setHeadingId;
exports.assignPanelId = assignPanelId;
const cheerio_1 = __importDefault(require("cheerio"));
const slugify_1 = __importDefault(require("@sindresorhus/slugify"));
const has_1 = __importDefault(require("lodash/has"));
const vueSlotSyntaxProcessor_1 = require("./vueSlotSyntaxProcessor");
const _ = {
    has: has_1.default,
};
/**
 * Increment the counter for same heading text, and set the id of the heading node
 *
 * If the addHeaderCount is false, the counter for the same heading text will not be incremented.
 * The heading id will also not have the count appended to it.
 *
 * So for, only SiteLinkManager uses this function with addHeaderCount set to false.
 * This is for validating intralinks in a side-effect free manner.
 *
 * Heading text refers to textContent of h1-h6 Nodes.
 */
function setHeadingId(node, config, addHeaderCount = true) {
    const textContent = (0, cheerio_1.default)(node).text();
    // remove the '&lt;' and '&gt;' symbols that markdown-it uses to escape '<' and '>'
    const cleanedContent = textContent.replace(/&lt;|&gt;/g, '');
    const slugifiedHeading = (0, slugify_1.default)(cleanedContent, { decamelize: false });
    let headerId = slugifiedHeading;
    if (!addHeaderCount) {
        node.attribs.id = headerId;
        return;
    }
    const { headerIdMap } = config;
    if (headerIdMap[slugifiedHeading]) {
        headerId = `${slugifiedHeading}-${headerIdMap[slugifiedHeading]}`;
        headerIdMap[slugifiedHeading] += 1;
    }
    else {
        headerIdMap[slugifiedHeading] = 2;
    }
    node.attribs.id = headerId;
}
/**
 * Traverses the dom breadth-first from the specified element to find a html heading child.
 * @param node Root element to search from
 * @returns  The header element, or undefined if none is found.
 */
function _findHeaderElement(node) {
    const elements = node.children;
    if (!elements || !elements.length) {
        return undefined;
    }
    const elementQueue = elements.slice(0);
    while (elementQueue.length) {
        const nextEl = elementQueue.shift();
        if ((nextEl === null || nextEl === void 0 ? void 0 : nextEl.name) && (/^h[1-6]$/).test(nextEl.name)) {
            return nextEl;
        }
        if (nextEl === null || nextEl === void 0 ? void 0 : nextEl.children) {
            nextEl.children.forEach(child => elementQueue.push(child));
        }
    }
    return undefined;
}
/**
 * Assigns an id to the root element of a panel component using the heading specified in the
 * panel's header slot or attribute (if any), with the header slot having priority if present.
 * This is to ensure anchors still work when panels are in their minimized form.
 * @param node The root panel element
 */
function assignPanelId(node) {
    const slotChildren = node.children
        ? node.children.filter(child => (0, vueSlotSyntaxProcessor_1.getVslotShorthandName)(child) !== '')
        : [];
    const headerSlot = slotChildren.find(child => (0, vueSlotSyntaxProcessor_1.getVslotShorthandName)(child) === 'header');
    if (headerSlot) {
        const header = _findHeaderElement(headerSlot);
        if (!header) {
            return;
        }
        if (!header.attribs || !_.has(header.attribs, 'id')) {
            throw new Error('Found a panel heading without an assigned id.\n'
                + 'Please report this to the MarkBind developers. Thank you!');
        }
        node.attribs.panelId = header.attribs.id;
    }
}
//# sourceMappingURL=headerProcessor.js.map