Source: utils/template/enhanceHTML.js

import { addCopyButton, addExpansionButton } from "../../ui/table/Utils.js";

/**
 * Apply default enhancements to html generated from resolved Templates
 * 
 * @param {HTMLElement} element 
 * @param {object} options 
 * 
 * @memberof vef.utils.template
 * @returns {HTMLElement} edited element
 */
export function enhanceHTML(element, options) {

    options = Object.assign({
        tables: true,
        css: true,
        targetBlank: true,
        groupedHeadlines: true
    }, options || {});

    // Add default css
    if (options.css) element.classList.add("template-ui");

    // add target _blank to links
    if (options.targetBlank) {
        const links = element.querySelectorAll("a");
        for (let i = 0; i < links.length; ++i) {
            links[i].target = "_blank";
        }
    }

    // extend tables
    if (options.tables) {
        const tables = element.querySelectorAll("table");
        tables.forEach(enhanceTable)
    }

    if (options.groupedHeadlines) groupHeadlines(element);

    return element;
}

export function enhanceTable(table) {
    // remove header if empty
    const th = table.querySelectorAll("thead th");
    let empty = true;
    for (let i = 0; i < th.length; ++i) {
        if (th[i].innerText.trim().length > 0) {
            headerEmpty = false;
            break;
        }
    }
    if (empty) table.querySelector("thead").remove();

    // add more extensions if the table has two columns
    const rows = table.querySelectorAll("tbody tr");
    if (rows.length > 0 && (rows[0].children.length == 2)) {

        // remove rows with an empty second column
        for (let i = 0; i < rows.length; ++i) {
            const row = rows[i];
            if (row.children[1].innerText.trim().length == 0 && !row.children[1].querySelector('[data-config-remove-empty-column="false"]')) {
                row.remove();
            } else {
                row.children[0].title = row.children[0].innerText;
                row.children[1].title = row.children[1].innerText;
            }
        }

        // remove table and h3 if the table is empty
        const tbody = table.querySelector("tbody");
        if (tbody.children.length == 0) {
            if (table.previousElementSibling.nodeName == "H3") table.previousElementSibling.remove();
            table.remove();
        } else {
            // add default css for metadata tables
            table.classList.add("metadata-table", "ellipsis");

            // add button features
            addCopyButton(table);
            addExpansionButton(table);
        }
    }
}

let previousGroups = null;
export function addCollapsingGroup(header, group, smallHeading) {
    // restore previous collapsed state
    let collapsed = smallHeading || header.classList.contains("collapsed");
    if (previousGroups) {
        const found = previousGroups.find(item => (item.header && (item.header.innerText.toLowerCase().trim() == header.innerText.toLowerCase().trim())));
        if (found) collapsed = (found.group.style.display == "none");
    }
    const i = document.createElement("i");
    i.style = "margin-right: 5px; width: 10px; text-align: center;";
    i.classList.add("fas", (collapsed) ? "fa-caret-right" : "fa-caret-down");
    if (collapsed) group.style.display = "none";
    header.insertAdjacentElement("afterbegin", i);
    header.onclick = () => {
        if (group.style.display == "none") {
            group.style.display = "block";
            i.classList.remove("fa-caret-right");
            i.classList.add("fa-caret-down");
        } else {
            group.style.display = "none";
            i.classList.remove("fa-caret-down");
            i.classList.add("fa-caret-right");
        }
    }
}

export function groupHeadlines(element) {
    const groups = [];
    const elements = Array.from(element.children);

    const headerNames = ["H1", "H2", "H3", "H4", "H5", "H6"];

    let currentGroup = null;
    for (let i = 0; i < elements.length; ++i) {
        const el = elements[i];
        const isHeadline = headerNames.includes(el.nodeName);
        if (isHeadline || (groups.length == 0)) {
            const smallHeading = headerNames.indexOf(el.nodeName) > 2
            const group = document.createElement("div");
            if (isHeadline) group.classList.add("grouped-content");
            el.insertAdjacentElement("afterend", group);
            if (isHeadline) {
                addCollapsingGroup(el, group, smallHeading);
            } else {
                group.appendChild(el);
            }
            currentGroup = {
                header: (isHeadline) ? el : null,
                group: group
            };
            groups.push(currentGroup);
        } else {
            currentGroup.group.appendChild(el);
        }
    }

    // remove empty groups
    for (let i = groups.length - 1; i >= 0; --i) {
        if (groups[i]?.group.innerText.trim() == "" && groups[i]?.group.querySelectorAll("table, img, video, .vef-plot, span[class^='icon'], .image-wrapper, .video").length == 0) {
            groups[i].group.remove()
            if (groups[i].header) groups[i].header.remove()
            groups.splice(i, 1)
            continue;
        }
    }

    for (let i = groups.length - 2; i >= 0; --i) {
        if (groups[i].header && groups[i + 1].header && (headerNames.indexOf(groups[i].header.nodeName) < headerNames.indexOf(groups[i + 1].header.nodeName))) {
            groups[i].group.appendChild(groups[i + 1].header);
            groups[i].group.appendChild(groups[i + 1].group);
        }
    }

    previousGroups = groups;

    return element;
}