Skip to content

Commit

Permalink
feat: Improve the jump-to-fragment fixup for non-heading targets
Browse files Browse the repository at this point in the history
Router logic was swallowing history entries and not scrolling far enough
for such targets to clear the fixed header.
  • Loading branch information
gibson042 committed Nov 30, 2023
1 parent d637afb commit 8fe8467
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 5 deletions.
55 changes: 50 additions & 5 deletions main/.vuepress/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,57 @@ module.exports = {
}
});
if (location.hash) {
// Re-navigate to the page target once content has loaded.
if (location.hash && location.hash !== '#') {
// Once content has loaded, re-navigate to the page target
// without triggering interfering router/history/scroll logic.
const hash = location.hash;
fixups.set(['main'], _elems => {
const old = location.hash;
location.hash = '';
location.hash = old;
const stopPropagation = evt => {
evt.stopImmediatePropagation();
const props = {};
const proto = Object.getPrototypeOf(evt);
const propSource = proto === Event.prototype ? {} : proto;
for (const name of Object.getOwnPropertyNames(propSource)) {
if (name !== 'constructor') props[name] = evt[name];
}
console.log('suppress', evt.type, { __proto__: evt, ...props });
};
const stopEvents = types => {
const restorers = types.map(type => {
window.addEventListener(type, stopPropagation, true);
return () => window.removeEventListener(type, stopPropagation, true);
});
const passEvents = () => {
// Run and drop references to all restore functions.
while (restorers.length > 0) restorers.pop()();
};
return passEvents;
};
// Navigate to the page itself as a blank slate.
const passStateEvents = stopEvents(['hashchange', 'popstate']);
const passScrollEvents = stopEvents(['scroll']);
location.replace('#');
// Restore state-change events, then navigate back to the target.
passStateEvents();
try {
const target = document.getElementById(decodeURIComponent(hash.slice(1)));
if (target && target.innerHTML.trim() === '') {
document.documentElement.classList.add('scrollingToTarget');
target.scrollIntoView({ behavior: 'instant' });
document.documentElement.classList.remove('scrollingToTarget');
}
} catch (err) {
console.warn(err);
}
location.replace(hash);
// Restore scroll events and create a new history entry to be overridden
// if the initial target lacks a TOC entry to highlight.
passScrollEvents();
history.pushState(null, '', hash);
});
}
Expand Down
4 changes: 4 additions & 0 deletions main/.vuepress/styles/index.styl
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@
}
}

:root.scrollingToTarget {
scroll-padding-top: $navbarHeight;
}

.ag-btn
background-color $accentColor
color $white
Expand Down

0 comments on commit 8fe8467

Please sign in to comment.