补充主题静态资源与归档模板
This commit is contained in:
1 parent
1268a55dd0
commit
3247db7ed1
265 files changed
+59174
No files matched your search
@@ -0,0 +1,163 @@
|
||||
/**
|
||||
* AKSRT Section Navs — Article TOC / Scrollspy
|
||||
*
|
||||
* Auto-generates a table of contents from h1~h4 headings within
|
||||
* [data-nav] content areas. Scrollspy highlights the current section.
|
||||
* Collapsible sub-items when the TOC is tall.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var HEADING_SEL = 'h1, h2, h3, h4';
|
||||
var MIN_HEADINGS = 2;
|
||||
var SCROLL_OFFSET = 105;
|
||||
var MAX_HEIGHT_COLLAPSE = 380;
|
||||
|
||||
function initSectionNavs() {
|
||||
var navContainer = document.querySelector('[data-nav]');
|
||||
if (!navContainer) return;
|
||||
|
||||
var headings = navContainer.querySelectorAll(HEADING_SEL);
|
||||
if (headings.length < MIN_HEADINGS) return;
|
||||
|
||||
var tocContainer = document.querySelector('.posts-nav-lists, .aksrt-section-nav');
|
||||
if (!tocContainer) {
|
||||
tocContainer = document.createElement('nav');
|
||||
tocContainer.className = 'aksrt-section-nav';
|
||||
tocContainer.setAttribute('aria-label', '文章目录');
|
||||
var sidebar = document.querySelector('.content-layout__aside, .sidebar, .widget-area');
|
||||
if (sidebar) {
|
||||
sidebar.insertBefore(tocContainer, sidebar.firstChild);
|
||||
} else {
|
||||
navContainer.parentNode.insertBefore(tocContainer, navContainer);
|
||||
}
|
||||
}
|
||||
|
||||
var list = document.createElement('ul');
|
||||
list.className = 'aksrt-section-nav__list';
|
||||
|
||||
var items = [];
|
||||
headings.forEach(function (heading, i) {
|
||||
if (!heading.id) {
|
||||
heading.id = 'section-nav-' + i;
|
||||
}
|
||||
|
||||
var level = parseInt(heading.tagName.charAt(1), 10);
|
||||
var li = document.createElement('li');
|
||||
li.className = 'aksrt-section-nav__item aksrt-section-nav__item--h' + level;
|
||||
|
||||
var link = document.createElement('a');
|
||||
link.href = '#' + heading.id;
|
||||
link.textContent = heading.textContent.trim();
|
||||
link.className = 'aksrt-section-nav__link';
|
||||
|
||||
link.addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
smoothScrollTo(heading);
|
||||
|
||||
// Expand collapsed panels containing the target
|
||||
var panel = heading.closest('[data-collapse], .collapse');
|
||||
if (panel) {
|
||||
panel.classList.add('show', 'is-open');
|
||||
var readMore = panel.previousElementSibling;
|
||||
if (readMore && readMore.classList.contains('read-more-open')) readMore.click();
|
||||
}
|
||||
});
|
||||
|
||||
li.appendChild(link);
|
||||
list.appendChild(li);
|
||||
items.push({ el: heading, link: link, li: li, level: level });
|
||||
});
|
||||
|
||||
tocContainer.innerHTML = '';
|
||||
tocContainer.appendChild(list);
|
||||
|
||||
// Collapse sub-items if TOC is tall
|
||||
if (tocContainer.scrollHeight > MAX_HEIGHT_COLLAPSE) {
|
||||
collapseSubItems(list, items);
|
||||
}
|
||||
|
||||
// Scrollspy
|
||||
var ticking = false;
|
||||
function onScroll() {
|
||||
if (ticking) return;
|
||||
ticking = true;
|
||||
requestAnimationFrame(function () {
|
||||
ticking = false;
|
||||
var scrollTop = window.pageYOffset + SCROLL_OFFSET;
|
||||
var activeIdx = 0;
|
||||
for (var i = items.length - 1; i >= 0; i--) {
|
||||
if (items[i].el.offsetTop <= scrollTop) {
|
||||
activeIdx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
items.forEach(function (item, idx) {
|
||||
item.link.classList.toggle('is-active', idx === activeIdx);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
window.addEventListener('scroll', onScroll, { passive: true });
|
||||
onScroll();
|
||||
|
||||
// URL hash auto-scroll
|
||||
if (window.location.hash) {
|
||||
var target = document.querySelector(window.location.hash);
|
||||
if (target) setTimeout(function () { smoothScrollTo(target); }, 100);
|
||||
}
|
||||
}
|
||||
|
||||
function smoothScrollTo(el) {
|
||||
if (window.aksrt && aksrt.scrollTopTo) {
|
||||
aksrt.scrollTopTo(el);
|
||||
} else {
|
||||
var top = el.getBoundingClientRect().top + window.pageYOffset - SCROLL_OFFSET;
|
||||
window.scrollTo({ top: Math.max(0, top), behavior: 'smooth' });
|
||||
}
|
||||
}
|
||||
|
||||
function collapseSubItems(list, items) {
|
||||
var parentStack = [];
|
||||
items.forEach(function (item) {
|
||||
while (parentStack.length && parentStack[parentStack.length - 1].level >= item.level) {
|
||||
parentStack.pop();
|
||||
}
|
||||
|
||||
if (item.level >= 3 && parentStack.length) {
|
||||
item.li.classList.add('yc');
|
||||
// Add collapse toggle to parent if not already there
|
||||
var parentLi = parentStack[parentStack.length - 1].li;
|
||||
if (!parentLi.querySelector('.nav-toggle-collapse')) {
|
||||
var toggle = document.createElement('span');
|
||||
toggle.className = 'nav-toggle-collapse';
|
||||
toggle.innerHTML = '<i class="fas fa-chevron-right"></i>';
|
||||
toggle.addEventListener('click', function (e) {
|
||||
e.stopPropagation();
|
||||
toggle.classList.toggle('fa-rotate-90');
|
||||
var next = parentLi.nextElementSibling;
|
||||
while (next && next.classList.contains('yc')) {
|
||||
next.classList.toggle('yc-open');
|
||||
next = next.nextElementSibling;
|
||||
}
|
||||
});
|
||||
parentLi.appendChild(toggle);
|
||||
}
|
||||
}
|
||||
|
||||
parentStack.push(item);
|
||||
});
|
||||
}
|
||||
|
||||
if (window.AksrtFrontend) {
|
||||
AksrtFrontend.register('aksrt-section-navs', function () { initSectionNavs(); });
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', initSectionNavs);
|
||||
} else {
|
||||
initSectionNavs();
|
||||
}
|
||||
})();
|
||||
Reference in new issue
Block a user