vike-react 0.5.1 → 0.5.2
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/components/Head/Head-client.d.ts +1 -11
- package/dist/components/Head/Head-client.js +2 -13
- package/dist/components/Head/Head-server.js +0 -1
- package/dist/hooks/useConfig/useConfig-client.js +7 -15
- package/dist/hooks/useConfig/useConfig-server.d.ts +2 -0
- package/dist/hooks/useConfig/useConfig-server.js +27 -27
- package/dist/renderer/getHeadSetting.d.ts +3 -2
- package/dist/renderer/getHeadSetting.js +5 -14
- package/dist/renderer/onRenderHtml.js +3 -3
- package/dist/types/Config.d.ts +11 -15
- package/dist/utils/includes.d.ts +2 -0
- package/dist/utils/includes.js +10 -0
- package/dist/utils/objectKeys.d.ts +2 -0
- package/dist/utils/objectKeys.js +6 -0
- package/package.json +16 -15
@@ -1,11 +1 @@
|
|
1
|
-
export
|
2
|
-
/**
|
3
|
-
* Add arbitrary `<head>` tags.
|
4
|
-
*
|
5
|
-
* (The children are teleported to `<head>`.)
|
6
|
-
*
|
7
|
-
* https://vike.dev/Head
|
8
|
-
*/
|
9
|
-
declare function Head({ children }: {
|
10
|
-
children: React.ReactNode;
|
11
|
-
}): null;
|
1
|
+
export declare function Head(): null;
|
@@ -1,15 +1,4 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
import { useConfig } from '../../hooks/useConfig/useConfig-client.js';
|
4
|
-
/**
|
5
|
-
* Add arbitrary `<head>` tags.
|
6
|
-
*
|
7
|
-
* (The children are teleported to `<head>`.)
|
8
|
-
*
|
9
|
-
* https://vike.dev/Head
|
10
|
-
*/
|
11
|
-
function Head({ children }) {
|
12
|
-
const config = useConfig();
|
13
|
-
config({ Head: children });
|
1
|
+
// https://vike.dev/Head#only-html
|
2
|
+
export function Head() {
|
14
3
|
return null;
|
15
4
|
}
|
@@ -7,35 +7,27 @@ import { getPageContext } from 'vike/getPageContext';
|
|
7
7
|
* https://vike.dev/useConfig
|
8
8
|
*/
|
9
9
|
function useConfig() {
|
10
|
-
const configSetter = (config) => setConfigOverPageContext(config, pageContext);
|
11
10
|
// Vike hook
|
12
11
|
let pageContext = getPageContext();
|
13
12
|
if (pageContext)
|
14
|
-
return
|
13
|
+
return (config) => setPageContextConfigFromHook(config, pageContext);
|
15
14
|
// React component
|
16
15
|
pageContext = usePageContext();
|
17
16
|
return (config) => {
|
18
17
|
if (!('_headAlreadySet' in pageContext)) {
|
19
|
-
|
18
|
+
setPageContextConfigFromHook(config, pageContext);
|
20
19
|
}
|
21
20
|
else {
|
22
|
-
|
21
|
+
apply(config);
|
23
22
|
}
|
24
23
|
};
|
25
24
|
}
|
26
|
-
|
27
|
-
function setConfigOverPageContext(config, pageContext) {
|
25
|
+
function setPageContextConfigFromHook(config, pageContext) {
|
28
26
|
pageContext._configFromHook ?? (pageContext._configFromHook = {});
|
29
|
-
|
30
|
-
const configValue = config[configName];
|
31
|
-
if (!configValue)
|
32
|
-
return;
|
33
|
-
pageContext._configFromHook[configName] = configValue;
|
34
|
-
});
|
27
|
+
Object.assign(pageContext._configFromHook, config);
|
35
28
|
}
|
36
|
-
function
|
29
|
+
function apply(config) {
|
37
30
|
const { title } = config;
|
38
|
-
if (title)
|
31
|
+
if (title)
|
39
32
|
window.document.title = title;
|
40
|
-
}
|
41
33
|
}
|
@@ -1,4 +1,5 @@
|
|
1
1
|
export { useConfig };
|
2
|
+
export type ConfigFromHookCumulative = (typeof configsCumulative)[number];
|
2
3
|
import type { ConfigFromHook } from '../../types/Config.js';
|
3
4
|
/**
|
4
5
|
* Set configurations inside React components and Vike hooks.
|
@@ -6,3 +7,4 @@ import type { ConfigFromHook } from '../../types/Config.js';
|
|
6
7
|
* https://vike.dev/useConfig
|
7
8
|
*/
|
8
9
|
declare function useConfig(): (config: ConfigFromHook) => void;
|
10
|
+
declare const configsCumulative: readonly ["Head", "bodyAttributes", "htmlAttributes"];
|
@@ -2,58 +2,58 @@ export { useConfig };
|
|
2
2
|
import { usePageContext } from '../usePageContext.js';
|
3
3
|
import { getPageContext } from 'vike/getPageContext';
|
4
4
|
import { useStream } from 'react-streaming';
|
5
|
+
import { objectKeys } from '../../utils/objectKeys.js';
|
6
|
+
import { includes } from '../../utils/includes.js';
|
5
7
|
/**
|
6
8
|
* Set configurations inside React components and Vike hooks.
|
7
9
|
*
|
8
10
|
* https://vike.dev/useConfig
|
9
11
|
*/
|
10
12
|
function useConfig() {
|
11
|
-
const configSetter = (config) => setConfigOverPageContext(config, pageContext);
|
12
13
|
// Vike hook
|
13
14
|
let pageContext = getPageContext();
|
14
15
|
if (pageContext)
|
15
|
-
return
|
16
|
+
return (config) => setPageContextConfigFromHook(config, pageContext);
|
16
17
|
// React component
|
17
18
|
pageContext = usePageContext();
|
18
19
|
const stream = useStream();
|
19
20
|
return (config) => {
|
20
21
|
if (!pageContext._headAlreadySet) {
|
21
|
-
|
22
|
+
setPageContextConfigFromHook(config, pageContext);
|
22
23
|
}
|
23
24
|
else {
|
24
25
|
// <head> already sent to the browser => send DOM-manipulating scripts during HTML streaming
|
25
|
-
|
26
|
+
apply(config, stream);
|
26
27
|
}
|
27
28
|
};
|
28
29
|
}
|
29
|
-
const
|
30
|
-
const configsCumulative = ['Head'];
|
31
|
-
|
32
|
-
function setConfigOverPageContext(config, pageContext) {
|
30
|
+
const configsClientSide = ['title'];
|
31
|
+
const configsCumulative = ['Head', 'bodyAttributes', 'htmlAttributes'];
|
32
|
+
function setPageContextConfigFromHook(config, pageContext) {
|
33
33
|
pageContext._configFromHook ?? (pageContext._configFromHook = {});
|
34
|
-
|
35
|
-
// Remove HTML only configs which the client-side doesn't need (also avoiding serialization errors)
|
36
|
-
for (const configName of configsHtmlOnly)
|
37
|
-
delete config[configName];
|
38
|
-
}
|
39
|
-
// Cumulative values
|
40
|
-
configsCumulative.forEach((configName) => {
|
34
|
+
objectKeys(config).forEach((configName) => {
|
41
35
|
var _a;
|
42
|
-
|
43
|
-
if (!
|
44
|
-
return;
|
45
|
-
(_a = pageContext._configFromHook)[configName] ?? (_a[configName] = []);
|
46
|
-
pageContext._configFromHook[configName].push(configValue);
|
47
|
-
});
|
48
|
-
// Overridable values
|
49
|
-
configsOverridable.forEach((configName) => {
|
50
|
-
const configValue = config[configName];
|
51
|
-
if (!configValue)
|
36
|
+
// Skip HTML only configs which the client-side doesn't need, saving KBs sent to the client as well as avoiding serialization errors.
|
37
|
+
if (pageContext.isClientSideNavigation && !configsClientSide.includes(configName))
|
52
38
|
return;
|
53
|
-
|
39
|
+
if (!includes(configsCumulative, configName)) {
|
40
|
+
// Overridable config
|
41
|
+
const configValue = config[configName];
|
42
|
+
if (configValue === undefined)
|
43
|
+
return;
|
44
|
+
pageContext._configFromHook[configName] = configValue;
|
45
|
+
}
|
46
|
+
else {
|
47
|
+
// Cumulative config
|
48
|
+
const configValue = config[configName];
|
49
|
+
if (!configValue)
|
50
|
+
return;
|
51
|
+
(_a = pageContext._configFromHook)[configName] ?? (_a[configName] = []);
|
52
|
+
pageContext._configFromHook[configName].push(configValue);
|
53
|
+
}
|
54
54
|
});
|
55
55
|
}
|
56
|
-
function
|
56
|
+
function apply(config, stream) {
|
57
57
|
const { title } = config;
|
58
58
|
if (title) {
|
59
59
|
const htmlSnippet = `<script>document.title = ${JSON.stringify(title)}</script>`;
|
@@ -1,5 +1,6 @@
|
|
1
1
|
export { getHeadSetting };
|
2
2
|
import type { PageContext } from 'vike/types';
|
3
3
|
import type { PageContextInternal } from '../types/PageContext.js';
|
4
|
-
type
|
5
|
-
|
4
|
+
import type { ConfigFromHookResolved } from '../types/Config.js';
|
5
|
+
type HeadSetting = Exclude<keyof ConfigFromHookResolved, 'Head'>;
|
6
|
+
declare function getHeadSetting<T>(headSetting: HeadSetting, pageContext: PageContext & PageContextInternal): undefined | T;
|
@@ -1,27 +1,18 @@
|
|
1
1
|
export { getHeadSetting };
|
2
2
|
import { isCallable } from '../utils/isCallable.js';
|
3
3
|
function getHeadSetting(headSetting, pageContext) {
|
4
|
+
// Set by useConfig()
|
4
5
|
{
|
5
6
|
const val = pageContext._configFromHook?.[headSetting];
|
6
7
|
if (val !== undefined)
|
7
8
|
return val;
|
8
9
|
}
|
9
|
-
|
10
|
-
|
11
|
-
return undefined;
|
12
|
-
const val = config.configValue;
|
13
|
-
if (typeof val === 'string')
|
14
|
-
return val;
|
15
|
-
if (!val)
|
16
|
-
return null;
|
10
|
+
// Set by +configName.js
|
11
|
+
const val = pageContext.config[headSetting];
|
17
12
|
if (isCallable(val)) {
|
18
|
-
|
19
|
-
if (typeof valStr !== 'string') {
|
20
|
-
throw new Error(config.configDefinedAt + ' should return a string');
|
21
|
-
}
|
22
|
-
return valStr;
|
13
|
+
return val(pageContext);
|
23
14
|
}
|
24
15
|
else {
|
25
|
-
|
16
|
+
return val;
|
26
17
|
}
|
27
18
|
}
|
@@ -64,6 +64,7 @@ function getHeadHtml(pageContext) {
|
|
64
64
|
const imageTags = !image
|
65
65
|
? ''
|
66
66
|
: escapeInject `<meta property="og:image" content="${image}"><meta name="twitter:card" content="summary_large_image">`;
|
67
|
+
const viewportTag = dangerouslySkipEscape(getViewportTag(getHeadSetting('viewport', pageContext)));
|
67
68
|
const headElementsHtml = dangerouslySkipEscape([
|
68
69
|
// Added by +Head
|
69
70
|
...(pageContext.config.Head ?? []),
|
@@ -75,7 +76,6 @@ function getHeadHtml(pageContext) {
|
|
75
76
|
.join('\n'));
|
76
77
|
// Not needed on the client-side, thus we remove it to save KBs sent to the client
|
77
78
|
delete pageContext._configFromHook;
|
78
|
-
const viewportTag = dangerouslySkipEscape(getViewportTag(pageContext.config.viewport));
|
79
79
|
const headHtml = escapeInject `
|
80
80
|
${titleTags}
|
81
81
|
${viewportTag}
|
@@ -105,8 +105,8 @@ function getTagAttributes(pageContext) {
|
|
105
105
|
// Don't set `lang` to its default value if it's `null` (so that users can set it to `null` in order to remove the default value)
|
106
106
|
if (lang === undefined)
|
107
107
|
lang = 'en';
|
108
|
-
const bodyAttributes = mergeTagAttributesList(pageContext
|
109
|
-
const htmlAttributes = mergeTagAttributesList(pageContext
|
108
|
+
const bodyAttributes = mergeTagAttributesList(getHeadSetting('bodyAttributes', pageContext));
|
109
|
+
const htmlAttributes = mergeTagAttributesList(getHeadSetting('htmlAttributes', pageContext));
|
110
110
|
const bodyAttributesString = getTagAttributesString(bodyAttributes);
|
111
111
|
const htmlAttributesString = getTagAttributesString({ ...htmlAttributes, lang: lang ?? htmlAttributes.lang });
|
112
112
|
return { htmlAttributesString, bodyAttributesString };
|
package/dist/types/Config.d.ts
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
import type { ImportString, PageContextClient, PageContext as PageContext_, PageContextServer } from 'vike/types';
|
2
2
|
import type { TagAttributes } from '../utils/getTagAttributesString.js';
|
3
3
|
import type { Viewport } from '../renderer/onRenderHtml.js';
|
4
|
+
import type { ConfigFromHookCumulative } from '../hooks/useConfig/useConfig-server.js';
|
4
5
|
declare global {
|
5
6
|
namespace Vike {
|
6
7
|
interface Config {
|
@@ -43,7 +44,7 @@ declare global {
|
|
43
44
|
*
|
44
45
|
* https://vike.dev/title
|
45
46
|
*/
|
46
|
-
title?: string | ((pageContext: PageContext_) => string);
|
47
|
+
title?: string | null | ((pageContext: PageContext_) => string | null | undefined);
|
47
48
|
/**
|
48
49
|
* Set the page's description.
|
49
50
|
*
|
@@ -57,7 +58,7 @@ declare global {
|
|
57
58
|
*
|
58
59
|
* https://vike.dev/description
|
59
60
|
*/
|
60
|
-
description?: string | ((pageContext: PageContextServer) => string);
|
61
|
+
description?: string | null | ((pageContext: PageContextServer) => string | null | undefined);
|
61
62
|
/**
|
62
63
|
* Set the page's preview image upon URL sharing.
|
63
64
|
*
|
@@ -71,7 +72,7 @@ declare global {
|
|
71
72
|
*
|
72
73
|
* https://vike.dev/image
|
73
74
|
*/
|
74
|
-
image?: string | ((pageContext: PageContextServer) => string);
|
75
|
+
image?: string | null | ((pageContext: PageContextServer) => string | null | undefined);
|
75
76
|
/**
|
76
77
|
* Set the page's width shown to the user on mobile/tablet devices.
|
77
78
|
*
|
@@ -79,7 +80,7 @@ declare global {
|
|
79
80
|
*
|
80
81
|
* https://vike.dev/viewport
|
81
82
|
*/
|
82
|
-
viewport?: Viewport;
|
83
|
+
viewport?: Viewport | ((pageContext: PageContextServer) => Viewport | undefined);
|
83
84
|
/**
|
84
85
|
* Set the page's favicon.
|
85
86
|
*
|
@@ -92,7 +93,7 @@ declare global {
|
|
92
93
|
*
|
93
94
|
* https://vike.dev/favicon
|
94
95
|
*/
|
95
|
-
favicon?: string | ((pageContext: PageContextServer) => string);
|
96
|
+
favicon?: string | null | ((pageContext: PageContextServer) => string | null | undefined);
|
96
97
|
/**
|
97
98
|
* Set the page's language (`<html lang>`).
|
98
99
|
*
|
@@ -100,19 +101,19 @@ declare global {
|
|
100
101
|
*
|
101
102
|
* https://vike.dev/lang
|
102
103
|
*/
|
103
|
-
lang?: string | ((pageContext: PageContext_) => string);
|
104
|
+
lang?: string | null | ((pageContext: PageContext_) => string | null | undefined);
|
104
105
|
/**
|
105
106
|
* Add tag attributes such as `<html class="dark">`.
|
106
107
|
*
|
107
108
|
* https://vike.dev/htmlAttributes
|
108
109
|
*/
|
109
|
-
htmlAttributes?: TagAttributes;
|
110
|
+
htmlAttributes?: TagAttributes | ((pageContext: PageContextServer) => TagAttributes | undefined);
|
110
111
|
/**
|
111
112
|
* Add tag attributes such as `<body class="dark">`.
|
112
113
|
*
|
113
114
|
* https://vike.dev/bodyAttributes
|
114
115
|
*/
|
115
|
-
bodyAttributes?: TagAttributes;
|
116
|
+
bodyAttributes?: TagAttributes | ((pageContext: PageContextServer) => TagAttributes | undefined);
|
116
117
|
/**
|
117
118
|
* If `true`, the page is rendered twice: on the server-side (to HTML) and on the client-side (hydration).
|
118
119
|
*
|
@@ -193,11 +194,6 @@ type Loading = {
|
|
193
194
|
type PickWithoutGetter<T, K extends keyof T> = {
|
194
195
|
[P in K]: Exclude<T[P], Function>;
|
195
196
|
};
|
196
|
-
export type ConfigFromHook = PickWithoutGetter<Vike.Config, 'Head' | 'title' | 'description' | 'image'>;
|
197
|
-
export type ConfigFromHookResolved =
|
198
|
-
Head?: Head[];
|
199
|
-
title?: string;
|
200
|
-
description?: string;
|
201
|
-
image?: string;
|
202
|
-
};
|
197
|
+
export type ConfigFromHook = PickWithoutGetter<Vike.Config, 'Head' | 'title' | 'description' | 'image' | 'favicon' | 'lang' | 'viewport' | 'bodyAttributes' | 'htmlAttributes'>;
|
198
|
+
export type ConfigFromHookResolved = Omit<ConfigFromHook, ConfigFromHookCumulative> & Pick<Vike.ConfigResolved, ConfigFromHookCumulative>;
|
203
199
|
export {};
|
@@ -0,0 +1,10 @@
|
|
1
|
+
// https://stackoverflow.com/questions/56565528/typescript-const-assertions-how-to-use-array-prototype-includes/74213179#74213179
|
2
|
+
/** Same as Array.prototype.includes() but with type inference */
|
3
|
+
export function includes(values, x) {
|
4
|
+
return values.includes(x);
|
5
|
+
}
|
6
|
+
/*
|
7
|
+
export function includes<Arr extends any[] | readonly any[]>(arr: Arr, el: unknown): el is Arr[number] {
|
8
|
+
return arr.includes(el as any)
|
9
|
+
}
|
10
|
+
*/
|
@@ -0,0 +1,6 @@
|
|
1
|
+
// https://stackoverflow.com/questions/52856496/typescript-object-keys-return-string
|
2
|
+
// https://github.com/sindresorhus/ts-extras/blob/main/source/object-keys.ts
|
3
|
+
/** Same as Object.keys() but with type inference */
|
4
|
+
export function objectKeys(obj) {
|
5
|
+
return Object.keys(obj);
|
6
|
+
}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "vike-react",
|
3
|
-
"version": "0.5.
|
3
|
+
"version": "0.5.2",
|
4
4
|
"type": "module",
|
5
5
|
"main": "./dist/index.js",
|
6
6
|
"types": "./dist/index.d.ts",
|
@@ -11,15 +11,15 @@
|
|
11
11
|
"browser": "./dist/hooks/useConfig/useConfig-client.js",
|
12
12
|
"default": "./dist/hooks/useConfig/useConfig-server.js"
|
13
13
|
},
|
14
|
-
"./ClientOnly": "./dist/components/ClientOnly.js",
|
15
|
-
"./Head": {
|
16
|
-
"browser": "./dist/components/Head/Head-client.js",
|
17
|
-
"default": "./dist/components/Head/Head-server.js"
|
18
|
-
},
|
19
14
|
"./Config": {
|
20
15
|
"browser": "./dist/components/Config/Config-client.js",
|
21
16
|
"default": "./dist/components/Config/Config-server.js"
|
22
17
|
},
|
18
|
+
"./Head": {
|
19
|
+
"browser": "./dist/components/Head/Head-client.js",
|
20
|
+
"default": "./dist/components/Head/Head-server.js"
|
21
|
+
},
|
22
|
+
"./ClientOnly": "./dist/components/ClientOnly.js",
|
23
23
|
"./clientOnly": "./dist/helpers/clientOnly.js",
|
24
24
|
".": "./dist/index.js",
|
25
25
|
"./config": "./dist/+config.js",
|
@@ -38,8 +38,7 @@
|
|
38
38
|
"peerDependencies": {
|
39
39
|
"react": ">=18.0.0",
|
40
40
|
"react-dom": ">=18.0.0",
|
41
|
-
"vike": ">=0.4.182"
|
42
|
-
"vite": ">=4.3.8"
|
41
|
+
"vike": ">=0.4.182"
|
43
42
|
},
|
44
43
|
"devDependencies": {
|
45
44
|
"@biomejs/biome": "^1.6.4",
|
@@ -47,11 +46,13 @@
|
|
47
46
|
"@types/node": "^20.11.17",
|
48
47
|
"@types/react": "^18.2.55",
|
49
48
|
"@types/react-dom": "^18.2.19",
|
50
|
-
"react": "^18.
|
51
|
-
"react-dom": "^18.
|
49
|
+
"react": "^18.3.1",
|
50
|
+
"react-dom": "^18.3.1",
|
51
|
+
"react-streaming": "^0.3.43",
|
52
52
|
"rimraf": "^5.0.5",
|
53
|
-
"typescript": "^5.5.
|
54
|
-
"vike": "^0.4.
|
53
|
+
"typescript": "^5.5.4",
|
54
|
+
"vike": "^0.4.183",
|
55
|
+
"vite": "^5.4.0"
|
55
56
|
},
|
56
57
|
"dependencies": {
|
57
58
|
"react-streaming": "^0.3.42"
|
@@ -67,12 +68,12 @@
|
|
67
68
|
"useConfig": [
|
68
69
|
"./dist/hooks/useConfig/useConfig-server.d.ts"
|
69
70
|
],
|
70
|
-
"Head": [
|
71
|
-
"./dist/components/Head/Head-server.d.ts"
|
72
|
-
],
|
73
71
|
"Config": [
|
74
72
|
"./dist/components/Config/Config-server.d.ts"
|
75
73
|
],
|
74
|
+
"Head": [
|
75
|
+
"./dist/components/Head/Head-server.d.ts"
|
76
|
+
],
|
76
77
|
"ClientOnly": [
|
77
78
|
"./dist/components/ClientOnly.d.ts"
|
78
79
|
],
|