vike 0.4.198 → 0.4.199-commit-6991a96

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.
Files changed (23) hide show
  1. package/dist/cjs/node/plugin/plugins/fileEnv.js +3 -0
  2. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/transpileAndExecuteFile.js +1 -1
  3. package/dist/cjs/utils/PROJECT_VERSION.js +1 -1
  4. package/dist/esm/client/client-routing-runtime/history.d.ts +8 -7
  5. package/dist/esm/client/client-routing-runtime/history.js +65 -46
  6. package/dist/esm/client/client-routing-runtime/index.d.ts +1 -0
  7. package/dist/esm/client/client-routing-runtime/index.js +1 -0
  8. package/dist/esm/client/client-routing-runtime/initClientRouter.js +4 -4
  9. package/dist/esm/client/client-routing-runtime/initOnPopState.d.ts +29 -0
  10. package/dist/esm/client/client-routing-runtime/initOnPopState.js +78 -0
  11. package/dist/esm/client/client-routing-runtime/prefetch.d.ts +1 -2
  12. package/dist/esm/client/client-routing-runtime/prefetch.js +21 -3
  13. package/dist/esm/client/client-routing-runtime/renderPageClientSide.d.ts +0 -2
  14. package/dist/esm/client/client-routing-runtime/renderPageClientSide.js +2 -13
  15. package/dist/esm/node/plugin/plugins/fileEnv.js +3 -0
  16. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/transpileAndExecuteFile.js +1 -1
  17. package/dist/esm/shared/page-configs/Config.d.ts +7 -7
  18. package/dist/esm/utils/PROJECT_VERSION.d.ts +1 -1
  19. package/dist/esm/utils/PROJECT_VERSION.js +1 -1
  20. package/dist/esm/utils/projectInfo.d.ts +1 -1
  21. package/package.json +1 -1
  22. package/dist/esm/client/client-routing-runtime/onBrowserHistoryNavigation.d.ts +0 -4
  23. package/dist/esm/client/client-routing-runtime/onBrowserHistoryNavigation.js +0 -63
@@ -22,6 +22,9 @@ function fileEnv() {
22
22
  return;
23
23
  if (skip(id))
24
24
  return;
25
+ // For `.vue` files: https://github.com/vikejs/vike/issues/1912#issuecomment-2394981475
26
+ if (id.endsWith('?direct'))
27
+ id = id.slice(0, -1 * '?direct'.length);
25
28
  const moduleInfo = viteDevServer.moduleGraph.getModuleById(id);
26
29
  (0, utils_js_1.assert)(moduleInfo);
27
30
  const importers = Array.from(moduleInfo.importers)
@@ -88,7 +88,7 @@ async function transpileWithEsbuild(filePath, userRootDir, transformImports) {
88
88
  metafile: true,
89
89
  bundle: true
90
90
  };
91
- let pointerImports = {};
91
+ const pointerImports = {};
92
92
  options.plugins = [
93
93
  // Determine whether an import should be:
94
94
  // - A pointer import
@@ -2,4 +2,4 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PROJECT_VERSION = void 0;
4
4
  // Automatically updated by @brillout/release-me
5
- exports.PROJECT_VERSION = '0.4.198';
5
+ exports.PROJECT_VERSION = '0.4.199-commit-6991a96';
@@ -1,16 +1,17 @@
1
- export { initHistoryState, getHistoryState, pushHistory, ScrollPosition, saveScrollPosition, monkeyPatchHistoryPushState };
2
- type HistoryState = {
3
- timestamp?: number;
4
- scrollPosition?: null | ScrollPosition;
5
- triggeredBy?: 'user' | 'vike' | 'browser';
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
- declare function initHistoryState(): void;
13
- declare function getHistoryState(): HistoryState;
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 { initHistoryState, getHistoryState, pushHistory, saveScrollPosition, monkeyPatchHistoryPushState };
1
+ export { enhanceHistoryState, getHistoryState, pushHistory, saveScrollPosition, monkeyPatchHistoryPushState };
2
2
  import { assert, assertUsage, hasProp, isObject } from './utils.js';
3
- // Fill missing state information:
4
- // - `history.state` can uninitialized (i.e. `null`):
5
- // - The very first render
6
- // - The user's code runs `location.hash = '#section'`
7
- // - The user clicks on an anchor link `<a href="#section">Section</a>` (Vike's `initOnLinkClick()` handler skips hash links).
8
- // - State information may be incomplete if `history.state` is set by an old Vike version. (E.g. `state.timestamp` was introduced for `pageContext.isBackwardNavigation` in `0.4.19`.)
9
- function initHistoryState() {
10
- // No way found to add TypeScript types to `window.history.state`: https://github.com/microsoft/TypeScript/issues/36178
11
- let state = window.history.state;
12
- if (!state) {
13
- state = { _isVikeEnhanced: true };
14
- }
15
- let hasModifications = false;
16
- if (!('timestamp' in state)) {
17
- hasModifications = true;
18
- state.timestamp = getTimestamp();
19
- }
20
- if (!('scrollPosition' in state)) {
21
- hasModifications = true;
22
- state.scrollPosition = getScrollPosition();
23
- }
24
- if (!('triggeredBy' in state)) {
25
- state.triggeredBy = 'browser';
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
- assertState(state);
28
- if (hasModifications) {
29
- replaceHistoryState(state);
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 = getHistoryState();
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({ timestamp, scrollPosition: null, triggeredBy: 'vike', _isVikeEnhanced: true }, url);
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(getHistoryState(), url);
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
- return isObject(state) && '_isVikeEnhanced' in state;
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
@@ -5,4 +5,5 @@
5
5
  // Use package.json#exports to make the imports isomorphic.
6
6
  export { navigate, reload } from './navigate.js';
7
7
  export { prefetch } from './prefetch.js';
8
+ export { onPopState } from './initOnPopState.js';
8
9
  export { PROJECT_VERSION as version } from './utils.js';
@@ -1,8 +1,8 @@
1
1
  export { initClientRouter };
2
2
  import { assert } from './utils.js';
3
- import { initHistoryState, monkeyPatchHistoryPushState } from './history.js';
3
+ import { enhanceHistoryState, monkeyPatchHistoryPushState } from './history.js';
4
4
  import { getRenderCount, renderPageClientSide } from './renderPageClientSide.js';
5
- import { onBrowserHistoryNavigation } from './onBrowserHistoryNavigation.js';
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
- initHistoryState();
32
+ enhanceHistoryState();
33
33
  autoSaveScrollPosition();
34
34
  monkeyPatchHistoryPushState();
35
35
  // Handle back-/forward navigation
36
- onBrowserHistoryNavigation();
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,78 @@
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 isHashNavigation = currentState.urlWithoutHash === previousState.urlWithoutHash;
25
+ const isBackwardNavigation = !currentState.historyState?.timestamp || !previousState.historyState?.timestamp
26
+ ? null
27
+ : currentState.historyState.timestamp < previousState.historyState.timestamp;
28
+ // - `history.state === null` when:
29
+ // - Click on `<a href="#some-hash" />` (note that Vike's `initOnLinkClick()` handler skips hash links)
30
+ // - `location.hash = 'some-hash'`
31
+ // - `history.state !== null` when `popstate` was triggered by the user clicking on his browser's forward/backward history button.
32
+ let isHashNavigationNew = isHashNavigation && window.history.state === null;
33
+ if (window.history.state === null) {
34
+ assert(isHashNavigation);
35
+ // The browser already scrolled to `#${hash}` => the current scroll position is the right one => we save it with `enhanceHistoryState()`.
36
+ enhanceHistoryState();
37
+ globalObject.previousState = getState();
38
+ }
39
+ // 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:
40
+ // - Alternative: we use `window.history.scrollRestoration = 'auto'`
41
+ // - Problem: I don't think it's possbible to set `window.history.scrollRestoration = 'auto'` only for hash navigation and not for non-hash navigations?
42
+ // - 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.
43
+ // - Specification: https://html.spec.whatwg.org/multipage/history.html#the-history-interface
44
+ // - Practice: https://stackoverflow.com/questions/70188241/history-scrollrestoration-manual-doesnt-prevent-safari-from-restoring-scrol
45
+ // - Alternative: we completely take over hash navigation and reproduce the browser's native behavior upon hash navigation.
46
+ // - By using the `hashchange` event.
47
+ // - 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.
48
+ if (isHashNavigation) {
49
+ if (!isHashNavigationNew) {
50
+ setScrollPosition(scrollTarget);
51
+ }
52
+ return;
53
+ }
54
+ let abort;
55
+ globalObject.listeners.forEach((listener) => {
56
+ abort || (abort = listener({ _experimental: { previousState } }));
57
+ });
58
+ if (abort)
59
+ return;
60
+ await renderPageClientSide({ scrollTarget, isBackwardNavigation });
61
+ });
62
+ }
63
+ /** Control client-side navigation.
64
+ *
65
+ * https://vike.dev/onPopState
66
+ */
67
+ function onPopState(listener) {
68
+ globalObject.listeners.push(listener);
69
+ }
70
+ function getState() {
71
+ return {
72
+ urlWithoutHash: getCurrentUrl({ withoutHash: true }),
73
+ historyState: getHistoryState()
74
+ };
75
+ }
76
+ function updateState() {
77
+ globalObject.previousState = getState();
78
+ }
@@ -28,9 +28,8 @@ declare function populatePageContextPrefetchCache(pageContext: PageContextForPre
28
28
  *
29
29
  * @param url - The URL of the page you want to prefetch.
30
30
  */
31
- declare function prefetch(url: string, options?: {
31
+ declare function prefetch(url: string, options_?: {
32
32
  pageContext?: boolean;
33
- staticAssets?: boolean;
34
33
  }): Promise<void>;
35
34
  declare function addLinkPrefetchHandlers(): void;
36
35
  declare function initLinkPrefetchHandlers(): void;
@@ -93,7 +93,18 @@ function getResultMaxAge() {
93
93
  *
94
94
  * @param url - The URL of the page you want to prefetch.
95
95
  */
96
- async function prefetch(url, options) {
96
+ async function prefetch(url,
97
+ /* TODO/pageContext-prefetch
98
+ options?: {
99
+ pageContext?: boolean
100
+ staticAssets?: boolean
101
+ }
102
+ */
103
+ options_) {
104
+ const options = {
105
+ staticAssets: true,
106
+ pageContext: options_?.pageContext ?? false
107
+ };
97
108
  assertUsage(checkIfClientRouting(), 'prefetch() only works with Client Routing, see https://vike.dev/prefetch', {
98
109
  showStackTrace: true
99
110
  });
@@ -115,6 +126,7 @@ async function prefetch(url, options) {
115
126
  })(),
116
127
  (async () => {
117
128
  if (options?.pageContext !== false) {
129
+ assertUsage(isBrilloutDocpress(), "prefetching pageContext isn't supported yet");
118
130
  const resultMaxAge = typeof options?.pageContext === 'number' ? options.pageContext : null;
119
131
  await prefetchPageContextFromServerHooks(pageContextLink, resultMaxAge);
120
132
  }
@@ -183,8 +195,14 @@ async function prefetchOnEvent(linkTag, event) {
183
195
  prefetchSettings = getPrefetchSettings(pageContextCurrent, linkTag);
184
196
  }
185
197
  else {
186
- // TODO/pageContext-prefetch: remove this dirty hack used by @brillout/docpress and, instead, use Vike's default if pageContextCurrent isn't defined yet.
187
- prefetchSettings = { staticAssets: 'hover', pageContext: Infinity };
198
+ if (isBrilloutDocpress()) {
199
+ // TODO/pageContext-prefetch: remove this dirty hack used by @brillout/docpress and, instead, use Vike's default if pageContextCurrent isn't defined yet.
200
+ prefetchSettings = { staticAssets: 'hover', pageContext: Infinity };
201
+ }
202
+ else {
203
+ // TODO/pageContext-prefetch: consider pageContextLink
204
+ return;
205
+ }
188
206
  }
189
207
  // Check again in case DOM was manipulated since last check
190
208
  if (skipLink(linkTag))
@@ -12,8 +12,6 @@ type RenderArgs = {
12
12
  overwriteLastHistoryEntry?: boolean;
13
13
  pageContextsFromRewrite?: PageContextFromRewrite[];
14
14
  redirectCount?: number;
15
- /** Whether the navigation was triggered by the user land calling `history.pushState()` */
16
- isUserLandPushStateNavigation?: boolean;
17
15
  isClientSideNavigation?: boolean;
18
16
  };
19
17
  declare function renderPageClientSide(renderArgs: RenderArgs): Promise<void>;
@@ -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 './onBrowserHistoryNavigation.js';
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';
@@ -30,15 +30,11 @@ const globalObject = getGlobalObject('renderPageClientSide.ts', (() => {
30
30
  })());
31
31
  const { firstRenderStartPromise } = globalObject;
32
32
  async function renderPageClientSide(renderArgs) {
33
- const { urlOriginal = getCurrentUrl(), overwriteLastHistoryEntry = false, isBackwardNavigation, pageContextsFromRewrite = [], redirectCount = 0, isUserLandPushStateNavigation, isClientSideNavigation = true } = renderArgs;
33
+ const { urlOriginal = getCurrentUrl(), overwriteLastHistoryEntry = false, isBackwardNavigation, pageContextsFromRewrite = [], redirectCount = 0, isClientSideNavigation = true } = renderArgs;
34
34
  let { scrollTarget } = renderArgs;
35
35
  const { previousPageContext } = globalObject;
36
36
  addLinkPrefetchHandlers_unwatch();
37
37
  const { isRenderOutdated, setHydrationCanBeAborted, isFirstRender } = getIsRenderOutdated();
38
- // Note that pageContext.isHydration isn't equivalent to isFirstRender
39
- // - Thus pageContext.isHydration isn't equivalent to !pageContext.isClientSideNavigation
40
- // - `pageContext.isHydration === !isFirstRender && !isErrorPage`
41
- assert(isClientSideNavigation === !isFirstRender);
42
38
  assertNoInfiniteAbortLoop(pageContextsFromRewrite.length, redirectCount);
43
39
  if (globalObject.clientRoutingIsDisabled) {
44
40
  redirectHard(urlOriginal);
@@ -121,13 +117,6 @@ async function renderPageClientSide(renderArgs) {
121
117
  redirectHard(urlOriginal);
122
118
  return;
123
119
  }
124
- const isSamePage = pageContextFromRoute.pageId &&
125
- previousPageContext?.pageId &&
126
- pageContextFromRoute.pageId === previousPageContext.pageId;
127
- if (isUserLandPushStateNavigation && isSamePage) {
128
- // Skip's Vike's rendering; let the user handle the navigation
129
- return;
130
- }
131
120
  // TODO/eventually: create helper assertPageContextFromHook()
132
121
  assert(!('urlOriginal' in pageContextFromRoute));
133
122
  objectAssign(pageContext, pageContextFromRoute);
@@ -17,6 +17,9 @@ function fileEnv() {
17
17
  return;
18
18
  if (skip(id))
19
19
  return;
20
+ // For `.vue` files: https://github.com/vikejs/vike/issues/1912#issuecomment-2394981475
21
+ if (id.endsWith('?direct'))
22
+ id = id.slice(0, -1 * '?direct'.length);
20
23
  const moduleInfo = viteDevServer.moduleGraph.getModuleById(id);
21
24
  assert(moduleInfo);
22
25
  const importers = Array.from(moduleInfo.importers)
@@ -83,7 +83,7 @@ async function transpileWithEsbuild(filePath, userRootDir, transformImports) {
83
83
  metafile: true,
84
84
  bundle: true
85
85
  };
86
- let pointerImports = {};
86
+ const pointerImports = {};
87
87
  options.plugins = [
88
88
  // Determine whether an import should be:
89
89
  // - A pointer import
@@ -34,6 +34,7 @@ export type { KeepScrollPosition };
34
34
  import type { PrefetchSetting, PrefetchStaticAssets } from '../../client/client-routing-runtime/prefetch/PrefetchSetting.js';
35
35
  import type { ConfigDefinition } from '../../node/plugin/plugins/importUserCode/v1-design/getVikeConfig/configDefinitionsBuiltIn.js';
36
36
  import type { DocumentHtml } from '../../node/runtime/html/renderHtml.js';
37
+ import type { InjectFilterEntry } from '../../types/index.js';
37
38
  import type { ConfigVikeUserProvided } from '../ConfigVike.js';
38
39
  import type { Vike, VikePackages } from '../VikeNamespace.js';
39
40
  import type { HooksTimeoutProvidedByUser } from '../hooks/getHook.js';
@@ -190,17 +191,16 @@ type OnRenderClientSync = (pageContext: PageContextClient) => void;
190
191
  *
191
192
  * https://vike.dev/onRenderHtml
192
193
  */
193
- type OnRenderHtmlAsync = (pageContext: PageContextServer) => Promise<DocumentHtml | {
194
- documentHtml: DocumentHtml;
195
- pageContext: OnRenderHtmlPageContextReturn | (() => Promise<OnRenderHtmlPageContextReturn> | OnRenderHtmlPageContextReturn);
196
- }>;
194
+ type OnRenderHtmlAsync = (pageContext: PageContextServer) => Promise<OnRenderHtmlReturn>;
197
195
  /** Hook called when page is rendered to HTML on the server-side.
198
196
  *
199
197
  * https://vike.dev/onRenderHtml
200
198
  */
201
- type OnRenderHtmlSync = (pageContext: PageContextServer) => DocumentHtml | {
202
- documentHtml: DocumentHtml;
203
- pageContext: OnRenderHtmlPageContextReturn | (() => Promise<OnRenderHtmlPageContextReturn> | OnRenderHtmlPageContextReturn);
199
+ type OnRenderHtmlSync = (pageContext: PageContextServer) => OnRenderHtmlReturn;
200
+ type OnRenderHtmlReturn = DocumentHtml | {
201
+ injectFilter?: (assets: InjectFilterEntry[]) => void;
202
+ documentHtml?: DocumentHtml;
203
+ pageContext?: OnRenderHtmlPageContextReturn | (() => Promise<OnRenderHtmlPageContextReturn> | OnRenderHtmlPageContextReturn);
204
204
  };
205
205
  type OnRenderHtmlPageContextReturn = Partial<Vike.PageContext & {
206
206
  /** See https://vike.dev/streaming */
@@ -1 +1 @@
1
- export declare const PROJECT_VERSION: "0.4.198";
1
+ export declare const PROJECT_VERSION: "0.4.199-commit-6991a96";
@@ -1,2 +1,2 @@
1
1
  // Automatically updated by @brillout/release-me
2
- export const PROJECT_VERSION = '0.4.198';
2
+ export const PROJECT_VERSION = '0.4.199-commit-6991a96';
@@ -1,4 +1,4 @@
1
1
  export declare const projectInfo: {
2
2
  projectName: "Vike";
3
- projectVersion: "0.4.198";
3
+ projectVersion: "0.4.199-commit-6991a96";
4
4
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vike",
3
- "version": "0.4.198",
3
+ "version": "0.4.199-commit-6991a96",
4
4
  "repository": "https://github.com/vikejs/vike",
5
5
  "exports": {
6
6
  "./server": {
@@ -1,4 +0,0 @@
1
- export { onBrowserHistoryNavigation };
2
- export { updateState };
3
- declare function onBrowserHistoryNavigation(): void;
4
- declare function updateState(): void;
@@ -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
- }