Skip to content

Commit 4b58de5

Browse files
DanielMatiasCarvalhosilverwind
authored andcommitted
Fix user-defined markup links targets (go-gitea#29305)
This seeks to fix the bug reported on issue go-gitea#29196. Cause: ID's with custom characters (- , _ , etc.), were not linking correctly in the Markdown file when rendered in the browser because the ID in the respective destinies would be different than the one in anchor, while for IDs with only letters, the ID would be the same. Fix: It was suggested that to fix this bug, it should more or less like GitHub does it. While in gitea the anchors would be put in HTML like this: ``` <p dir="auto"><a href="#user-content-_toc152597800" rel="nofollow">Review</a></p> <p dir="auto"><a href="#user-content-_toc152597802" rel="nofollow">Staging</a></p> <p dir="auto"><a href="#user-content-_toc152597803" rel="nofollow">Development</a></p> <p dir="auto"><a href="#user-content-_toc152597828" rel="nofollow">Testing</a></p> <p dir="auto"><a href="#user-content-_toc152597829" rel="nofollow">Unit-tests</a></p> ``` In GitHub, the same anchor's href properties would be the same without "user-content-" trailing behind. So my code made sure to change those anchors, so it would not include "user-content-" and then add respective Event Listeners so it would scroll into the supposed places. Fixes: go-gitea#29196 --------- Co-authored-by: silverwind <me@silverwind.io>
1 parent bd7de0c commit 4b58de5

File tree

1 file changed

+15
-0
lines changed

1 file changed

+15
-0
lines changed

web_src/js/markup/anchors.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {svg} from '../svg.js';
22

33
const headingSelector = '.markup h1, .markup h2, .markup h3, .markup h4, .markup h5, .markup h6';
44

5+
// scroll to anchor while respecting the `user-content` prefix that exists on the target
56
function scrollToAnchor(hash, initial) {
67
// abort if the browser has already scrolled to another anchor during page load
78
if (initial && document.querySelector(':target')) return;
@@ -19,6 +20,7 @@ function scrollToAnchor(hash, initial) {
1920
export function initMarkupAnchors() {
2021
if (!document.querySelector('.markup')) return;
2122

23+
// create link icons for markup headings, the resulting link href will remove `user-content-`
2224
for (const heading of document.querySelectorAll(headingSelector)) {
2325
const originalId = heading.id.replace(/^user-content-/, '');
2426
const a = document.createElement('a');
@@ -31,5 +33,18 @@ export function initMarkupAnchors() {
3133
heading.prepend(a);
3234
}
3335

36+
// handle user-defined `name` anchors like `[Link](#link)` linking to `<a name="link"></a>Link`
37+
for (const a of document.querySelectorAll('.markup a[href^="#"]')) {
38+
const href = a.getAttribute('href');
39+
if (!href.startsWith('#user-content-')) continue;
40+
const originalId = href.replace(/^#user-content-/, '');
41+
a.setAttribute('href', `#${encodeURIComponent(originalId)}`);
42+
if (document.getElementsByName(originalId).length !== 1) {
43+
a.addEventListener('click', (e) => {
44+
scrollToAnchor(e.currentTarget.getAttribute('href'), false);
45+
});
46+
}
47+
}
48+
3449
scrollToAnchor(window.location.hash, true);
3550
}

0 commit comments

Comments
 (0)