That is not a solution for everyone but for us. Most users will use wysiwyg editor. If they choose “heading 1” we let ckeditor translate it to h2. We removed “heading 6” as there is not translation to h7 possible.
Of course users can use the wiki2.0 syntax. But these users are advanced. If they use = heading = they will see something is awkward in the toc and have a look at other articles to compare and to fix it.
We want our wiki as accessible as possible. Therefore we disabled color, background color and font size in the wysiwyg editor. Of course advanced user can do this with wiki syntax. But if they do they should know why.
We are aware that our way written in post #1 has its problems but we want to deal with it. Now we search for a solution to have a good looking toc, not starting with h1 by default. Or we can think of a special styling omitting the first li-dot (representing h1). But this seems to be more problematic to me.
We found a solution which works for us. Maybe someone will get some inspiration.
The XWiki macro TOC is not directly accessible for us to make pretty. By default, the TOC always starts with header 1. However, we only allow headers from H2 in articles in the WYSIWYG editor, since the title of the article is always already H1, which may only exist once. The parameter start=“2” can be passed for the TOC, but it cannot be set as default. Thus the list would always have a nonsensical leading dot for the empty H1 of the article. But this point should disappear.
First of all, the TOC is given an ID so that you can continue working with it. Then an inserted H2 “Table of contents” is added. A frame is drawn around the whole thing for a better delimitation. Also, all list items, which are internal links, are stripped of the link underlines. It is clear that these are links. The mass of links would become very confusing with the many underlines.
Here is the code of the JavaScriptExtension:
// Add id to table of content
function addTocID() {
let lists = document.querySelectorAll("div#xwikicontent ul");
for (let i = 0; i<lists.length; i++) {
if (typeof lists[i].children[0] !== "undefined") {
if (typeof lists[i].children[0].children[0] !== "undefined") {
if (typeof lists[i].children[0].children[0].children[0] !== "undefined") {
if (typeof lists[i].children[0].children[0].children[0].getAttribute("href") !== "undefined" && lists[i].children[0].children[0].children[0].getAttribute("href") !== null) {
if (lists[i].children[0].children[0].children[0].getAttribute("href").startsWith("#H")) {
if (lists[i].getAttribute("id") !== "ndr-toc") {
lists[i].setAttribute("id", "ndr-toc");
}
break;
}
}
}
}
}
};
let listsEditor = document.querySelectorAll("div#xwikicontent div ul li ul");
for (let i = 0; i<listsEditor.length; i++) {
if (typeof listsEditor[i].children[0] !== "undefined") {
if (typeof listsEditor[i].children[0].children[0] !== "undefined") {
if (typeof listsEditor[i].children[0].children[0] !== "undefined") {
if (typeof listsEditor[i].children[0].children[0].getAttribute("href") !== "undefined" && listsEditor[i].children[0].children[0].getAttribute("href") !== null) {
if (listsEditor[i].children[0].children[0].getAttribute("href").startsWith("#H")) {
if (listsEditor[i].getAttribute("id") !== "ndr-toc") {
listsEditor[i].setAttribute("id", "ndr-toc");
}
break;
}
}
}
}
}
};
}
// add header "Table of contents" to toc
function setHeaderToTOC() {
// Check if div-ndr-toc exists and just got called a second time
// NOTE: this whole script only works for the first toc.
if (document.getElementById("div-ndr-toc") !== null) {
return;
}
let toc = document.getElementById("ndr-toc");
if (toc !== null) {
// create wrapper container
let wrapper = document.createElement('div');
wrapper.id = "div-ndr-toc";
// insert wrapper before toc in the DOM tree
toc.parentNode.insertBefore(wrapper, toc);
// move toc into wrapper
wrapper.appendChild(toc);
// insert h2 into wrapper
let tocDiv = document.getElementById("div-ndr-toc");
let header = document.createElement("h2");
let headerText = document.createTextNode("Table of contents");
header.appendChild(headerText);
tocDiv.insertAdjacentElement("afterbegin", header);
}
}
// remove toc's parent li and ul element
// NOTE: the toc macro creates a table of contents starting with H1.
// We have set CKEditor to create H2 as highest headline, so there is
// no H1 in the article, leading to empty ul and li around the actual toc
// resulting in useless bullets. addTocID sets the id "ndr-toc" to
// the actual toc, so we need to remove the tocs parents (ul and li)
function removeTOCsParentLi() {
let toc = document.getElementById("ndr-toc");
if (toc !== null) {
let parent = toc.parentElement;
let fragment = document.createDocumentFragment();
if (parent.tagName === "LI") {
fragment.appendChild(toc);
if (parent.parentNode.tagName === "UL") {
parent.parentNode.parentNode.replaceChild(fragment, parent.parentNode);
}
}
}
}
// NOTE: For some reason the dom updates and this listener does not get called
// I could not figure out what's wrong, so since all functions check if they
// have to add/remove something, I can safely call them twice and add a timeout
// to await the dom updates
document.observe('xwiki:dom:updated', function(event) {
addTocID();
removeTOCsParentLi()
setHeaderToTOC();
setTimeout(function() {
addTocID();
removeTOCsParentLi()
setHeaderToTOC();
}, 500);
});
addTocID();
removeTOCsParentLi()
setHeaderToTOC();
StyleSheetExtension looks like:
/* do not underline all links in toc */
#ndr-toc a {
text-decoration: none !important;
}
/* border around TOC */
#div-ndr-toc {
border: 1px solid #e8e8e8;
border-radius: 4px;
padding: 16px;
padding-bottom: 0;
width: fit-content;
margin-bottom: 20px;
}
/* move heading for table of contents to same height as LI */
#div-ndr-toc h2 {
margin-top: 0;
}