1
1
import { svg } from '../svg.js' ;
2
2
3
+ const addPrefix = ( str ) => `user-content-${ str } ` ;
4
+ const removePrefix = ( str ) => str . replace ( / ^ u s e r - c o n t e n t - / , '' ) ;
5
+ const hasPrefix = ( str ) => str . startsWith ( 'user-content-' ) ;
6
+
3
7
// scroll to anchor while respecting the `user-content` prefix that exists on the target
4
- function scrollToAnchor ( encodedId , initial ) {
5
- // abort if the browser has already scrolled to another anchor during page load
6
- if ( ! encodedId || ( initial && document . querySelector ( ':target' ) ) ) return ;
8
+ function scrollToAnchor ( encodedId ) {
9
+ if ( ! encodedId ) return ;
7
10
const id = decodeURIComponent ( encodedId ) ;
8
- let el = document . getElementById ( `user-content-${ id } ` ) ;
11
+ const prefixedId = addPrefix ( id ) ;
12
+ let el = document . getElementById ( prefixedId ) ;
9
13
10
14
// check for matching user-generated `a[name]`
11
15
if ( ! el ) {
12
- const nameAnchors = document . getElementsByName ( `user-content- ${ id } ` ) ;
16
+ const nameAnchors = document . getElementsByName ( prefixedId ) ;
13
17
if ( nameAnchors . length ) {
14
18
el = nameAnchors [ 0 ] ;
15
19
}
16
20
}
17
21
18
22
// compat for links with old 'user-content-' prefixed hashes
19
- if ( ! el && id . startsWith ( 'user-content-' ) ) {
20
- const el = document . getElementById ( id ) ;
21
- if ( el ) el . scrollIntoView ( ) ;
23
+ if ( ! el && hasPrefix ( id ) ) {
24
+ return document . getElementById ( id ) ?. scrollIntoView ( ) ;
22
25
}
23
26
24
- if ( el ) {
25
- el . scrollIntoView ( ) ;
26
- }
27
+ el ?. scrollIntoView ( ) ;
27
28
}
28
29
29
30
export function initMarkupAnchors ( ) {
@@ -32,11 +33,10 @@ export function initMarkupAnchors() {
32
33
33
34
for ( const markupEl of markupEls ) {
34
35
// create link icons for markup headings, the resulting link href will remove `user-content-`
35
- for ( const heading of markupEl . querySelectorAll ( `:is(h1, h2, h3, h4, h5, h6` ) ) {
36
- const originalId = heading . id . replace ( / ^ u s e r - c o n t e n t - / , '' ) ;
36
+ for ( const heading of markupEl . querySelectorAll ( 'h1, h2, h3, h4, h5, h6' ) ) {
37
37
const a = document . createElement ( 'a' ) ;
38
38
a . classList . add ( 'anchor' ) ;
39
- a . setAttribute ( 'href' , `#${ encodeURIComponent ( originalId ) } ` ) ;
39
+ a . setAttribute ( 'href' , `#${ encodeURIComponent ( removePrefix ( heading . id ) ) } ` ) ;
40
40
a . innerHTML = svg ( 'octicon-link' ) ;
41
41
heading . prepend ( a ) ;
42
42
}
@@ -45,24 +45,26 @@ export function initMarkupAnchors() {
45
45
for ( const a of markupEl . querySelectorAll ( 'a[href^="#"]' ) ) {
46
46
const href = a . getAttribute ( 'href' ) ;
47
47
if ( ! href . startsWith ( '#user-content-' ) ) continue ;
48
- const originalId = href . replace ( / ^ # u s e r - c o n t e n t - / , '' ) ;
49
- a . setAttribute ( 'href' , `#${ originalId } ` ) ;
48
+ a . setAttribute ( 'href' , `#${ removePrefix ( href . substring ( 1 ) ) } ` ) ;
50
49
}
51
50
52
51
// add `user-content-` prefix to user-generated `a[name]` link targets
53
52
// TODO: this prefix should be added in backend instead
54
53
for ( const a of markupEl . querySelectorAll ( 'a[name]' ) ) {
55
54
const name = a . getAttribute ( 'name' ) ;
56
55
if ( ! name ) continue ;
57
- a . setAttribute ( 'name' , `user-content- ${ a . name } ` ) ;
56
+ a . setAttribute ( 'name' , addPrefix ( a . name ) ) ;
58
57
}
59
58
60
59
for ( const a of markupEl . querySelectorAll ( 'a[href^="#"]' ) ) {
61
60
a . addEventListener ( 'click' , ( e ) => {
62
- scrollToAnchor ( e . currentTarget . getAttribute ( 'href' ) ?. substring ( 1 ) , false ) ;
61
+ scrollToAnchor ( e . currentTarget . getAttribute ( 'href' ) ?. substring ( 1 ) ) ;
63
62
} ) ;
64
63
}
65
64
}
66
65
67
- scrollToAnchor ( window . location . hash . substring ( 1 ) , true ) ;
66
+ // scroll to anchor unless the browser has already scrolled somewhere during page load
67
+ if ( ! document . querySelector ( ':target' ) ) {
68
+ scrollToAnchor ( window . location . hash ?. substring ( 1 ) ) ;
69
+ }
68
70
}
0 commit comments