-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathutils.js
109 lines (88 loc) · 3 KB
/
utils.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
export async function getPageContent(url) {
// This is a really scrappy way to do this.
// Don't do this in production!
const response = await fetch(url);
const text = await response.text();
// Particularly as it uses regexp
return /<body[^>]*>([\w\W]*)<\/body>/.exec(text)[1];
}
function isBackNavigation(navigateEvent) {
if (navigateEvent.navigationType === 'push' || navigateEvent.navigationType === 'replace') {
return false;
}
if (
navigateEvent.destination.index !== -1 &&
navigateEvent.destination.index < navigation.currentEntry.index
) {
return true;
}
return false;
}
// Intercept navigations
// https://developer.chrome.com/docs/web-platform/navigation-api/
// This is a naive usage of the navigation API, to keep things simple.
export async function onLinkNavigate(callback) {
// Ok, here's an even shittier version just to get things working in Safari
if (!self.navigation) {
document.addEventListener('click', (event) => {
const link = event.target.closest('a');
if (!link) return;
event.preventDefault();
const toUrl = new URL(link.href);
callback({
toPath: toUrl.pathname,
fromPath: location.pathname,
isBack: false,
});
history.pushState({}, null, toUrl.pathname);
});
return;
}
navigation.addEventListener('navigate', (event) => {
const toUrl = new URL(event.destination.url);
if (location.origin !== toUrl.origin) return;
const fromPath = location.pathname;
const isBack = isBackNavigation(event);
event.intercept({
async handler() {
if (event.info === 'ignore') return;
await callback({
toPath: toUrl.pathname,
fromPath,
isBack,
});
},
});
});
}
export function getLink(href) {
const fullLink = new URL(href, location.href).href;
return [...document.querySelectorAll('a')].find((link) =>
link.href === fullLink
);
}
// This helper function returns a View-Transition-like object, even for browsers that don't support view transitions.
// It won't do the transition in unsupported browsers, it'll act as if the transition is skipped.
// It also makes it easier to add class names to the document element.
export function transitionHelper({
skipTransition = false,
classNames = '',
updateDOM,
}) {
if (skipTransition || !document.startViewTransition) {
const updateCallbackDone = Promise.resolve(updateDOM()).then(() => undefined);
return {
ready: Promise.reject(Error('View transitions unsupported')),
domUpdated: updateCallbackDone,
updateCallbackDone,
finished: updateCallbackDone,
};
}
const classNamesArray = classNames.split(/\s+/g).filter(Boolean);
document.documentElement.classList.add(...classNamesArray);
const transition = document.startViewTransition(updateDOM);
transition.finished.finally(() =>
document.documentElement.classList.remove(...classNamesArray)
);
return transition;
}