@abreen/tada 1.15.4 → 1.15.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/hash-target.ts +29 -0
- package/src/index.ts +2 -5
- package/src/navigate/index.ts +8 -7
package/package.json
CHANGED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* markdown-it-anchor's slugifier uses encodeURIComponent() so generated
|
|
3
|
+
* heading IDs can safely be used as URL hashes.
|
|
4
|
+
*
|
|
5
|
+
* Tada also allows raw HTML, so an author can create a decoded ID like
|
|
6
|
+
* <h2 id="hello world">Hello</h2>. A link to that target becomes
|
|
7
|
+
* #hello%20world, and getElementById('hello%20world') would not find it.
|
|
8
|
+
*/
|
|
9
|
+
export function getHashTarget(
|
|
10
|
+
document: Document,
|
|
11
|
+
hash: string,
|
|
12
|
+
): HTMLElement | null {
|
|
13
|
+
const id = hash.slice(1);
|
|
14
|
+
if (!id) {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const rawTarget = document.getElementById(id);
|
|
19
|
+
if (rawTarget) {
|
|
20
|
+
return rawTarget;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
const decodedId = decodeURIComponent(id);
|
|
25
|
+
return decodedId === id ? null : document.getElementById(decodedId);
|
|
26
|
+
} catch {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -21,6 +21,7 @@ import mountTop from './top';
|
|
|
21
21
|
import mountNavigate from './navigate';
|
|
22
22
|
import mountPageUpdate from './page-update';
|
|
23
23
|
import { mountPerPageComponents } from './navigate/lifecycle';
|
|
24
|
+
import { getHashTarget } from './hash-target';
|
|
24
25
|
|
|
25
26
|
import { scheduleTask, formatDuration } from './util';
|
|
26
27
|
|
|
@@ -68,11 +69,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|
|
68
69
|
// finished mutating the DOM. On a fresh cold load the browser already
|
|
69
70
|
// scrolled, so this is a harmless re-align.
|
|
70
71
|
if (window.location.hash) {
|
|
71
|
-
|
|
72
|
-
const el = window.document.getElementById(id);
|
|
73
|
-
if (el) {
|
|
74
|
-
el.scrollIntoView();
|
|
75
|
-
}
|
|
72
|
+
getHashTarget(window.document, window.location.hash)?.scrollIntoView();
|
|
76
73
|
}
|
|
77
74
|
|
|
78
75
|
for (const [name, reason] of Object.entries(failed)) {
|
package/src/navigate/index.ts
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
setHistoryIndex,
|
|
14
14
|
} from './runtime';
|
|
15
15
|
import { globals } from '../globals';
|
|
16
|
+
import { getHashTarget } from '../hash-target';
|
|
16
17
|
|
|
17
18
|
function findAnchor(event: MouseEvent): HTMLAnchorElement | null {
|
|
18
19
|
const target = event.target as HTMLElement | null;
|
|
@@ -78,7 +79,11 @@ export default function mountNavigate(window: Window): () => void {
|
|
|
78
79
|
clearSearch(window.document);
|
|
79
80
|
closeHeaderDetails(window.document);
|
|
80
81
|
if (url.hash) {
|
|
81
|
-
|
|
82
|
+
if (url.hash === window.location.hash) {
|
|
83
|
+
getHashTarget(window.document, url.hash)?.scrollIntoView();
|
|
84
|
+
} else {
|
|
85
|
+
globals.setLocationHash(window, url.hash);
|
|
86
|
+
}
|
|
82
87
|
}
|
|
83
88
|
return;
|
|
84
89
|
}
|
|
@@ -112,12 +117,8 @@ export default function mountNavigate(window: Window): () => void {
|
|
|
112
117
|
}
|
|
113
118
|
|
|
114
119
|
// Same page, different hash: fall back to the fragment target
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
const el = window.document.getElementById(hash);
|
|
118
|
-
if (el) {
|
|
119
|
-
el.scrollIntoView();
|
|
120
|
-
}
|
|
120
|
+
if (window.location.hash) {
|
|
121
|
+
getHashTarget(window.document, window.location.hash)?.scrollIntoView();
|
|
121
122
|
} else {
|
|
122
123
|
window.scrollTo({ top: 0 });
|
|
123
124
|
}
|