vike 0.4.144 → 0.4.145-commit-2520555
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/__internal/index.js +6 -2
- package/dist/cjs/node/plugin/plugins/buildConfig.js +3 -3
- package/dist/cjs/node/plugin/plugins/commonConfig.js +0 -3
- package/dist/cjs/node/plugin/plugins/config/index.js +3 -3
- package/dist/cjs/node/plugin/plugins/devConfig/determineOptimizeDeps.js +8 -8
- package/dist/cjs/node/plugin/plugins/devConfig/index.js +1 -0
- package/dist/cjs/node/plugin/plugins/envVars.js +34 -20
- package/dist/cjs/node/plugin/plugins/importBuild/index.js +3 -3
- package/dist/cjs/node/plugin/plugins/importUserCode/getVirtualFileImportUserCode.js +1 -1
- package/dist/cjs/node/plugin/plugins/importUserCode/index.js +3 -3
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/configDefinitionsBuiltIn.js +5 -4
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/filesystemRouting.js +12 -12
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +249 -228
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigValuesAll.js +8 -6
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigs.js +36 -14
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/helpers.js +1 -14
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/isRuntimeEnvMatch.js +18 -0
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/transpileAndExecuteFile.js +15 -17
- package/dist/cjs/node/plugin/plugins/previewConfig.js +11 -2
- package/dist/cjs/node/prerender/runPrerender.js +34 -26
- package/dist/cjs/node/prerender/utils.js +1 -1
- package/dist/cjs/node/runtime/html/serializePageContextClientSide.js +20 -6
- package/dist/cjs/node/runtime/renderPage/debugPageFiles.js +5 -5
- package/dist/cjs/node/runtime/renderPage/log404/index.js +28 -17
- package/dist/cjs/node/runtime/renderPage/renderPageAlreadyRouted.js +3 -3
- package/dist/cjs/node/runtime/renderPage.js +3 -3
- package/dist/cjs/node/runtime/utils.js +1 -1
- package/dist/cjs/node/shared/getClientEntryFilePath.js +2 -2
- package/dist/cjs/node/shared/getConfigVike.js +4 -1
- package/dist/cjs/shared/addUrlComputedProps.js +24 -12
- package/dist/cjs/shared/getPageFiles/analyzeClientSide.js +4 -6
- package/dist/cjs/shared/getPageFiles/getExports.js +3 -3
- package/dist/cjs/shared/hooks/getHook.js +1 -1
- package/dist/cjs/shared/page-configs/getExportPath.js +3 -3
- package/dist/cjs/shared/page-configs/helpers/getConfigDefinedAtString.js +43 -0
- package/dist/cjs/shared/page-configs/helpers/getConfigValue.js +44 -0
- package/dist/cjs/shared/page-configs/helpers.js +33 -0
- package/dist/cjs/shared/page-configs/loadConfigValues.js +2 -2
- package/dist/cjs/shared/page-configs/serialize/parseConfigValuesImported.js +14 -13
- package/dist/cjs/shared/page-configs/serialize/parsePageConfigs.js +2 -2
- package/dist/cjs/shared/page-configs/serialize/serializeConfigValue.js +9 -10
- package/dist/cjs/shared/route/abort.js +1 -1
- package/dist/cjs/shared/route/executeOnBeforeRouteHook.js +41 -15
- package/dist/cjs/shared/route/index.js +22 -32
- package/dist/cjs/shared/route/loadPageRoutes.js +11 -10
- package/dist/cjs/shared/route/noRouteMatch.js +4 -0
- package/dist/cjs/shared/route/resolveRouteFunction.js +1 -1
- package/dist/cjs/shared/utils.js +1 -1
- package/dist/cjs/utils/getFilePathAbsolute.js +11 -11
- package/dist/cjs/utils/isExternalLink.js +7 -0
- package/dist/cjs/utils/{hasPropertyGetter.js → isPropertyGetter.js} +3 -3
- package/dist/cjs/utils/onPageVisibilityChange.js +19 -0
- package/dist/cjs/utils/parseUrl.js +1 -1
- package/dist/cjs/utils/projectInfo.js +1 -1
- package/dist/cjs/utils/truncateString.js +12 -7
- package/dist/esm/__internal/index.d.ts +6 -3
- package/dist/esm/__internal/index.js +8 -3
- package/dist/esm/client/client-routing-runtime/createPageContext.d.ts +2 -3
- package/dist/esm/client/client-routing-runtime/createPageContext.js +3 -4
- package/dist/esm/client/client-routing-runtime/entry.js +2 -2
- package/dist/esm/client/client-routing-runtime/getBaseServer.d.ts +2 -1
- package/dist/esm/client/client-routing-runtime/getBaseServer.js +2 -1
- package/dist/esm/client/client-routing-runtime/getPageContextFromHooks.d.ts +39 -0
- package/dist/esm/client/client-routing-runtime/{getPageContext.js → getPageContextFromHooks.js} +50 -79
- package/dist/esm/client/client-routing-runtime/history.d.ts +3 -1
- package/dist/esm/client/client-routing-runtime/history.js +31 -9
- package/dist/esm/client/client-routing-runtime/installClientRouter.d.ts +2 -0
- package/dist/esm/client/client-routing-runtime/installClientRouter.js +22 -0
- package/dist/esm/client/client-routing-runtime/isClientSideRoutable.d.ts +8 -0
- package/dist/esm/client/client-routing-runtime/isClientSideRoutable.js +12 -0
- package/dist/esm/client/client-routing-runtime/navigate.d.ts +0 -2
- package/dist/esm/client/client-routing-runtime/navigate.js +9 -8
- package/dist/esm/client/client-routing-runtime/onBrowserHistoryNavigation.d.ts +4 -0
- package/dist/esm/client/client-routing-runtime/onBrowserHistoryNavigation.js +63 -0
- package/dist/esm/client/client-routing-runtime/onLinkClick.d.ts +2 -0
- package/dist/esm/client/client-routing-runtime/onLinkClick.js +40 -0
- package/dist/esm/client/client-routing-runtime/prefetch.js +54 -29
- package/dist/esm/client/client-routing-runtime/renderPageClientSide.d.ts +19 -0
- package/dist/esm/client/client-routing-runtime/renderPageClientSide.js +347 -0
- package/dist/esm/client/client-routing-runtime/scrollRestoration.d.ts +6 -0
- package/dist/esm/client/client-routing-runtime/scrollRestoration.js +25 -0
- package/dist/esm/client/client-routing-runtime/setScrollPosition.d.ts +7 -0
- package/dist/esm/client/client-routing-runtime/setScrollPosition.js +77 -0
- package/dist/esm/client/client-routing-runtime/skipLink.d.ts +0 -1
- package/dist/esm/client/client-routing-runtime/skipLink.js +9 -5
- package/dist/esm/client/client-routing-runtime/utils.d.ts +2 -0
- package/dist/esm/client/client-routing-runtime/utils.js +2 -0
- package/dist/esm/client/server-routing-runtime/getPageContext.js +1 -1
- package/dist/esm/client/shared/executeOnRenderClientHook.js +6 -5
- package/dist/esm/client/shared/getPageContextProxyForUser.js +13 -7
- package/dist/esm/client/shared/loadPageFilesClientSide.d.ts +8 -3
- package/dist/esm/client/shared/loadPageFilesClientSide.js +5 -5
- package/dist/esm/node/plugin/plugins/buildConfig.js +3 -3
- package/dist/esm/node/plugin/plugins/commonConfig.js +0 -3
- package/dist/esm/node/plugin/plugins/config/index.js +4 -4
- package/dist/esm/node/plugin/plugins/devConfig/determineOptimizeDeps.js +9 -9
- package/dist/esm/node/plugin/plugins/devConfig/index.js +1 -0
- package/dist/esm/node/plugin/plugins/envVars.d.ts +2 -0
- package/dist/esm/node/plugin/plugins/envVars.js +35 -20
- package/dist/esm/node/plugin/plugins/importBuild/index.js +3 -3
- package/dist/esm/node/plugin/plugins/importUserCode/getVirtualFileImportUserCode.js +1 -1
- package/dist/esm/node/plugin/plugins/importUserCode/index.js +3 -3
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/configDefinitionsBuiltIn.d.ts +2 -1
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/configDefinitionsBuiltIn.js +5 -4
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/filesystemRouting.d.ts +1 -1
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/filesystemRouting.js +12 -12
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.d.ts +2 -1
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +250 -229
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigValuesAll.d.ts +2 -2
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigValuesAll.js +7 -5
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigs.d.ts +2 -2
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigs.js +37 -15
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/helpers.js +1 -14
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/isRuntimeEnvMatch.d.ts +7 -0
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/isRuntimeEnvMatch.js +15 -0
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/transpileAndExecuteFile.d.ts +2 -2
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/transpileAndExecuteFile.js +16 -18
- package/dist/esm/node/plugin/plugins/previewConfig.js +11 -2
- package/dist/esm/node/prerender/runPrerender.js +29 -21
- package/dist/esm/node/prerender/utils.d.ts +1 -1
- package/dist/esm/node/prerender/utils.js +1 -1
- package/dist/esm/node/runtime/html/serializePageContextClientSide.js +21 -7
- package/dist/esm/node/runtime/renderPage/debugPageFiles.d.ts +5 -5
- package/dist/esm/node/runtime/renderPage/debugPageFiles.js +5 -5
- package/dist/esm/node/runtime/renderPage/loadPageFilesServerSide.d.ts +2 -2
- package/dist/esm/node/runtime/renderPage/log404/index.d.ts +2 -2
- package/dist/esm/node/runtime/renderPage/log404/index.js +28 -16
- package/dist/esm/node/runtime/renderPage/renderPageAlreadyRouted.js +2 -2
- package/dist/esm/node/runtime/renderPage.js +3 -3
- package/dist/esm/node/runtime/utils.d.ts +1 -1
- package/dist/esm/node/runtime/utils.js +1 -1
- package/dist/esm/node/shared/getClientEntryFilePath.js +1 -1
- package/dist/esm/node/shared/getConfigVike.d.ts +2 -1
- package/dist/esm/node/shared/getConfigVike.js +4 -1
- package/dist/esm/shared/addUrlComputedProps.d.ts +1 -0
- package/dist/esm/shared/addUrlComputedProps.js +25 -13
- package/dist/esm/shared/getPageFiles/analyzeClientSide.js +2 -4
- package/dist/esm/shared/getPageFiles/getExports.js +2 -2
- package/dist/esm/shared/hooks/getHook.js +1 -1
- package/dist/esm/shared/page-configs/PageConfig.d.ts +55 -31
- package/dist/esm/shared/page-configs/getExportPath.d.ts +1 -1
- package/dist/esm/shared/page-configs/getExportPath.js +3 -3
- package/dist/esm/shared/page-configs/helpers/getConfigDefinedAtString.d.ts +7 -0
- package/dist/esm/shared/page-configs/helpers/getConfigDefinedAtString.js +37 -0
- package/dist/esm/shared/page-configs/helpers/getConfigValue.d.ts +14 -0
- package/dist/esm/shared/page-configs/helpers/getConfigValue.js +38 -0
- package/dist/esm/shared/page-configs/helpers.d.ts +13 -0
- package/dist/esm/shared/page-configs/helpers.js +27 -0
- package/dist/esm/shared/page-configs/loadConfigValues.js +2 -2
- package/dist/esm/shared/page-configs/serialize/PageConfigSerialized.d.ts +4 -4
- package/dist/esm/shared/page-configs/serialize/parseConfigValuesImported.js +15 -11
- package/dist/esm/shared/page-configs/serialize/parsePageConfigs.js +2 -2
- package/dist/esm/shared/page-configs/serialize/serializeConfigValue.js +9 -10
- package/dist/esm/shared/route/abort.js +1 -1
- package/dist/esm/shared/route/executeOnBeforeRouteHook.d.ts +5 -8
- package/dist/esm/shared/route/executeOnBeforeRouteHook.js +41 -15
- package/dist/esm/shared/route/index.d.ts +12 -10
- package/dist/esm/shared/route/index.js +23 -33
- package/dist/esm/shared/route/loadPageRoutes.js +8 -7
- package/dist/esm/shared/route/noRouteMatch.d.ts +1 -0
- package/dist/esm/shared/route/noRouteMatch.js +1 -0
- package/dist/esm/shared/route/resolveRouteFunction.js +1 -1
- package/dist/esm/shared/utils.d.ts +1 -1
- package/dist/esm/shared/utils.js +1 -1
- package/dist/esm/utils/getFilePathAbsolute.d.ts +1 -1
- package/dist/esm/utils/getFilePathAbsolute.js +11 -11
- package/dist/esm/utils/isPropertyGetter.d.ts +1 -0
- package/dist/esm/utils/{hasPropertyGetter.js → isPropertyGetter.js} +1 -1
- package/dist/esm/utils/onPageVisibilityChange.d.ts +4 -0
- package/dist/esm/utils/onPageVisibilityChange.js +16 -0
- package/dist/esm/utils/parseUrl.js +1 -1
- package/dist/esm/utils/projectInfo.d.ts +1 -1
- package/dist/esm/utils/projectInfo.js +1 -1
- package/dist/esm/utils/truncateString.d.ts +2 -1
- package/dist/esm/utils/truncateString.js +10 -7
- package/node/cli/bin-entry.js +1 -1
- package/package.json +2 -3
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getFilePathToShowToUser.js +0 -16
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/isConfigEnvMatch.js +0 -13
- package/dist/cjs/shared/page-configs/utils.js +0 -103
- package/dist/esm/client/client-routing-runtime/getPageContext.d.ts +0 -29
- package/dist/esm/client/client-routing-runtime/getPageId.d.ts +0 -10
- package/dist/esm/client/client-routing-runtime/getPageId.js +0 -17
- package/dist/esm/client/client-routing-runtime/navigationState.d.ts +0 -5
- package/dist/esm/client/client-routing-runtime/navigationState.js +0 -14
- package/dist/esm/client/client-routing-runtime/skipLink/isClientSideRoutable.d.ts +0 -2
- package/dist/esm/client/client-routing-runtime/skipLink/isClientSideRoutable.js +0 -15
- package/dist/esm/client/client-routing-runtime/useClientRouter.d.ts +0 -6
- package/dist/esm/client/client-routing-runtime/useClientRouter.js +0 -493
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getFilePathToShowToUser.d.ts +0 -24
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getFilePathToShowToUser.js +0 -13
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/isConfigEnvMatch.d.ts +0 -3
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/isConfigEnvMatch.js +0 -10
- package/dist/esm/shared/page-configs/utils.d.ts +0 -35
- package/dist/esm/shared/page-configs/utils.js +0 -97
- package/dist/esm/utils/hasPropertyGetter.d.ts +0 -1
- /package/dist/esm/{client/client-routing-runtime → utils}/isExternalLink.d.ts +0 -0
- /package/dist/esm/{client/client-routing-runtime → utils}/isExternalLink.js +0 -0
package/dist/esm/client/client-routing-runtime/{getPageContext.js → getPageContextFromHooks.js}
RENAMED
|
@@ -1,105 +1,91 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export {
|
|
3
|
-
export {
|
|
1
|
+
export { getPageContextFromHooks_firstRender };
|
|
2
|
+
export { getPageContextFromHooks_uponNavigation };
|
|
3
|
+
export { getPageContextFromHooks_errorPage };
|
|
4
4
|
export { isAlreadyServerSideRouted };
|
|
5
|
-
import { navigationState } from './navigationState.js';
|
|
6
5
|
import { assert, assertUsage, hasProp, objectAssign, getProjectError, serverSideRouteTo, executeHook, isObject, getGlobalObject } from './utils.js';
|
|
7
6
|
import { parse } from '@brillout/json-serializer/parse';
|
|
8
7
|
import { getPageContextSerializedInHtml } from '../shared/getPageContextSerializedInHtml.js';
|
|
9
8
|
import { analyzePageServerSide } from '../../shared/getPageFiles/analyzePageServerSide.js';
|
|
10
|
-
import { route } from '../../shared/route/index.js';
|
|
11
9
|
import { getErrorPageId } from '../../shared/error-page.js';
|
|
12
10
|
import { getHook } from '../../shared/hooks/getHook.js';
|
|
13
11
|
import { preparePageContextForUserConsumptionClientSide } from '../shared/preparePageContextForUserConsumptionClientSide.js';
|
|
14
12
|
import { loadPageFilesClientSide } from '../shared/loadPageFilesClientSide.js';
|
|
15
13
|
import { removeBuiltInOverrides } from './getPageContext/removeBuiltInOverrides.js';
|
|
16
14
|
import { getPageContextRequestUrl } from '../../shared/getPageContextRequestUrl.js';
|
|
17
|
-
import { getConfigValue, getPageConfig } from '../../shared/page-configs/
|
|
15
|
+
import { getConfigValue, getPageConfig } from '../../shared/page-configs/helpers.js';
|
|
18
16
|
import { assertOnBeforeRenderHookReturn } from '../../shared/assertOnBeforeRenderHookReturn.js';
|
|
19
17
|
import { executeGuardHook } from '../../shared/route/executeGuardHook.js';
|
|
20
18
|
import { AbortRender, isAbortPageContext } from '../../shared/route/abort.js';
|
|
21
19
|
const globalObject = getGlobalObject('router/getPageContext.ts', {});
|
|
22
|
-
async function
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
setPageContextInitHasClientData(pageContextAddendum);
|
|
27
|
-
return pageContextAddendum;
|
|
28
|
-
}
|
|
29
|
-
else {
|
|
30
|
-
assert(hasProp(pageContext, '_isFirstRenderAttempt', 'false'));
|
|
31
|
-
const pageContextAddendum = await getPageContextUponNavigation(pageContext);
|
|
32
|
-
setPageContextInitHasClientData(pageContextAddendum);
|
|
33
|
-
return pageContextAddendum;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
async function getPageContextFirstRender(pageContext) {
|
|
37
|
-
const pageContextAddendum = getPageContextSerializedInHtml();
|
|
38
|
-
removeBuiltInOverrides(pageContextAddendum);
|
|
39
|
-
objectAssign(pageContextAddendum, {
|
|
20
|
+
async function getPageContextFromHooks_firstRender(pageContext) {
|
|
21
|
+
const pageContextFromHooks = getPageContextSerializedInHtml();
|
|
22
|
+
removeBuiltInOverrides(pageContextFromHooks);
|
|
23
|
+
objectAssign(pageContextFromHooks, {
|
|
40
24
|
isHydration: true,
|
|
41
25
|
_hasPageContextFromClient: false
|
|
42
26
|
});
|
|
43
|
-
objectAssign(
|
|
27
|
+
objectAssign(pageContextFromHooks, await loadPageFilesClientSide(pageContextFromHooks._pageId, pageContext));
|
|
44
28
|
{
|
|
45
|
-
const pageContextForHook = { ...pageContext, ...
|
|
29
|
+
const pageContextForHook = { ...pageContext, ...pageContextFromHooks };
|
|
46
30
|
if (await onBeforeRenderClientOnlyExists(pageContextForHook)) {
|
|
47
31
|
const pageContextFromHook = await executeOnBeforeRenderHookClientSide(pageContextForHook);
|
|
48
|
-
objectAssign(
|
|
32
|
+
objectAssign(pageContextFromHooks, pageContextFromHook);
|
|
49
33
|
}
|
|
50
34
|
}
|
|
51
|
-
|
|
35
|
+
setPageContextInitHasClientData(pageContextFromHooks);
|
|
36
|
+
return pageContextFromHooks;
|
|
52
37
|
}
|
|
53
|
-
async function
|
|
38
|
+
async function getPageContextFromHooks_errorPage(pageContext) {
|
|
54
39
|
const errorPageId = getErrorPageId(pageContext._pageFilesAll, pageContext._pageConfigs);
|
|
55
40
|
if (!errorPageId)
|
|
56
41
|
throw new Error('No error page defined.');
|
|
57
|
-
const
|
|
42
|
+
const pageContextFromHooks = {
|
|
58
43
|
isHydration: false,
|
|
59
44
|
_pageId: errorPageId
|
|
60
45
|
};
|
|
61
|
-
objectAssign(
|
|
62
|
-
return
|
|
46
|
+
objectAssign(pageContextFromHooks, await getPageContextAlreadyRouted({ ...pageContext, ...pageContextFromHooks }, true));
|
|
47
|
+
return pageContextFromHooks;
|
|
63
48
|
}
|
|
64
|
-
async function
|
|
65
|
-
const
|
|
66
|
-
isHydration: false
|
|
49
|
+
async function getPageContextFromHooks_uponNavigation(pageContext) {
|
|
50
|
+
const pageContextFromHooks = {
|
|
51
|
+
isHydration: false,
|
|
52
|
+
_pageId: pageContext._pageId
|
|
67
53
|
};
|
|
68
|
-
objectAssign(
|
|
69
|
-
|
|
70
|
-
return
|
|
54
|
+
objectAssign(pageContextFromHooks, await getPageContextAlreadyRouted({ ...pageContext, ...pageContextFromHooks }, false));
|
|
55
|
+
setPageContextInitHasClientData(pageContextFromHooks);
|
|
56
|
+
return pageContextFromHooks;
|
|
71
57
|
}
|
|
72
58
|
async function getPageContextAlreadyRouted(pageContext, isErrorPage) {
|
|
73
|
-
let
|
|
74
|
-
objectAssign(
|
|
59
|
+
let pageContextFromHooks = {};
|
|
60
|
+
objectAssign(pageContextFromHooks, await loadPageFilesClientSide(pageContext._pageId, pageContext));
|
|
75
61
|
// Needs to be called before any client-side hook, because it may contain pageContextInit.user which is needed for guard() and onBeforeRender()
|
|
76
62
|
if (
|
|
77
63
|
// For the error page, we cannot fetch pageContext from the server because the pageContext JSON request is based on the URL
|
|
78
64
|
!isErrorPage &&
|
|
79
|
-
(await hasPageContextServer({ ...pageContext, ...
|
|
65
|
+
(await hasPageContextServer({ ...pageContext, ...pageContextFromHooks }))) {
|
|
80
66
|
const pageContextFromServer = await fetchPageContextFromServer(pageContext);
|
|
81
67
|
if (!pageContextFromServer['_isError']) {
|
|
82
|
-
objectAssign(
|
|
68
|
+
objectAssign(pageContextFromHooks, pageContextFromServer);
|
|
83
69
|
}
|
|
84
70
|
else {
|
|
85
71
|
const errorPageId = getErrorPageId(pageContext._pageFilesAll, pageContext._pageConfigs);
|
|
86
72
|
assert(errorPageId);
|
|
87
|
-
|
|
88
|
-
objectAssign(
|
|
73
|
+
pageContextFromHooks = {};
|
|
74
|
+
objectAssign(pageContextFromHooks, {
|
|
89
75
|
isHydration: false,
|
|
90
76
|
_pageId: errorPageId
|
|
91
77
|
});
|
|
92
|
-
objectAssign(
|
|
78
|
+
objectAssign(pageContextFromHooks, await loadPageFilesClientSide(pageContextFromHooks._pageId, pageContext));
|
|
93
79
|
assert(hasProp(pageContextFromServer, 'is404', 'boolean'));
|
|
94
80
|
assert(hasProp(pageContextFromServer, 'pageProps', 'object'));
|
|
95
81
|
assert(hasProp(pageContextFromServer.pageProps, 'is404', 'boolean'));
|
|
96
82
|
// When the user hasn't define a `_error.page.js` file: the mechanism with `serverSideError: true` is used instead
|
|
97
83
|
assert(!('serverSideError' in pageContextFromServer));
|
|
98
|
-
objectAssign(
|
|
84
|
+
objectAssign(pageContextFromHooks, pageContextFromServer);
|
|
99
85
|
}
|
|
100
86
|
}
|
|
101
87
|
else {
|
|
102
|
-
objectAssign(
|
|
88
|
+
objectAssign(pageContextFromHooks, { _hasPageContextFromServer: false });
|
|
103
89
|
// We don't need to call guard() on the client-side if we fetch pageContext from the server side. (Because the `${url}.pageContext.json` HTTP request will already trigger the routing and guard() hook on the serve-side.)
|
|
104
90
|
// We cannot call guard() before retrieving pageContext from server, since the server-side may define pageContextInit.user which is paramount for guard() hooks
|
|
105
91
|
if (!isErrorPage) {
|
|
@@ -107,41 +93,41 @@ async function getPageContextAlreadyRouted(pageContext, isErrorPage) {
|
|
|
107
93
|
await executeGuardHook({
|
|
108
94
|
_hasPageContextFromClient: false,
|
|
109
95
|
...pageContext,
|
|
110
|
-
...
|
|
96
|
+
...pageContextFromHooks
|
|
111
97
|
}, (pageContext) => preparePageContextForUserConsumptionClientSide(pageContext, true));
|
|
112
98
|
}
|
|
113
99
|
}
|
|
114
100
|
{
|
|
115
101
|
// For the error page, we also execute the client-side onBeforeRender() hook, but maybe we shouldn't? The server-side does it as well (but maybe it shouldn't).
|
|
116
|
-
const
|
|
117
|
-
|
|
102
|
+
const pageContextFromOnBeforeRender = await executeOnBeforeRenderHookClientSide({
|
|
103
|
+
...pageContext,
|
|
104
|
+
...pageContextFromHooks
|
|
105
|
+
});
|
|
106
|
+
objectAssign(pageContextFromHooks, pageContextFromOnBeforeRender);
|
|
118
107
|
}
|
|
119
|
-
return
|
|
108
|
+
return pageContextFromHooks;
|
|
120
109
|
}
|
|
121
110
|
async function executeOnBeforeRenderHookClientSide(pageContext) {
|
|
122
111
|
const hook = getHook(pageContext, 'onBeforeRender');
|
|
123
112
|
if (!hook) {
|
|
124
|
-
const
|
|
113
|
+
const pageContextFromOnBeforeRender = {
|
|
125
114
|
_hasPageContextFromClient: false
|
|
126
115
|
};
|
|
127
|
-
return
|
|
116
|
+
return pageContextFromOnBeforeRender;
|
|
128
117
|
}
|
|
129
118
|
const onBeforeRender = hook.hookFn;
|
|
130
|
-
const
|
|
119
|
+
const pageContextFromOnBeforeRender = {
|
|
131
120
|
_hasPageContextFromClient: true
|
|
132
121
|
};
|
|
133
122
|
const pageContextForUserConsumption = preparePageContextForUserConsumptionClientSide({
|
|
134
123
|
...pageContext,
|
|
135
|
-
...
|
|
124
|
+
...pageContextFromOnBeforeRender
|
|
136
125
|
}, true);
|
|
137
126
|
const hookResult = await executeHook(() => onBeforeRender(pageContextForUserConsumption), 'onBeforeRender', hook.hookFilePath);
|
|
138
127
|
assertOnBeforeRenderHookReturn(hookResult, hook.hookFilePath);
|
|
139
128
|
const pageContextFromHook = hookResult?.pageContext;
|
|
140
|
-
objectAssign(
|
|
141
|
-
return
|
|
142
|
-
}
|
|
143
|
-
async function hasPageContextServer(pageContext) {
|
|
144
|
-
return !!globalObject.pageContextInitHasClientData || (await onBeforeRenderServerOnlyExists(pageContext));
|
|
129
|
+
objectAssign(pageContextFromOnBeforeRender, pageContextFromHook);
|
|
130
|
+
return pageContextFromOnBeforeRender;
|
|
145
131
|
}
|
|
146
132
|
// Workaround for the fact that the client-side cannot known whether a pageContext JSON request is needed in order to fetch pageContextInit data passed to the client.
|
|
147
133
|
// - The workaround is reliable as long as the user sets additional pageContextInit to undefined instead of not defining the property:
|
|
@@ -160,6 +146,9 @@ function setPageContextInitHasClientData(pageContext) {
|
|
|
160
146
|
globalObject.pageContextInitHasClientData = true;
|
|
161
147
|
}
|
|
162
148
|
}
|
|
149
|
+
async function hasPageContextServer(pageContext) {
|
|
150
|
+
return !!globalObject.pageContextInitHasClientData || (await onBeforeRenderServerOnlyExists(pageContext));
|
|
151
|
+
}
|
|
163
152
|
async function onBeforeRenderServerOnlyExists(pageContext) {
|
|
164
153
|
if (pageContext._pageConfigs.length > 0) {
|
|
165
154
|
// V1
|
|
@@ -184,26 +173,8 @@ async function onBeforeRenderClientOnlyExists(pageContext) {
|
|
|
184
173
|
return false;
|
|
185
174
|
}
|
|
186
175
|
}
|
|
187
|
-
async function getPageContextFromRoute(pageContext) {
|
|
188
|
-
const routeResult = await route(pageContext);
|
|
189
|
-
const pageContextFromRoute = routeResult.pageContextAddendum;
|
|
190
|
-
if (!pageContextFromRoute._pageId) {
|
|
191
|
-
const err = new Error('No routing match');
|
|
192
|
-
markIs404(err);
|
|
193
|
-
throw err;
|
|
194
|
-
}
|
|
195
|
-
assert(hasProp(pageContextFromRoute, '_pageId', 'string'));
|
|
196
|
-
return pageContextFromRoute;
|
|
197
|
-
}
|
|
198
|
-
function markIs404(err) {
|
|
199
|
-
objectAssign(err, { _is404: true });
|
|
200
|
-
}
|
|
201
|
-
function checkIf404(err) {
|
|
202
|
-
return isObject(err) && err._is404 === true;
|
|
203
|
-
}
|
|
204
176
|
async function fetchPageContextFromServer(pageContext) {
|
|
205
|
-
const
|
|
206
|
-
const pageContextUrl = getPageContextRequestUrl(urlLogical);
|
|
177
|
+
const pageContextUrl = getPageContextRequestUrl(pageContext._urlRewrite ?? pageContext.urlOriginal);
|
|
207
178
|
const response = await fetch(pageContextUrl);
|
|
208
179
|
{
|
|
209
180
|
const contentType = response.headers.get('content-type');
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
export { initHistoryState, getHistoryState, pushHistory, ScrollPosition, saveScrollPosition };
|
|
1
|
+
export { initHistoryState, getHistoryState, pushHistory, ScrollPosition, saveScrollPosition, monkeyPatchHistoryPushState };
|
|
2
2
|
type HistoryState = {
|
|
3
3
|
timestamp?: number;
|
|
4
4
|
scrollPosition?: null | ScrollPosition;
|
|
5
|
+
triggedBy?: 'user' | 'vike' | 'browser';
|
|
5
6
|
};
|
|
6
7
|
type ScrollPosition = {
|
|
7
8
|
x: number;
|
|
@@ -11,3 +12,4 @@ declare function initHistoryState(): void;
|
|
|
11
12
|
declare function getHistoryState(): HistoryState;
|
|
12
13
|
declare function saveScrollPosition(): void;
|
|
13
14
|
declare function pushHistory(url: string, overwriteLastHistoryEntry: boolean): void;
|
|
15
|
+
declare function monkeyPatchHistoryPushState(): void;
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
export { initHistoryState, getHistoryState, pushHistory, saveScrollPosition };
|
|
2
|
-
import { assert, hasProp, isObject } from './utils.js';
|
|
3
|
-
|
|
4
|
-
//
|
|
5
|
-
// -
|
|
6
|
-
//
|
|
7
|
-
//
|
|
1
|
+
export { initHistoryState, getHistoryState, pushHistory, saveScrollPosition, monkeyPatchHistoryPushState };
|
|
2
|
+
import { assert, assertUsage, getGlobalObject, hasProp, isObject } from './utils.js';
|
|
3
|
+
const globalObject = getGlobalObject('history.ts', {});
|
|
4
|
+
// Fill missing state information:
|
|
5
|
+
// - `history.state` can uninitialized (i.e. `null`):
|
|
6
|
+
// - The very first render
|
|
7
|
+
// - The user's code runs `location.hash = '#section'`
|
|
8
|
+
// - The user clicks on an anchor link `<a href="#section">Section</a>` (Vike's `onLinkClick()` handler skips hash links).
|
|
9
|
+
// - 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`.)
|
|
8
10
|
function initHistoryState() {
|
|
9
11
|
let state = window.history.state;
|
|
10
12
|
if (!state) {
|
|
@@ -19,6 +21,9 @@ function initHistoryState() {
|
|
|
19
21
|
hasModifications = true;
|
|
20
22
|
state.scrollPosition = getScrollPosition();
|
|
21
23
|
}
|
|
24
|
+
if (!('triggedBy' in state)) {
|
|
25
|
+
state.triggedBy = 'browser';
|
|
26
|
+
}
|
|
22
27
|
assertState(state);
|
|
23
28
|
if (hasModifications) {
|
|
24
29
|
replaceHistoryState(state);
|
|
@@ -44,7 +49,7 @@ function saveScrollPosition() {
|
|
|
44
49
|
function pushHistory(url, overwriteLastHistoryEntry) {
|
|
45
50
|
if (!overwriteLastHistoryEntry) {
|
|
46
51
|
const timestamp = getTimestamp();
|
|
47
|
-
pushHistoryState({ timestamp, scrollPosition: null }, url);
|
|
52
|
+
pushHistoryState({ timestamp, scrollPosition: null, triggedBy: 'vike' }, url);
|
|
48
53
|
}
|
|
49
54
|
else {
|
|
50
55
|
replaceHistoryState(getHistoryState(), url);
|
|
@@ -67,5 +72,22 @@ function replaceHistoryState(state, url) {
|
|
|
67
72
|
window.history.replaceState(state, '', url ?? /* Passing `undefined` chokes older Edge versions */ null);
|
|
68
73
|
}
|
|
69
74
|
function pushHistoryState(state, url) {
|
|
70
|
-
|
|
75
|
+
pushStateOriginal(state, '', url);
|
|
76
|
+
}
|
|
77
|
+
function monkeyPatchHistoryPushState() {
|
|
78
|
+
globalObject.pushStateOriginal = globalObject.pushStateOriginal ?? window.history.pushState;
|
|
79
|
+
window.history.pushState = (stateFromUser = {}, ...rest) => {
|
|
80
|
+
assertUsage(null === stateFromUser || undefined === stateFromUser || isObject(stateFromUser), 'history.pushState(state) argument state must be an object');
|
|
81
|
+
const state = {
|
|
82
|
+
scrollPosition: getScrollPosition(),
|
|
83
|
+
timestamp: getTimestamp(),
|
|
84
|
+
...stateFromUser,
|
|
85
|
+
// Don't allow user to overwrite triggedBy as it would break Vike's handling of the 'popstate' event
|
|
86
|
+
triggedBy: 'user'
|
|
87
|
+
};
|
|
88
|
+
return pushStateOriginal(state, ...rest);
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
function pushStateOriginal(...args) {
|
|
92
|
+
globalObject.pushStateOriginal.apply(history, args);
|
|
71
93
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export { installClientRouter };
|
|
2
|
+
import { assert } from './utils.js';
|
|
3
|
+
import { initHistoryState, monkeyPatchHistoryPushState } from './history.js';
|
|
4
|
+
import { getRenderCount, renderPageClientSide } from './renderPageClientSide.js';
|
|
5
|
+
import { onBrowserHistoryNavigation } from './onBrowserHistoryNavigation.js';
|
|
6
|
+
import { onLinkClick } from './onLinkClick.js';
|
|
7
|
+
import { setupNativeScrollRestoration } from './scrollRestoration.js';
|
|
8
|
+
import { autoSaveScrollPosition } from './setScrollPosition.js';
|
|
9
|
+
function installClientRouter() {
|
|
10
|
+
setupNativeScrollRestoration();
|
|
11
|
+
initHistoryState();
|
|
12
|
+
autoSaveScrollPosition();
|
|
13
|
+
monkeyPatchHistoryPushState();
|
|
14
|
+
// First initial render
|
|
15
|
+
assert(getRenderCount() === 0);
|
|
16
|
+
renderPageClientSide({ scrollTarget: 'preserve-scroll', isBackwardNavigation: null, isClientSideNavigation: false });
|
|
17
|
+
assert(getRenderCount() === 1);
|
|
18
|
+
// Intercept <a> links
|
|
19
|
+
onLinkClick();
|
|
20
|
+
// Handle back-/forward navigation
|
|
21
|
+
onBrowserHistoryNavigation();
|
|
22
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { isClientSideRoutable };
|
|
2
|
+
import type { PageFile } from '../../shared/getPageFiles.js';
|
|
3
|
+
import type { PageConfigRuntime } from '../../shared/page-configs/PageConfig.js';
|
|
4
|
+
type PageContextPageFiles = {
|
|
5
|
+
_pageFilesAll: PageFile[];
|
|
6
|
+
_pageConfigs: PageConfigRuntime[];
|
|
7
|
+
};
|
|
8
|
+
declare function isClientSideRoutable(pageId: string, pageContext: PageContextPageFiles): Promise<boolean>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { isClientSideRoutable };
|
|
2
|
+
import { analyzePageClientSideInit } from '../../shared/getPageFiles/analyzePageClientSide.js';
|
|
3
|
+
import { findPageConfig } from '../../shared/page-configs/findPageConfig.js';
|
|
4
|
+
import { analyzeClientSide } from '../../shared/getPageFiles/analyzeClientSide.js';
|
|
5
|
+
async function isClientSideRoutable(pageId, pageContext) {
|
|
6
|
+
await analyzePageClientSideInit(pageContext._pageFilesAll, pageId, {
|
|
7
|
+
sharedPageFilesAlreadyLoaded: false
|
|
8
|
+
});
|
|
9
|
+
const pageConfig = findPageConfig(pageContext._pageConfigs, pageId);
|
|
10
|
+
const { isClientSideRenderable, isClientRouting } = analyzeClientSide(pageConfig, pageContext._pageFilesAll, pageId);
|
|
11
|
+
return isClientSideRenderable && isClientRouting;
|
|
12
|
+
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
export { navigate };
|
|
2
2
|
export { reload };
|
|
3
|
-
export { defineNavigate };
|
|
4
3
|
/** Programmatically navigate to a new page.
|
|
5
4
|
*
|
|
6
5
|
* https://vike.dev/navigate
|
|
@@ -13,5 +12,4 @@ declare function navigate(url: string, { keepScrollPosition, overwriteLastHistor
|
|
|
13
12
|
keepScrollPosition?: boolean | undefined;
|
|
14
13
|
overwriteLastHistoryEntry?: boolean | undefined;
|
|
15
14
|
}): Promise<void>;
|
|
16
|
-
declare function defineNavigate(navigate_: typeof navigate): void;
|
|
17
15
|
declare function reload(): Promise<void>;
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
export { navigate };
|
|
2
2
|
export { reload };
|
|
3
|
-
|
|
4
|
-
import { assertUsage, isBrowser,
|
|
3
|
+
import { renderPageClientSide } from './renderPageClientSide.js';
|
|
4
|
+
import { assertUsage, isBrowser, assertClientRouting, checkIfClientRouting, getCurrentUrl } from './utils.js';
|
|
5
5
|
assertClientRouting();
|
|
6
|
-
const globalObject = getGlobalObject('navigate.ts', {});
|
|
7
6
|
/** Programmatically navigate to a new page.
|
|
8
7
|
*
|
|
9
8
|
* https://vike.dev/navigate
|
|
@@ -15,7 +14,6 @@ const globalObject = getGlobalObject('navigate.ts', {});
|
|
|
15
14
|
async function navigate(url, { keepScrollPosition = false, overwriteLastHistoryEntry = false } = {}) {
|
|
16
15
|
assertUsage(isBrowser(), 'The navigate() function can be called only on the client-side', { showStackTrace: true });
|
|
17
16
|
const errMsg = 'navigate() works only with Client Routing, see https://vike.dev/navigate';
|
|
18
|
-
assertUsage(globalObject.navigate, errMsg, { showStackTrace: true });
|
|
19
17
|
assertUsage(checkIfClientRouting(), errMsg, { showStackTrace: true });
|
|
20
18
|
assertUsage(url, '[navigate(url)] Missing argument url', { showStackTrace: true });
|
|
21
19
|
assertUsage(typeof url === 'string', '[navigate(url)] Argument url should be a string', { showStackTrace: true });
|
|
@@ -24,10 +22,13 @@ async function navigate(url, { keepScrollPosition = false, overwriteLastHistoryE
|
|
|
24
22
|
assertUsage(url.startsWith('/'), '[navigate(url)] Argument url should start with a leading /', {
|
|
25
23
|
showStackTrace: true
|
|
26
24
|
});
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
25
|
+
const scrollTarget = keepScrollPosition ? 'preserve-scroll' : 'scroll-to-top-or-hash';
|
|
26
|
+
await renderPageClientSide({
|
|
27
|
+
scrollTarget,
|
|
28
|
+
urlOriginal: url,
|
|
29
|
+
overwriteLastHistoryEntry,
|
|
30
|
+
isBackwardNavigation: false
|
|
31
|
+
});
|
|
31
32
|
}
|
|
32
33
|
async function reload() {
|
|
33
34
|
await navigate(getCurrentUrl());
|
|
@@ -0,0 +1,63 @@
|
|
|
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` 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', () => {
|
|
19
|
+
const currentState = getState();
|
|
20
|
+
const scrollTarget = currentState.historyState.scrollPosition || 'scroll-to-top-or-hash';
|
|
21
|
+
const isUserLandPushStateNavigation = currentState.historyState.triggedBy === '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 `onLinkClick()` 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
|
+
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
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// Code adapted from https://github.com/HenrikJoreteg/internal-nav-helper/blob/5199ec5448d0b0db7ec63cf76d88fa6cad878b7d/src/index.js#L11-L29
|
|
2
|
+
export { onLinkClick };
|
|
3
|
+
import { assert } from './utils.js';
|
|
4
|
+
import { skipLink } from './skipLink.js';
|
|
5
|
+
import { renderPageClientSide } from './renderPageClientSide.js';
|
|
6
|
+
function onLinkClick() {
|
|
7
|
+
document.addEventListener('click', handler);
|
|
8
|
+
}
|
|
9
|
+
function handler(ev) {
|
|
10
|
+
if (!isNormalLeftClick(ev))
|
|
11
|
+
return;
|
|
12
|
+
const linkTag = findLinkTag(ev.target);
|
|
13
|
+
if (!linkTag)
|
|
14
|
+
return;
|
|
15
|
+
const url = linkTag.getAttribute('href');
|
|
16
|
+
if (skipLink(linkTag))
|
|
17
|
+
return;
|
|
18
|
+
assert(url);
|
|
19
|
+
ev.preventDefault();
|
|
20
|
+
const keepScrollPosition = ![null, 'false'].includes(linkTag.getAttribute('keep-scroll-position'));
|
|
21
|
+
const scrollTarget = keepScrollPosition ? 'preserve-scroll' : 'scroll-to-top-or-hash';
|
|
22
|
+
renderPageClientSide({
|
|
23
|
+
scrollTarget,
|
|
24
|
+
urlOriginal: url,
|
|
25
|
+
isBackwardNavigation: false
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
function isNormalLeftClick(ev) {
|
|
29
|
+
return ev.button === 0 && !ev.ctrlKey && !ev.shiftKey && !ev.altKey && !ev.metaKey;
|
|
30
|
+
}
|
|
31
|
+
function findLinkTag(target) {
|
|
32
|
+
while (target.tagName !== 'A') {
|
|
33
|
+
const { parentNode } = target;
|
|
34
|
+
if (!parentNode) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
target = parentNode;
|
|
38
|
+
}
|
|
39
|
+
return target;
|
|
40
|
+
}
|