fix docs table of contents scrolling
This commit is contained in:
parent
94972a0c58
commit
43c06b65c6
1 changed files with 48 additions and 0 deletions
|
|
@ -107,6 +107,43 @@
|
|||
}).join('');
|
||||
}
|
||||
|
||||
// marked no longer guarantees heading ids across versions, and the docs
|
||||
// reader is an internal scroll container. Add stable GitHub-style ids and
|
||||
// handle same-page #toc links by scrolling the reader, not the window.
|
||||
function slugHeading(text) {
|
||||
return String(text || '')
|
||||
.trim()
|
||||
.toLowerCase()
|
||||
.replace(/\s/g, '-')
|
||||
.replace(/[^a-z0-9_-]/g, '');
|
||||
}
|
||||
|
||||
function prepareDocAnchors(body) {
|
||||
if (!body) return;
|
||||
var seen = {};
|
||||
body.querySelectorAll('h1,h2,h3,h4,h5,h6').forEach(function (h) {
|
||||
var base = h.id || slugHeading(h.textContent || '');
|
||||
if (!base) return;
|
||||
var id = base;
|
||||
var n = seen[base] || 0;
|
||||
if (n) id = base + '-' + n;
|
||||
seen[base] = n + 1;
|
||||
h.id = id;
|
||||
});
|
||||
}
|
||||
|
||||
function scrollReaderToHash(hash) {
|
||||
var body = $('docs-reader-body');
|
||||
var reader = $('docs-reader');
|
||||
if (!body || !reader || !hash) return false;
|
||||
var id = String(hash).replace(/^#/, '');
|
||||
if (!id) return false;
|
||||
var target = document.getElementById(id);
|
||||
if (!target || !body.contains(target)) return false;
|
||||
reader.scrollTop = target.offsetTop - body.offsetTop - 8;
|
||||
return true;
|
||||
}
|
||||
|
||||
function loadTree() {
|
||||
if (_treeLoaded) return;
|
||||
fetch('/api/admin/docs/tree', { headers: getAuthHeaders() })
|
||||
|
|
@ -152,6 +189,7 @@
|
|||
return;
|
||||
}
|
||||
body.innerHTML = data.html || '';
|
||||
prepareDocAnchors(body);
|
||||
if (meta) {
|
||||
meta.textContent = relPath + ' • ' + (data.bytes != null ? (data.bytes + ' bytes') : '');
|
||||
}
|
||||
|
|
@ -160,6 +198,7 @@
|
|||
// Scroll content area to top so deep-link readers don't land mid-doc
|
||||
var reader = $('docs-reader');
|
||||
if (reader) reader.scrollTop = 0;
|
||||
if (window.location.hash) setTimeout(function () { scrollReaderToHash(window.location.hash); }, 0);
|
||||
})
|
||||
.catch(function (err) {
|
||||
body.innerHTML = '<p style="color:var(--red);">' + escHtml(err.message || String(err)) + '</p>';
|
||||
|
|
@ -203,6 +242,15 @@
|
|||
arrow.classList.toggle('fa-chevron-right', !willOpen);
|
||||
}
|
||||
persistExpanded();
|
||||
return;
|
||||
}
|
||||
var docLink = e.target.closest('#docs-reader-body a[href^="#"]');
|
||||
if (docLink) {
|
||||
var href = docLink.getAttribute('href');
|
||||
if (href && scrollReaderToHash(href)) {
|
||||
e.preventDefault();
|
||||
try { history.replaceState(null, '', href); } catch (_) { window.location.hash = href; }
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue