-
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
81 additions
and
86 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,57 +1,54 @@ | ||
export { useConfig }; | ||
export type ConfigFromHookCumulative = (typeof configsCumulative)[number]; | ||
|
||
import type { PageContext } from "vike/types"; | ||
import type { PageContextInternal } from "../../types/PageContext.js"; | ||
import type { ConfigFromHook } from "../../types/Config.js"; | ||
import { usePageContext } from "../usePageContext.js"; | ||
import { getPageContext } from "vike/getPageContext"; | ||
import { objectKeys } from "../../utils/objectKeys.js"; | ||
import { includes } from "../../utils/includes.js"; | ||
|
||
/** | ||
* Set configurations inside React components and Vike hooks. | ||
* | ||
* https://vike.dev/useConfig | ||
*/ | ||
function useConfig(): (config: ConfigFromHook) => void { | ||
const configSetter = (config: ConfigFromHook) => setConfigOverPageContext(config, pageContext); | ||
|
||
// Vike hook | ||
let pageContext = getPageContext() as PageContext & PageContextInternal; | ||
if (pageContext) return configSetter; | ||
if (pageContext) return (config: ConfigFromHook) => setPageContextConfigFromHook(config, pageContext); | ||
|
||
// React component | ||
pageContext = usePageContext(); | ||
return (config: ConfigFromHook) => { | ||
if (!pageContext._headAlreadySet) { | ||
configSetter(config); | ||
setPageContextConfigFromHook(config, pageContext); | ||
} else { | ||
throw new Error("Using useConfig() with HTML streaming isn't supported yet"); | ||
} | ||
}; | ||
} | ||
|
||
const configsHtmlOnly = ["Head", "description", "image"] as const; | ||
const configsClientSide = ["title"]; | ||
const configsCumulative = ["Head"] as const; | ||
const configsOverridable = ["title", "description", "image"] as const; | ||
function setConfigOverPageContext(config: ConfigFromHook, pageContext: PageContext & PageContextInternal) { | ||
function setPageContextConfigFromHook(config: ConfigFromHook, pageContext: PageContext & PageContextInternal) { | ||
pageContext._configFromHook ??= {}; | ||
|
||
if (pageContext.isClientSideNavigation) { | ||
// Remove HTML only configs which the client-side doesn't need (also avoiding serialization errors) | ||
for (const configName of configsHtmlOnly) delete config[configName]; | ||
} | ||
|
||
// Cumulative values | ||
configsCumulative.forEach((configName) => { | ||
const configValue = config[configName]; | ||
if (!configValue) return; | ||
pageContext._configFromHook![configName] ??= []; | ||
pageContext._configFromHook![configName].push(configValue); | ||
}); | ||
|
||
// Overridable values | ||
configsOverridable.forEach((configName) => { | ||
const configValue = config[configName]; | ||
if (!configValue) return; | ||
pageContext._configFromHook![configName] = configValue; | ||
objectKeys(config).forEach((configName) => { | ||
// Skip HTML only configs which the client-side doesn't need, saving KBs sent to the client as well as avoiding serialization errors. | ||
if (pageContext.isClientSideNavigation && !configsClientSide.includes(configName)) return; | ||
|
||
if (!includes(configsCumulative, configName)) { | ||
// Overridable config | ||
const configValue = config[configName]; | ||
if (configValue === undefined) return; | ||
pageContext._configFromHook![configName] = configValue as any; | ||
} else { | ||
// Cumulative config | ||
const configValue = config[configName]; | ||
if (!configValue) return; | ||
pageContext._configFromHook![configName] ??= []; | ||
pageContext._configFromHook![configName].push(configValue as any); | ||
} | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
// https://stackoverflow.com/questions/56565528/typescript-const-assertions-how-to-use-array-prototype-includes/74213179#74213179 | ||
/** Same as Array.prototype.includes() but with type inference */ | ||
export function includes<T>(values: readonly T[], x: unknown): x is T { | ||
return values.includes(x as any); | ||
} | ||
/* | ||
export function includes<Arr extends any[] | readonly any[]>(arr: Arr, el: unknown): el is Arr[number] { | ||
return arr.includes(el as any) | ||
} | ||
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
// https://stackoverflow.com/questions/52856496/typescript-object-keys-return-string | ||
// https://github.com/sindresorhus/ts-extras/blob/main/source/object-keys.ts | ||
/** Same as Object.keys() but with type inference */ | ||
export function objectKeys<T extends object>(obj: T): (keyof T)[] { | ||
return Object.keys(obj) as any; | ||
} |