vike 0.4.198-commit-77f6a27 → 0.4.199-commit-3be497f
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/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/transpileAndExecuteFile.js +1 -1
- package/dist/cjs/utils/PROJECT_VERSION.js +1 -1
- package/dist/esm/client/client-routing-runtime/history.d.ts +8 -7
- package/dist/esm/client/client-routing-runtime/history.js +65 -46
- package/dist/esm/client/client-routing-runtime/index.d.ts +1 -0
- package/dist/esm/client/client-routing-runtime/index.js +1 -0
- package/dist/esm/client/client-routing-runtime/initClientRouter.js +4 -4
- package/dist/esm/client/client-routing-runtime/initOnPopState.d.ts +29 -0
- package/dist/esm/client/client-routing-runtime/initOnPopState.js +79 -0
- package/dist/esm/client/client-routing-runtime/renderPageClientSide.js +1 -1
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/transpileAndExecuteFile.js +1 -1
- package/dist/esm/utils/PROJECT_VERSION.d.ts +1 -1
- package/dist/esm/utils/PROJECT_VERSION.js +1 -1
- package/dist/esm/utils/projectInfo.d.ts +1 -1
- package/package.json +1 -1
- package/dist/esm/client/client-routing-runtime/onBrowserHistoryNavigation.d.ts +0 -4
- package/dist/esm/client/client-routing-runtime/onBrowserHistoryNavigation.js +0 -63
|
@@ -88,7 +88,7 @@ async function transpileWithEsbuild(filePath, userRootDir, transformImports) {
|
|
|
88
88
|
metafile: true,
|
|
89
89
|
bundle: true
|
|
90
90
|
};
|
|
91
|
-
|
|
91
|
+
const pointerImports = {};
|
|
92
92
|
options.plugins = [
|
|
93
93
|
// Determine whether an import should be:
|
|
94
94
|
// - A pointer import
|
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
export {
|
|
2
|
-
type
|
|
3
|
-
timestamp
|
|
4
|
-
scrollPosition
|
|
5
|
-
triggeredBy
|
|
1
|
+
export { enhanceHistoryState, getHistoryState, pushHistory, type ScrollPosition, saveScrollPosition, monkeyPatchHistoryPushState };
|
|
2
|
+
type StateVikeEnhanced = {
|
|
3
|
+
timestamp: number;
|
|
4
|
+
scrollPosition: null | ScrollPosition;
|
|
5
|
+
triggeredBy: 'user' | 'vike' | 'browser';
|
|
6
6
|
_isVikeEnhanced: true;
|
|
7
7
|
};
|
|
8
8
|
type ScrollPosition = {
|
|
9
9
|
x: number;
|
|
10
10
|
y: number;
|
|
11
11
|
};
|
|
12
|
-
|
|
13
|
-
declare function
|
|
12
|
+
type StateNotInitialized = null | undefined | Partial<StateVikeEnhanced> | StateVikeEnhanced;
|
|
13
|
+
declare function enhanceHistoryState(): void;
|
|
14
|
+
declare function getHistoryState(): StateNotInitialized;
|
|
14
15
|
declare function saveScrollPosition(): void;
|
|
15
16
|
declare function pushHistory(url: string, overwriteLastHistoryEntry: boolean): void;
|
|
16
17
|
declare function monkeyPatchHistoryPushState(): void;
|
|
@@ -1,37 +1,48 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { enhanceHistoryState, getHistoryState, pushHistory, saveScrollPosition, monkeyPatchHistoryPushState };
|
|
2
2
|
import { assert, assertUsage, hasProp, isObject } from './utils.js';
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
3
|
+
// `window.history.state === null` when:
|
|
4
|
+
// - The very first render
|
|
5
|
+
// - Click on `<a href="#some-hash" />`
|
|
6
|
+
// - `location.hash = 'some-hash'`
|
|
7
|
+
function enhanceHistoryState() {
|
|
8
|
+
const stateNotInitialized = window.history.state;
|
|
9
|
+
if (isVikeEnhanced(stateNotInitialized))
|
|
10
|
+
return;
|
|
11
|
+
const stateVikeEnhanced = enhance(stateNotInitialized);
|
|
12
|
+
replaceHistoryState(stateVikeEnhanced);
|
|
13
|
+
}
|
|
14
|
+
function enhance(stateNotInitialized) {
|
|
15
|
+
const timestamp = getTimestamp();
|
|
16
|
+
const scrollPosition = getScrollPosition();
|
|
17
|
+
const triggeredBy = 'browser';
|
|
18
|
+
let stateVikeEnhanced;
|
|
19
|
+
if (!stateNotInitialized) {
|
|
20
|
+
stateVikeEnhanced = {
|
|
21
|
+
timestamp,
|
|
22
|
+
scrollPosition,
|
|
23
|
+
triggeredBy,
|
|
24
|
+
_isVikeEnhanced: true
|
|
25
|
+
};
|
|
26
26
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
else {
|
|
28
|
+
// State information may be incomplete if `window.history.state` is set by an old Vike version. (E.g. `state.timestamp` was introduced for `pageContext.isBackwardNavigation` in `0.4.19`.)
|
|
29
|
+
stateVikeEnhanced = {
|
|
30
|
+
timestamp: stateNotInitialized.timestamp ?? timestamp,
|
|
31
|
+
scrollPosition: stateNotInitialized.scrollPosition ?? scrollPosition,
|
|
32
|
+
triggeredBy: stateNotInitialized.triggeredBy ?? triggeredBy,
|
|
33
|
+
_isVikeEnhanced: true
|
|
34
|
+
};
|
|
30
35
|
}
|
|
36
|
+
assert(isVikeEnhanced(stateVikeEnhanced));
|
|
37
|
+
return stateVikeEnhanced;
|
|
38
|
+
}
|
|
39
|
+
function getState_alreadyEnhanced() {
|
|
40
|
+
const state = getHistoryState();
|
|
41
|
+
assert(isVikeEnhanced(state));
|
|
42
|
+
return state;
|
|
31
43
|
}
|
|
32
44
|
function getHistoryState() {
|
|
33
|
-
const state = window.history.state
|
|
34
|
-
assertState(state);
|
|
45
|
+
const state = window.history.state;
|
|
35
46
|
return state;
|
|
36
47
|
}
|
|
37
48
|
function getScrollPosition() {
|
|
@@ -43,29 +54,22 @@ function getTimestamp() {
|
|
|
43
54
|
}
|
|
44
55
|
function saveScrollPosition() {
|
|
45
56
|
const scrollPosition = getScrollPosition();
|
|
46
|
-
const state =
|
|
57
|
+
const state = getState_alreadyEnhanced();
|
|
47
58
|
replaceHistoryState({ ...state, scrollPosition });
|
|
48
59
|
}
|
|
49
60
|
function pushHistory(url, overwriteLastHistoryEntry) {
|
|
50
61
|
if (!overwriteLastHistoryEntry) {
|
|
51
62
|
const timestamp = getTimestamp();
|
|
52
|
-
pushHistoryState({
|
|
63
|
+
pushHistoryState({
|
|
64
|
+
timestamp,
|
|
65
|
+
// I don't remember why I set it to `null`, maybe because setting it now would be too early? (Maybe there is a delay between renderPageClientSide() is finished and the browser updating the scroll position.) Anyways, it seems like autoSaveScrollPosition() is enough.
|
|
66
|
+
scrollPosition: null,
|
|
67
|
+
triggeredBy: 'vike',
|
|
68
|
+
_isVikeEnhanced: true
|
|
69
|
+
}, url);
|
|
53
70
|
}
|
|
54
71
|
else {
|
|
55
|
-
replaceHistoryState(
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
function assertState(state) {
|
|
59
|
-
assert(isObject(state));
|
|
60
|
-
if ('timestamp' in state) {
|
|
61
|
-
const { timestamp } = state;
|
|
62
|
-
assert(typeof timestamp === 'number');
|
|
63
|
-
}
|
|
64
|
-
if ('scrollPosition' in state) {
|
|
65
|
-
const { scrollPosition } = state;
|
|
66
|
-
if (scrollPosition !== null) {
|
|
67
|
-
assert(hasProp(scrollPosition, 'x', 'number') && hasProp(scrollPosition, 'y', 'number'));
|
|
68
|
-
}
|
|
72
|
+
replaceHistoryState(getState_alreadyEnhanced(), url);
|
|
69
73
|
}
|
|
70
74
|
}
|
|
71
75
|
function replaceHistoryState(state, url) {
|
|
@@ -89,9 +93,24 @@ function monkeyPatchHistoryPushState() {
|
|
|
89
93
|
triggeredBy: 'user',
|
|
90
94
|
...stateOriginal
|
|
91
95
|
};
|
|
96
|
+
assert(isVikeEnhanced(stateEnhanced));
|
|
92
97
|
return pushStateOriginal(stateEnhanced, ...rest);
|
|
93
98
|
};
|
|
94
99
|
}
|
|
95
100
|
function isVikeEnhanced(state) {
|
|
96
|
-
|
|
101
|
+
const yes = isObject(state) && '_isVikeEnhanced' in state;
|
|
102
|
+
if (yes)
|
|
103
|
+
assertStateVikeEnhanced(state);
|
|
104
|
+
return yes;
|
|
105
|
+
}
|
|
106
|
+
function assertStateVikeEnhanced(state) {
|
|
107
|
+
assert(isObject(state));
|
|
108
|
+
assert(hasProp(state, '_isVikeEnhanced', 'true'));
|
|
109
|
+
// TODO/eventually: remove assert() below to save client-side KBs
|
|
110
|
+
assert(hasProp(state, 'timestamp', 'number'));
|
|
111
|
+
assert(hasProp(state, 'scrollPosition'));
|
|
112
|
+
if (state.scrollPosition !== null) {
|
|
113
|
+
assert(hasProp(state, 'scrollPosition', 'object'));
|
|
114
|
+
assert(hasProp(state.scrollPosition, 'x', 'number') && hasProp(state.scrollPosition, 'y', 'number'));
|
|
115
|
+
}
|
|
97
116
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { navigate, reload } from './navigate.js';
|
|
2
2
|
export { prefetch } from './prefetch.js';
|
|
3
|
+
export { onPopState } from './initOnPopState.js';
|
|
3
4
|
export { PROJECT_VERSION as version } from './utils.js';
|
|
4
5
|
import type { PageContextBuiltInClientWithClientRouting } from '../../shared/types.js';
|
|
5
6
|
/** @deprecated
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export { initClientRouter };
|
|
2
2
|
import { assert } from './utils.js';
|
|
3
|
-
import {
|
|
3
|
+
import { enhanceHistoryState, monkeyPatchHistoryPushState } from './history.js';
|
|
4
4
|
import { getRenderCount, renderPageClientSide } from './renderPageClientSide.js';
|
|
5
|
-
import {
|
|
5
|
+
import { initOnPopState } from './initOnPopState.js';
|
|
6
6
|
import { initOnLinkClick } from './initOnLinkClick.js';
|
|
7
7
|
import { setupNativeScrollRestoration } from './scrollRestoration.js';
|
|
8
8
|
import { autoSaveScrollPosition } from './setScrollPosition.js';
|
|
@@ -29,9 +29,9 @@ async function renderFirstPage() {
|
|
|
29
29
|
}
|
|
30
30
|
function initHistoryAndScroll() {
|
|
31
31
|
setupNativeScrollRestoration();
|
|
32
|
-
|
|
32
|
+
enhanceHistoryState();
|
|
33
33
|
autoSaveScrollPosition();
|
|
34
34
|
monkeyPatchHistoryPushState();
|
|
35
35
|
// Handle back-/forward navigation
|
|
36
|
-
|
|
36
|
+
initOnPopState();
|
|
37
37
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export { initOnPopState };
|
|
2
|
+
export { updateState };
|
|
3
|
+
export { onPopState };
|
|
4
|
+
declare function initOnPopState(): void;
|
|
5
|
+
type Listener = (arg: {
|
|
6
|
+
_experimental: {
|
|
7
|
+
previousState: ReturnType<typeof getState>;
|
|
8
|
+
};
|
|
9
|
+
}) => undefined | boolean;
|
|
10
|
+
/** Control client-side navigation.
|
|
11
|
+
*
|
|
12
|
+
* https://vike.dev/onPopState
|
|
13
|
+
*/
|
|
14
|
+
declare function onPopState(listener: Listener): void;
|
|
15
|
+
declare function getState(): {
|
|
16
|
+
urlWithoutHash: string;
|
|
17
|
+
historyState: {
|
|
18
|
+
timestamp: number;
|
|
19
|
+
scrollPosition: null | import("./history.js").ScrollPosition;
|
|
20
|
+
triggeredBy: "user" | "vike" | "browser";
|
|
21
|
+
_isVikeEnhanced: true;
|
|
22
|
+
} | Partial<{
|
|
23
|
+
timestamp: number;
|
|
24
|
+
scrollPosition: null | import("./history.js").ScrollPosition;
|
|
25
|
+
triggeredBy: "user" | "vike" | "browser";
|
|
26
|
+
_isVikeEnhanced: true;
|
|
27
|
+
}> | null | undefined;
|
|
28
|
+
};
|
|
29
|
+
declare function updateState(): void;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
export { initOnPopState };
|
|
2
|
+
export { updateState };
|
|
3
|
+
export { onPopState };
|
|
4
|
+
import { assert, getCurrentUrl, getGlobalObject } from './utils.js';
|
|
5
|
+
import { enhanceHistoryState, getHistoryState } from './history.js';
|
|
6
|
+
import { renderPageClientSide } from './renderPageClientSide.js';
|
|
7
|
+
import { setScrollPosition } from './setScrollPosition.js';
|
|
8
|
+
const globalObject = getGlobalObject('initOnPopState.ts', { previousState: getState(), listeners: [] });
|
|
9
|
+
function initOnPopState() {
|
|
10
|
+
// - The popstate event is trigged upon:
|
|
11
|
+
// - Back-/forward navigation.
|
|
12
|
+
// - By user clicking on his browser's back-/forward navigation (or using a shortcut)
|
|
13
|
+
// - By JavaScript: `history.back()` / `history.forward()`
|
|
14
|
+
// - URL hash change.
|
|
15
|
+
// - Click on `<a href="#some-hash" />`
|
|
16
|
+
// - The popstate event is *only* triggered if `href` starts with '#' (even if `href` is '/#some-hash' while the current URL's pathname is '/' then the popstate still isn't triggered)
|
|
17
|
+
// - `location.hash = 'some-hash'`
|
|
18
|
+
// - The `event` argument of `window.addEventListener('popstate', (event) => /*...*/)` is useless: the History API doesn't provide the previous state (the popped state), see https://stackoverflow.com/questions/48055323/is-history-state-always-the-same-as-popstate-event-state
|
|
19
|
+
window.addEventListener('popstate', async () => {
|
|
20
|
+
const { previousState } = globalObject;
|
|
21
|
+
const currentState = getState();
|
|
22
|
+
globalObject.previousState = currentState;
|
|
23
|
+
const scrollTarget = currentState.historyState?.scrollPosition || undefined;
|
|
24
|
+
const isUserLandPushStateNavigation = currentState.historyState?.triggeredBy === 'user';
|
|
25
|
+
const isHashNavigation = currentState.urlWithoutHash === previousState.urlWithoutHash;
|
|
26
|
+
const isBackwardNavigation = !currentState.historyState?.timestamp || !previousState.historyState?.timestamp
|
|
27
|
+
? null
|
|
28
|
+
: currentState.historyState.timestamp < previousState.historyState.timestamp;
|
|
29
|
+
// - `history.state === null` when:
|
|
30
|
+
// - Click on `<a href="#some-hash" />` (note that Vike's `initOnLinkClick()` handler skips hash links)
|
|
31
|
+
// - `location.hash = 'some-hash'`
|
|
32
|
+
// - `history.state !== null` when `popstate` was triggered by the user clicking on his browser's forward/backward history button.
|
|
33
|
+
let isHashNavigationNew = isHashNavigation && window.history.state === null;
|
|
34
|
+
if (window.history.state === null) {
|
|
35
|
+
assert(isHashNavigation);
|
|
36
|
+
// The browser already scrolled to `#${hash}` => the current scroll position is the right one => we save it with `enhanceHistoryState()`.
|
|
37
|
+
enhanceHistoryState();
|
|
38
|
+
globalObject.previousState = getState();
|
|
39
|
+
}
|
|
40
|
+
// We have to scroll ourselves because we use `window.history.scrollRestoration = 'manual'`. So far this seems to work. Alternatives in case it doesn't work:
|
|
41
|
+
// - Alternative: we use `window.history.scrollRestoration = 'auto'`
|
|
42
|
+
// - Problem: I don't think it's possbible to set `window.history.scrollRestoration = 'auto'` only for hash navigation and not for non-hash navigations?
|
|
43
|
+
// - Problem: inconsistencies between browsers? For example specification says that setting `window.history.scrollRestoration` only affects the current entry in the session history but this contradicts what people are experiencing in practice.
|
|
44
|
+
// - Specification: https://html.spec.whatwg.org/multipage/history.html#the-history-interface
|
|
45
|
+
// - Practice: https://stackoverflow.com/questions/70188241/history-scrollrestoration-manual-doesnt-prevent-safari-from-restoring-scrol
|
|
46
|
+
// - Alternative: we completely take over hash navigation and reproduce the browser's native behavior upon hash navigation.
|
|
47
|
+
// - By using the `hashchange` event.
|
|
48
|
+
// - Problem: conflict if user wants to override the browser's default behavior? E.g. for smooth scrolling, or when using hashes for saving states of some fancy animations.
|
|
49
|
+
if (isHashNavigation && !isUserLandPushStateNavigation) {
|
|
50
|
+
if (!isHashNavigationNew) {
|
|
51
|
+
setScrollPosition(scrollTarget);
|
|
52
|
+
}
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
let abort;
|
|
56
|
+
globalObject.listeners.forEach(listener => {
|
|
57
|
+
abort || (abort = listener({ _experimental: { previousState } }));
|
|
58
|
+
});
|
|
59
|
+
if (abort)
|
|
60
|
+
return;
|
|
61
|
+
await renderPageClientSide({ scrollTarget, isBackwardNavigation, isUserLandPushStateNavigation });
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
/** Control client-side navigation.
|
|
65
|
+
*
|
|
66
|
+
* https://vike.dev/onPopState
|
|
67
|
+
*/
|
|
68
|
+
function onPopState(listener) {
|
|
69
|
+
globalObject.listeners.push(listener);
|
|
70
|
+
}
|
|
71
|
+
function getState() {
|
|
72
|
+
return {
|
|
73
|
+
urlWithoutHash: getCurrentUrl({ withoutHash: true }),
|
|
74
|
+
historyState: getHistoryState()
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
function updateState() {
|
|
78
|
+
globalObject.previousState = getState();
|
|
79
|
+
}
|
|
@@ -15,7 +15,7 @@ import { assertNoInfiniteAbortLoop, getPageContextFromAllRewrites, isAbortError,
|
|
|
15
15
|
import { route } from '../../shared/route/index.js';
|
|
16
16
|
import { isClientSideRoutable } from './isClientSideRoutable.js';
|
|
17
17
|
import { setScrollPosition } from './setScrollPosition.js';
|
|
18
|
-
import { updateState } from './
|
|
18
|
+
import { updateState } from './initOnPopState.js';
|
|
19
19
|
import { browserNativeScrollRestoration_disable, setInitialRenderIsDone } from './scrollRestoration.js';
|
|
20
20
|
import { getErrorPageId } from '../../shared/error-page.js';
|
|
21
21
|
import { setPageContextCurrent } from './getPageContextCurrent.js';
|
|
@@ -83,7 +83,7 @@ async function transpileWithEsbuild(filePath, userRootDir, transformImports) {
|
|
|
83
83
|
metafile: true,
|
|
84
84
|
bundle: true
|
|
85
85
|
};
|
|
86
|
-
|
|
86
|
+
const pointerImports = {};
|
|
87
87
|
options.plugins = [
|
|
88
88
|
// Determine whether an import should be:
|
|
89
89
|
// - A pointer import
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const PROJECT_VERSION: "0.4.
|
|
1
|
+
export declare const PROJECT_VERSION: "0.4.199-commit-3be497f";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Automatically updated by @brillout/release-me
|
|
2
|
-
export const PROJECT_VERSION = '0.4.
|
|
2
|
+
export const PROJECT_VERSION = '0.4.199-commit-3be497f';
|
package/package.json
CHANGED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
export { onBrowserHistoryNavigation };
|
|
2
|
-
export { updateState };
|
|
3
|
-
import { getCurrentUrl, getGlobalObject } from './utils.js';
|
|
4
|
-
import { initHistoryState, getHistoryState } from './history.js';
|
|
5
|
-
import { renderPageClientSide } from './renderPageClientSide.js';
|
|
6
|
-
import { setScrollPosition } from './setScrollPosition.js';
|
|
7
|
-
const globalObject = getGlobalObject('onBrowserHistoryNavigation.ts', { previousState: getState() });
|
|
8
|
-
function onBrowserHistoryNavigation() {
|
|
9
|
-
// - The popstate event is trigged upon:
|
|
10
|
-
// - Back-/forward navigation.
|
|
11
|
-
// - By user clicking on his browser's back-/forward navigation (or using a shortcut)
|
|
12
|
-
// - By JavaScript: `history.back()` / `history.forward()`
|
|
13
|
-
// - URL hash change.
|
|
14
|
-
// - By user clicking on a hash link `<a href="#some-hash" />`
|
|
15
|
-
// - The popstate event is *only* triggered if `href` starts with '#' (even if `href` is '/#some-hash' while the current URL's pathname is '/' then the popstate still isn't triggered)
|
|
16
|
-
// - By JavaScript: `location.hash = 'some-hash'`
|
|
17
|
-
// - The `event` argument of `window.addEventListener('popstate', (event) => /*...*/)` is useless: the History API doesn't provide the previous state (the popped state), see https://stackoverflow.com/questions/48055323/is-history-state-always-the-same-as-popstate-event-state
|
|
18
|
-
window.addEventListener('popstate', async () => {
|
|
19
|
-
const currentState = getState();
|
|
20
|
-
const scrollTarget = currentState.historyState.scrollPosition || undefined;
|
|
21
|
-
const isUserLandPushStateNavigation = currentState.historyState.triggeredBy === 'user';
|
|
22
|
-
const isHashNavigation = currentState.urlWithoutHash === globalObject.previousState.urlWithoutHash;
|
|
23
|
-
const isBackwardNavigation = !currentState.historyState.timestamp || !globalObject.previousState.historyState.timestamp
|
|
24
|
-
? null
|
|
25
|
-
: currentState.historyState.timestamp < globalObject.previousState.historyState.timestamp;
|
|
26
|
-
globalObject.previousState = currentState;
|
|
27
|
-
if (isHashNavigation && !isUserLandPushStateNavigation) {
|
|
28
|
-
// - `history.state` is uninitialized (`null`) when:
|
|
29
|
-
// - The user's code runs `window.location.hash = '#section'`.
|
|
30
|
-
// - The user clicks on an anchor link `<a href="#section">Section</a>` (because Vike's `initOnLinkClick()` handler skips hash links).
|
|
31
|
-
// - `history.state` is `null` when uninitialized: https://developer.mozilla.org/en-US/docs/Web/API/History/state
|
|
32
|
-
// - Alternatively, we completely take over hash navigation and reproduce the browser's native behavior upon hash navigation.
|
|
33
|
-
// - Problem: we cannot intercept `window.location.hash = '#section'`. (Or maybe we can with the `hashchange` event?)
|
|
34
|
-
// - Other potential problem: would there be a conflict when the user wants to override the browser's default behavior? E.g. for smooth scrolling, or when using hashes for saving states of some fancy animations.
|
|
35
|
-
// - Another alternative: we use the browser's scroll restoration mechanism (see `browserNativeScrollRestoration_enable()` below).
|
|
36
|
-
// - Problem: not clear when to call `browserNativeScrollRestoration_disable()`/`browserNativeScrollRestoration_enable()`
|
|
37
|
-
// - Other potential problem are inconsistencies between browsers: specification says that setting `window.history.scrollRestoration` only affects the current entry in the session history. But this seems to contradict what folks saying.
|
|
38
|
-
// - Specification: https://html.spec.whatwg.org/multipage/history.html#the-history-interface
|
|
39
|
-
// - https://stackoverflow.com/questions/70188241/history-scrollrestoration-manual-doesnt-prevent-safari-from-restoring-scrol
|
|
40
|
-
if (window.history.state === null) {
|
|
41
|
-
// The browser already scrolled to `#${hash}` => the current scroll position is the right one => we save it with `initHistoryState()`.
|
|
42
|
-
initHistoryState();
|
|
43
|
-
globalObject.previousState = getState();
|
|
44
|
-
}
|
|
45
|
-
else {
|
|
46
|
-
// If `history.state !== null` then it means that `popstate` was triggered by the user clicking on his browser's forward/backward history button.
|
|
47
|
-
setScrollPosition(scrollTarget);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
else {
|
|
51
|
-
await renderPageClientSide({ scrollTarget, isBackwardNavigation, isUserLandPushStateNavigation });
|
|
52
|
-
}
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
function getState() {
|
|
56
|
-
return {
|
|
57
|
-
urlWithoutHash: getCurrentUrl({ withoutHash: true }),
|
|
58
|
-
historyState: getHistoryState()
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
function updateState() {
|
|
62
|
-
globalObject.previousState = getState();
|
|
63
|
-
}
|