diff --git a/www/static/dergstyle.css b/www/static/dergstyle.css index a162d9b..96b3726 100644 --- a/www/static/dergstyle.css +++ b/www/static/dergstyle.css @@ -165,8 +165,11 @@ a:hover { margin-right: 2rem; } -:target { - scroll-margin-top: 6rem; +:target, html, body { + scroll-margin-top: 140px; +} +:target { + outline: 1px solid var(--highlight_1); } #main_content_flexbox { diff --git a/www/static/styles/toc.css b/www/static/styles/toc.css index 795befd..ecbb9bf 100644 --- a/www/static/styles/toc.css +++ b/www/static/styles/toc.css @@ -37,7 +37,7 @@ color: var(--toc-fg) !important; } - & .active { + & .active > a { background-color: var(--toc-bg); border-bottom: 1px solid var(--highlight_1); @@ -57,4 +57,11 @@ margin-bottom: 0.2em; transition: all 1s; } + + & .toc_collapsing { + display: none; + } + & li:is(:has(.active),.active) > ol > .toc_collapsing { + display: block; + } } \ No newline at end of file diff --git a/www/static/toc.js b/www/static/toc.js index 2428898..66aeb36 100644 --- a/www/static/toc.js +++ b/www/static/toc.js @@ -7,7 +7,7 @@ let tocId = "toc"; const TOC_IDENTIFIER = "toc"; const TOC_MAIN_CONTENT_ID = "#content_article" -const TOC_TOP_PIXEL_MARGIN = 300; +const TOC_TOP_PIXEL_MARGIN = 150; class TocTracker { known_heading_elements = []; @@ -49,14 +49,25 @@ class TocTracker { throw Error("A `main` tag section is required to query headings from."); } - let headings = main.querySelectorAll("h1, h2, h3, h4, h5, h6"); + let headings = main.querySelectorAll("h1, h2, h3, h4, h5, h6, li strong"); headings.forEach((heading, index) => { - const heading_level = parseInt(heading.tagName.slice(-1)); + let heading_level = parseInt(heading.tagName.slice(-1)); + let heading_collapsed = false; + + let heading_name = heading.innerHTML; + + if(heading.tagName == 'STRONG') { + heading_level = -1; + heading_collapsed = true; + + heading = heading.closest('li'); + } this.known_heading_elements.push({ level: heading_level, - name: heading.innerHTML, + name: heading_name, dom: heading, + collapse: heading_collapsed }); }); } @@ -65,6 +76,23 @@ class TocTracker { this.known_heading_elements.sort((a, b) => { return a.dom.getBoundingClientRect().y - b.dom.getBoundingClientRect().y; + }); + + let lastHeadingLevel = 0; + this.known_heading_elements.forEach((element) => { + if(element.level == -1) { + let extra_depth = 0; + let current_dom = element.dom; + while(current_dom.tagName != 'ARTICLE') { + if((current_dom.tagName == 'OL') || (current_dom.tagName == 'UL')) + extra_depth += 1; + + current_dom = current_dom.parentElement.closest('ol,ul,article'); + } + element.level = lastHeadingLevel+extra_depth; + } + else + lastHeadingLevel = element.level; }); } @@ -192,7 +220,7 @@ class TocNavBarUpdater { let newNode = document.createElement('li'); const pathURL = location.pathname + '#' + pathItem.id + location.search; - newNode.innerHTML = " #" + pathItem.level + '' + pathItem.name + '' + newNode.innerHTML = " #" + pathItem.level + '' + pathItem.name + '' this.navbar_dom.appendChild(newNode); this.added_navbar_elements.push(newNode); @@ -224,17 +252,37 @@ class TocSidemenu { } _generateSidebar() { - this.toc_tracker.known_heading_elements.forEach(element => { - let new_element = document.createElement('li'); + let toc_stack = [this.sidebar_dom]; + let last_added_li = null; + this.toc_tracker.known_heading_elements.forEach(element => { + while(element.level > toc_stack.length) { + if(!last_added_li) { + last_added_li = document.createElement('li'); + toc_stack[toc_stack.length-1].appendChild(last_added_li); + } + + let new_ol = document.createElement('ol'); + last_added_li.appendChild(new_ol); + last_added_li = false; + toc_stack.push(new_ol); + } + while(element.level < toc_stack.length) + toc_stack.pop(); + + + let new_element = document.createElement('li'); + last_added_li = new_element; + const pathURL = location.pathname + '#' + element.id + location.search; - new_element.style = "padding-left: " + element.level * 0.8 + "em"; - new_element.innerHTML = "" + element.name + ""; + new_element.innerHTML = "" + element.name + ""; + if(element.collapse) + new_element.classList.add('toc_collapsing'); this.sidebar_elements[element.id] = new_element; - this.sidebar_dom.appendChild(new_element); + toc_stack[toc_stack.length-1].appendChild(new_element); }); } @@ -251,13 +299,18 @@ class TocSidemenu { if(this.currently_active_entry) { this.currently_active_entry.classList.remove('active'); } + Object.values(this.sidebar_elements).forEach((entry) => entry.classList.remove('contains_active')); let active_entry = this.sidebar_elements[entry.dom.id]; active_entry.classList.add('active'); this.currently_active_entry = active_entry; + + entry.path.forEach((path_piece) => this.sidebar_elements[path_piece.id].classList.add('contains_active')); } } let tracker = new TocTracker(); let navbar_updater = new TocNavBarUpdater(tracker); -let sidebar_updater = new TocSidemenu(tracker); \ No newline at end of file +let sidebar_updater = new TocSidemenu(tracker); + +document.addEventListener('DOMContentLoaded', (event) => tracker.reloadHeadings());