Skip to main content

Inhaltsverzeichnis im Editor im Kommentarfeld anzeigen

<script>
const generateTOC = () => {
    let out = document.createElement('div');
    out.id = "hack-toc-editor";
    // Bookstack doesn't use h1 inside the editor, only h2-h6
    let list = document.createElement('ul');
    let previousLevel = 2;
    let currentList = list;
    for (const x of tinymce.activeEditor.getBody().querySelectorAll('h2,h3,h4,h5,h6')) {
        // Create our link to content
        let link = document.createElement('a');
        link.setAttribute('data-id', x.id);
        link.textContent = x.textContent;
        link.addEventListener('click', onLinkClicked);
        let li = document.createElement('li');
        li.append(link);


        // Now let's find out where we insert it
        let level = Number(x.tagName.toLowerCase().replace('h', ''));
        // We need to go deeper, let's create new level(s) 
        // Will be triggered only if level > previousLevel
        for(let i = previousLevel; i < level; i++) {
            let newList = document.createElement('ul');
            currentList.append(newList);
            currentList = newList;
        }
        // We need to go back one (or more) level(s)
        // Will be triggered only if level < previousLevel
        for(let i = previousLevel; i > level; i--) {
            currentList = currentList.parentElement;
        }
        // Now, let's append our link at the right place
        currentList.append(li);
        previousLevel = level;
    }
    out.append(list);
    return out;
}
// Add TOC content inside comment sidebar
const populateTOC = () => {
    document.querySelector('.comment-container-compact').append(generateTOC());
}

const scrollToHeader = (id) => {
    // querySelector doesn't work for some ID which contains accentued characters, so use getElementByID which works fine
    tinymce.activeEditor.getDoc().getElementById(id).scrollIntoView();
}
const onLinkClicked = (event) => {
    let id = event.target.getAttribute('data-id');
    scrollToHeader(id);
}
// It's ugly bit it works : just wait until we find tinyMCE to populate ToC !
const checkForTiny = () => {
    if (window?.tinymce?.activeEditor?.getDoc()) {
        populateTOC();
    }
    else {
        setTimeout(checkForTiny, 1000);
    }
}

setTimeout(checkForTiny, 1000);
</script>