anchor: add option to scroll into view #886

This commit is contained in:
Sören Weber 2024-08-22 18:33:27 +02:00
parent de438327bc
commit efa0a93fb7
No known key found for this signature in database
GPG key ID: BEC6D55545451B6D
5 changed files with 81 additions and 17 deletions

View file

@ -265,6 +265,20 @@ disableRootBreadcrumb = true
# pages. Only the page title will then be shown on the term pages.
disableTermBreadcrumbs = false
# Disable copying heading links to clipboard
# Default: false
# If set to true, this disables the copying of anchor links to the clipboard;
# if also `disableAnchorScrolling=true` then no anchor link will be visible
# when hovering a heading.
disableAnchorCopy = false
# Disable scrolling to heading link on click
# Default: false
# If set to true, this disables the scrolling to the beginning of the heading
# when clicked; if also `disableAnchorCopy=true` then no anchor link will
# be visible when hovering a heading.
disableAnchorScrolling = false
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# Highlight
# These options configure how code is displayed.

View file

@ -168,6 +168,26 @@ If you are unhappy with the default, you can define the following CSS variable i
}
````
## Change Heading Anchor Behavior
Each heading may have an anchor link that is displayed when the heading is hovered.
The behavior what should happen if the anchor icon is clicked is configurable in your `hugo.toml`. By default all options are activated. If you deactivate all options, no link will be shown on hover.
{{< multiconfig file=hugo >}}
[params]
disableAnchorCopy = false
disableAnchorScrolling = false
{{< /multiconfig >}}
### `disableAnchorCopy`
If set to `true`, this disables the copying of anchor links to the clipboard.
### `disableAnchorScrolling`
If set to `true`, this disables the scrolling to the beginning of the heading when clicked.
## Own Shortcodes with JavaScript Dependencies
Certain shortcodes make use of additional dependencies like JavaScript and CSS files. The theme only loads these dependencies if the shortcode is used. To do so correctly the theme adds management code in various files.

View file

@ -20,6 +20,12 @@ This document shows you what's new in the latest release and flags it with one o
## 6.2.0.beta (XXXX-XX-XX) {#620}
- {{% badge style="note" title=" " %}}Change{{% /badge %}} The heading anchor links are extended in functionality.
If you now click on it, not only is the link copied to the clipboard (previous behavior) but also the heading scrolls to the top of the page.
If you dislike the new behavior, you can deactivate it by setting `disableAnchorScrolling=true` in your `hugo.toml`. See the [docs for further options](basics/customization#change-heading-anchor-behavior).
- {{% badge style="info" icon="plus-circle" title=" " %}}New{{% /badge %}} If you are running Hugo {{% badge color="fuchsia" icon="fa-fw fab fa-hackerrank" title=" " %}}0.132.0{{% /badge %}} or later, the theme is now capable to print [GitHub styled alerts](cont/markdown#alerts).
- {{% badge style="info" icon="plus-circle" title=" " %}}New{{% /badge %}} To support new severity levels for GitHub styled alerts, all shortcodes that support severity levels with their `style` parameter were expanded with the new severities `caution` and `important` and the `color` parameter was expanded with `cyan` and `magenta`. Please note, that coloring and icons of severities may defer from the [display you see on GitHub](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts).

View file

@ -30,6 +30,8 @@
window.relearn.relBasePath='{{ partial "relBasePath.hugo" $page | safeJS }}';
window.relearn.relBaseUri='{{ partial "relBaseUri.hugo" $page | safeJS }}';
window.relearn.absBaseUri='{{ replaceRE "/*$" "" .Site.BaseURL | safeJS }}';
window.relearn.disableAnchorCopy={{ printf "%t" (eq .Site.Params.disableAnchorCopy true) | safeJS }};
window.relearn.disableAnchorScrolling={{ printf "%t" (eq .Site.Params.disableAnchorScrolling true) | safeJS }};
{{- with .Site.Home.OutputFormats.Get "search" }}
window.index_js_url={{ (printf "index.search.js%s" $assetBusting) | relLangURL }};
{{- end }}

View file

@ -528,18 +528,25 @@ function initOpenapi( update, attrs ){
}
function initAnchorClipboard(){
if( window.relearn.disableAnchorCopy && window.relearn.disableAnchorScrolling ){
return;
}
document.querySelectorAll( 'h1~h2,h1~h3,h1~h4,h1~h5,h1~h6').forEach( function( element ){
var url = encodeURI( (document.location.origin == "null" ? (document.location.protocol + "//" + document.location.host) : document.location.origin )+ document.location.pathname);
var link = url + "#" + element.id;
var new_element = document.createElement( 'span' );
new_element.classList.add( 'anchor' );
if( !window.relearn.disableAnchorCopy ){
new_element.setAttribute( 'title', window.T_Copy_link_to_clipboard );
}
new_element.setAttribute( 'data-clipboard-text', link );
new_element.innerHTML = '<i class="fas fa-link fa-lg"></i>';
element.appendChild( new_element );
});
var anchors = document.querySelectorAll( '.anchor' );
if( !window.relearn.disableAnchorCopy ){
for( var i = 0; i < anchors.length; i++ ) {
anchors[i].addEventListener( 'mouseleave', function( e ){
this.removeAttribute( 'aria-label' );
@ -552,7 +559,24 @@ function initAnchorClipboard(){
e.clearSelection();
e.trigger.setAttribute( 'aria-label', window.T_Link_copied_to_clipboard );
e.trigger.classList.add( 'tooltipped', 'tooltipped-s'+(isRtl?'e':'w') );
if( !window.relearn.disableAnchorScrolling ){
e.trigger.parentElement.scrollIntoView({ behavior: 'smooth' });
var state = window.history.state || {};
state = Object.assign( {}, ( typeof state === 'object' ) ? state : {} );
history.replaceState( {}, '', e.text );
}
});
}
else if ( !window.relearn.disableAnchorScrolling ){
for( var i = 0; i < anchors.length; i++ ) {
anchors[i].addEventListener( 'click', function( e ){
e.target.parentElement.parentElement.scrollIntoView({ behavior: 'smooth' });
var state = window.history.state || {};
state = Object.assign( {}, ( typeof state === 'object' ) ? state : {} );
history.replaceState( {}, '', e.text );
});
}
}
}
function initCodeClipboard(){
@ -1267,7 +1291,7 @@ function scrollToPositions() {
var found = elementContains( search, elc );
var searchedElem = found.length && found[ 0 ];
if( searchedElem ){
searchedElem.scrollIntoView( true );
searchedElem.scrollIntoView();
var scrolledY = window.scrollY;
if( scrolledY ){
window.scroll( 0, scrolledY - 125 );
@ -1281,9 +1305,7 @@ function scrollToPositions() {
try{
var e = document.querySelector( window.location.hash );
if( e && e.scrollIntoView ){
e.scrollIntoView({
block: 'start',
});
e.scrollIntoView();
}
} catch( e ){}
}, 10 );