sygnal 5.3.4 → 5.3.5
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/index.d.ts +28 -23
- package/dist/vike/onRenderHtml.cjs.js +23 -1
- package/dist/vike/onRenderHtml.mjs +23 -1
- package/package.json +1 -1
- package/src/index.d.ts +28 -23
- package/src/vike/onRenderHtml.ts +23 -1
package/dist/index.d.ts
CHANGED
|
@@ -42,11 +42,13 @@ type NextFunction<ACTIONS = any> = ACTIONS extends object
|
|
|
42
42
|
) => void
|
|
43
43
|
: (action: string, data?: any, delay?: number) => void
|
|
44
44
|
|
|
45
|
-
type
|
|
45
|
+
type ReducerExtras<PROPS, CONTEXT> = PROPS & { context: CONTEXT; children?: JSX.Element | JSX.Element[]; slots?: Record<string, JSX.Element[]> }
|
|
46
|
+
|
|
47
|
+
type Reducer<STATE, PROPS, ACTIONS = any, DATA = any, RETURN = any, CONTEXT = {}> = (
|
|
46
48
|
state: STATE,
|
|
47
49
|
args: DATA,
|
|
48
50
|
next: NextFunction<ACTIONS>,
|
|
49
|
-
props: PROPS
|
|
51
|
+
props: ReducerExtras<PROPS, CONTEXT>
|
|
50
52
|
) => RETURN | ABORT | undefined
|
|
51
53
|
|
|
52
54
|
export type ExactShape<EXPECTED, ACTUAL extends EXPECTED> = ACTUAL &
|
|
@@ -76,24 +78,24 @@ type ResolvedNonStateSinkReturns<SINK_RETURNS extends NonStateSinkReturns = {}>
|
|
|
76
78
|
* - true: Whatever value is received from the intent for this action is passed on as-is.
|
|
77
79
|
* - Function: A reducer
|
|
78
80
|
*/
|
|
79
|
-
type SinkValue<STATE, PROPS, ACTIONS, DATA, RETURN, CALCULATED> =
|
|
81
|
+
type SinkValue<STATE, PROPS, ACTIONS, DATA, RETURN, CALCULATED, CONTEXT = {}> =
|
|
80
82
|
| true
|
|
81
|
-
| Reducer<STATE & CALCULATED, PROPS, ACTIONS, DATA, RETURN>
|
|
83
|
+
| Reducer<STATE & CALCULATED, PROPS, ACTIONS, DATA, RETURN, CONTEXT>
|
|
82
84
|
|
|
83
|
-
type EffectReducer<STATE, PROPS, ACTIONS, DATA, CALCULATED> =
|
|
84
|
-
| ((state: STATE & CALCULATED, args: DATA, next: NextFunction<ACTIONS>, props: PROPS) => void)
|
|
85
|
+
type EffectReducer<STATE, PROPS, ACTIONS, DATA, CALCULATED, CONTEXT = {}> =
|
|
86
|
+
| ((state: STATE & CALCULATED, args: DATA, next: NextFunction<ACTIONS>, props: ReducerExtras<PROPS, CONTEXT>) => void)
|
|
85
87
|
|
|
86
|
-
type DefaultSinks<STATE, PROPS, ACTIONS, DATA, CALCULATED, SINK_RETURNS extends NonStateSinkReturns = {}> = {
|
|
87
|
-
STATE?: SinkValue<STATE, PROPS, ACTIONS, DATA, STATE, CALCULATED>;
|
|
88
|
-
EVENTS?: SinkValue<STATE, PROPS, ACTIONS, DATA, ResolvedNonStateSinkReturns<SINK_RETURNS>['EVENTS'], CALCULATED>;
|
|
89
|
-
LOG?: SinkValue<STATE, PROPS, ACTIONS, DATA, ResolvedNonStateSinkReturns<SINK_RETURNS>['LOG'], CALCULATED>;
|
|
90
|
-
PARENT?: SinkValue<STATE, PROPS, ACTIONS, DATA, ResolvedNonStateSinkReturns<SINK_RETURNS>['PARENT'], CALCULATED>;
|
|
91
|
-
EFFECT?: EffectReducer<STATE, PROPS, ACTIONS, DATA, CALCULATED>;
|
|
88
|
+
type DefaultSinks<STATE, PROPS, ACTIONS, DATA, CALCULATED, SINK_RETURNS extends NonStateSinkReturns = {}, CONTEXT = {}> = {
|
|
89
|
+
STATE?: SinkValue<STATE, PROPS, ACTIONS, DATA, STATE, CALCULATED, CONTEXT>;
|
|
90
|
+
EVENTS?: SinkValue<STATE, PROPS, ACTIONS, DATA, ResolvedNonStateSinkReturns<SINK_RETURNS>['EVENTS'], CALCULATED, CONTEXT>;
|
|
91
|
+
LOG?: SinkValue<STATE, PROPS, ACTIONS, DATA, ResolvedNonStateSinkReturns<SINK_RETURNS>['LOG'], CALCULATED, CONTEXT>;
|
|
92
|
+
PARENT?: SinkValue<STATE, PROPS, ACTIONS, DATA, ResolvedNonStateSinkReturns<SINK_RETURNS>['PARENT'], CALCULATED, CONTEXT>;
|
|
93
|
+
EFFECT?: EffectReducer<STATE, PROPS, ACTIONS, DATA, CALCULATED, CONTEXT>;
|
|
92
94
|
}
|
|
93
95
|
|
|
94
|
-
type CustomDriverSinks<STATE, PROPS, DRIVERS, ACTIONS, ACTION_ENTRY, CALCULATED> = keyof DRIVERS extends never
|
|
96
|
+
type CustomDriverSinks<STATE, PROPS, DRIVERS, ACTIONS, ACTION_ENTRY, CALCULATED, CONTEXT = {}> = keyof DRIVERS extends never
|
|
95
97
|
? {
|
|
96
|
-
[driver: string]: SinkValue<STATE, PROPS, ACTIONS, any, any, CALCULATED>
|
|
98
|
+
[driver: string]: SinkValue<STATE, PROPS, ACTIONS, any, any, CALCULATED, CONTEXT>
|
|
97
99
|
}
|
|
98
100
|
: {
|
|
99
101
|
[DRIVER_KEY in keyof DRIVERS]: SinkValue<
|
|
@@ -102,15 +104,16 @@ type CustomDriverSinks<STATE, PROPS, DRIVERS, ACTIONS, ACTION_ENTRY, CALCULATED>
|
|
|
102
104
|
ACTIONS,
|
|
103
105
|
ACTION_ENTRY,
|
|
104
106
|
DRIVERS[DRIVER_KEY] extends { source: any; sink: any } ? DRIVERS[DRIVER_KEY]['sink'] : any,
|
|
105
|
-
CALCULATED
|
|
107
|
+
CALCULATED,
|
|
108
|
+
CONTEXT
|
|
106
109
|
>
|
|
107
110
|
}
|
|
108
111
|
|
|
109
|
-
type ModelEntry<STATE, PROPS, DRIVERS, ACTIONS, ACTION_ENTRY, CALCULATED, SINK_RETURNS extends NonStateSinkReturns = {}> =
|
|
110
|
-
| SinkValue<STATE, PROPS, ACTIONS, ACTION_ENTRY, STATE, CALCULATED>
|
|
112
|
+
type ModelEntry<STATE, PROPS, DRIVERS, ACTIONS, ACTION_ENTRY, CALCULATED, SINK_RETURNS extends NonStateSinkReturns = {}, CONTEXT = {}> =
|
|
113
|
+
| SinkValue<STATE, PROPS, ACTIONS, ACTION_ENTRY, STATE, CALCULATED, CONTEXT>
|
|
111
114
|
| Partial<
|
|
112
|
-
DefaultSinks<STATE, PROPS, ACTIONS, ACTION_ENTRY, CALCULATED, SINK_RETURNS> &
|
|
113
|
-
CustomDriverSinks<STATE, PROPS, DRIVERS, ACTIONS, ACTION_ENTRY, CALCULATED>
|
|
115
|
+
DefaultSinks<STATE, PROPS, ACTIONS, ACTION_ENTRY, CALCULATED, SINK_RETURNS, CONTEXT> &
|
|
116
|
+
CustomDriverSinks<STATE, PROPS, DRIVERS, ACTIONS, ACTION_ENTRY, CALCULATED, CONTEXT>
|
|
114
117
|
>
|
|
115
118
|
|
|
116
119
|
type WithDefaultActions<STATE, ACTIONS> = ACTIONS & {
|
|
@@ -120,7 +123,7 @@ type WithDefaultActions<STATE, ACTIONS> = ACTIONS & {
|
|
|
120
123
|
DISPOSE?: never;
|
|
121
124
|
}
|
|
122
125
|
|
|
123
|
-
type ComponentModel<STATE, PROPS, DRIVERS, ACTIONS, CALCULATED, SINK_RETURNS extends NonStateSinkReturns = {}> = keyof ACTIONS extends never
|
|
126
|
+
type ComponentModel<STATE, PROPS, DRIVERS, ACTIONS, CALCULATED, SINK_RETURNS extends NonStateSinkReturns = {}, CONTEXT = {}> = keyof ACTIONS extends never
|
|
124
127
|
? {
|
|
125
128
|
[action: string]: ModelEntry<
|
|
126
129
|
STATE,
|
|
@@ -129,7 +132,8 @@ type ComponentModel<STATE, PROPS, DRIVERS, ACTIONS, CALCULATED, SINK_RETURNS ext
|
|
|
129
132
|
WithDefaultActions<STATE, { [action: string]: any }>,
|
|
130
133
|
any,
|
|
131
134
|
CALCULATED,
|
|
132
|
-
SINK_RETURNS
|
|
135
|
+
SINK_RETURNS,
|
|
136
|
+
CONTEXT
|
|
133
137
|
>
|
|
134
138
|
}
|
|
135
139
|
: {
|
|
@@ -140,7 +144,8 @@ type ComponentModel<STATE, PROPS, DRIVERS, ACTIONS, CALCULATED, SINK_RETURNS ext
|
|
|
140
144
|
WithDefaultActions<STATE, ACTIONS>,
|
|
141
145
|
WithDefaultActions<STATE, ACTIONS>[ACTION_KEY],
|
|
142
146
|
CALCULATED,
|
|
143
|
-
SINK_RETURNS
|
|
147
|
+
SINK_RETURNS,
|
|
148
|
+
CONTEXT
|
|
144
149
|
>
|
|
145
150
|
}
|
|
146
151
|
|
|
@@ -259,7 +264,7 @@ export type Component<
|
|
|
259
264
|
DOMSourceName?: string;
|
|
260
265
|
stateSourceName?: string;
|
|
261
266
|
requestSourceName?: string;
|
|
262
|
-
model?: ComponentModel<STATE, PROPS, FixDrivers<DRIVERS>, ACTIONS, CALCULATED, SINK_RETURNS>;
|
|
267
|
+
model?: ComponentModel<STATE, PROPS, FixDrivers<DRIVERS>, ACTIONS, CALCULATED, SINK_RETURNS, CONTEXT>;
|
|
263
268
|
intent?: ComponentIntent<STATE & CALCULATED, FixDrivers<DRIVERS>, ACTIONS>;
|
|
264
269
|
initialState?: STATE;
|
|
265
270
|
calculated?: Calculated<STATE, CALCULATED>;
|
|
@@ -31,17 +31,39 @@ function esc(str) {
|
|
|
31
31
|
function onRenderHtml(pageContext) {
|
|
32
32
|
const { Page, config } = pageContext;
|
|
33
33
|
const data = pageContext.data || {};
|
|
34
|
-
// SPA mode: return empty shell, let the client render everything
|
|
34
|
+
// SPA mode: return empty shell, let the client render everything.
|
|
35
|
+
// Head component and meta tags are still included — they're static
|
|
36
|
+
// metadata that should be present regardless of SSR being disabled.
|
|
35
37
|
if (config.ssr === false) {
|
|
36
38
|
const lang = config.lang || 'en';
|
|
37
39
|
const title = config.title || '';
|
|
40
|
+
const description = config.description || '';
|
|
41
|
+
const favicon = config.favicon || '';
|
|
38
42
|
const titleTag = title ? `<title>${esc(title)}</title>` : '';
|
|
43
|
+
const descTag = description
|
|
44
|
+
? `<meta name="description" content="${esc(description)}">`
|
|
45
|
+
: '';
|
|
46
|
+
const faviconTag = favicon
|
|
47
|
+
? `<link rel="icon" href="${esc(favicon)}">`
|
|
48
|
+
: '';
|
|
49
|
+
let headContent = '';
|
|
50
|
+
if (config.Head && typeof config.Head === 'function') {
|
|
51
|
+
try {
|
|
52
|
+
headContent = sygnal.renderToString(config.Head, { state: {} });
|
|
53
|
+
}
|
|
54
|
+
catch (_) {
|
|
55
|
+
// Head rendering failure is non-fatal
|
|
56
|
+
}
|
|
57
|
+
}
|
|
39
58
|
const spaHtml = `<!DOCTYPE html>
|
|
40
59
|
<html lang="${lang}">
|
|
41
60
|
<head>
|
|
42
61
|
<meta charset="UTF-8">
|
|
43
62
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
44
63
|
${titleTag}
|
|
64
|
+
${descTag}
|
|
65
|
+
${faviconTag}
|
|
66
|
+
${headContent}
|
|
45
67
|
</head>
|
|
46
68
|
<body>
|
|
47
69
|
<div id="page-view"></div>
|
|
@@ -29,17 +29,39 @@ function esc(str) {
|
|
|
29
29
|
function onRenderHtml(pageContext) {
|
|
30
30
|
const { Page, config } = pageContext;
|
|
31
31
|
const data = pageContext.data || {};
|
|
32
|
-
// SPA mode: return empty shell, let the client render everything
|
|
32
|
+
// SPA mode: return empty shell, let the client render everything.
|
|
33
|
+
// Head component and meta tags are still included — they're static
|
|
34
|
+
// metadata that should be present regardless of SSR being disabled.
|
|
33
35
|
if (config.ssr === false) {
|
|
34
36
|
const lang = config.lang || 'en';
|
|
35
37
|
const title = config.title || '';
|
|
38
|
+
const description = config.description || '';
|
|
39
|
+
const favicon = config.favicon || '';
|
|
36
40
|
const titleTag = title ? `<title>${esc(title)}</title>` : '';
|
|
41
|
+
const descTag = description
|
|
42
|
+
? `<meta name="description" content="${esc(description)}">`
|
|
43
|
+
: '';
|
|
44
|
+
const faviconTag = favicon
|
|
45
|
+
? `<link rel="icon" href="${esc(favicon)}">`
|
|
46
|
+
: '';
|
|
47
|
+
let headContent = '';
|
|
48
|
+
if (config.Head && typeof config.Head === 'function') {
|
|
49
|
+
try {
|
|
50
|
+
headContent = renderToString(config.Head, { state: {} });
|
|
51
|
+
}
|
|
52
|
+
catch (_) {
|
|
53
|
+
// Head rendering failure is non-fatal
|
|
54
|
+
}
|
|
55
|
+
}
|
|
37
56
|
const spaHtml = `<!DOCTYPE html>
|
|
38
57
|
<html lang="${lang}">
|
|
39
58
|
<head>
|
|
40
59
|
<meta charset="UTF-8">
|
|
41
60
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
42
61
|
${titleTag}
|
|
62
|
+
${descTag}
|
|
63
|
+
${faviconTag}
|
|
64
|
+
${headContent}
|
|
43
65
|
</head>
|
|
44
66
|
<body>
|
|
45
67
|
<div id="page-view"></div>
|
package/package.json
CHANGED
package/src/index.d.ts
CHANGED
|
@@ -42,11 +42,13 @@ type NextFunction<ACTIONS = any> = ACTIONS extends object
|
|
|
42
42
|
) => void
|
|
43
43
|
: (action: string, data?: any, delay?: number) => void
|
|
44
44
|
|
|
45
|
-
type
|
|
45
|
+
type ReducerExtras<PROPS, CONTEXT> = PROPS & { context: CONTEXT; children?: JSX.Element | JSX.Element[]; slots?: Record<string, JSX.Element[]> }
|
|
46
|
+
|
|
47
|
+
type Reducer<STATE, PROPS, ACTIONS = any, DATA = any, RETURN = any, CONTEXT = {}> = (
|
|
46
48
|
state: STATE,
|
|
47
49
|
args: DATA,
|
|
48
50
|
next: NextFunction<ACTIONS>,
|
|
49
|
-
props: PROPS
|
|
51
|
+
props: ReducerExtras<PROPS, CONTEXT>
|
|
50
52
|
) => RETURN | ABORT | undefined
|
|
51
53
|
|
|
52
54
|
export type ExactShape<EXPECTED, ACTUAL extends EXPECTED> = ACTUAL &
|
|
@@ -76,24 +78,24 @@ type ResolvedNonStateSinkReturns<SINK_RETURNS extends NonStateSinkReturns = {}>
|
|
|
76
78
|
* - true: Whatever value is received from the intent for this action is passed on as-is.
|
|
77
79
|
* - Function: A reducer
|
|
78
80
|
*/
|
|
79
|
-
type SinkValue<STATE, PROPS, ACTIONS, DATA, RETURN, CALCULATED> =
|
|
81
|
+
type SinkValue<STATE, PROPS, ACTIONS, DATA, RETURN, CALCULATED, CONTEXT = {}> =
|
|
80
82
|
| true
|
|
81
|
-
| Reducer<STATE & CALCULATED, PROPS, ACTIONS, DATA, RETURN>
|
|
83
|
+
| Reducer<STATE & CALCULATED, PROPS, ACTIONS, DATA, RETURN, CONTEXT>
|
|
82
84
|
|
|
83
|
-
type EffectReducer<STATE, PROPS, ACTIONS, DATA, CALCULATED> =
|
|
84
|
-
| ((state: STATE & CALCULATED, args: DATA, next: NextFunction<ACTIONS>, props: PROPS) => void)
|
|
85
|
+
type EffectReducer<STATE, PROPS, ACTIONS, DATA, CALCULATED, CONTEXT = {}> =
|
|
86
|
+
| ((state: STATE & CALCULATED, args: DATA, next: NextFunction<ACTIONS>, props: ReducerExtras<PROPS, CONTEXT>) => void)
|
|
85
87
|
|
|
86
|
-
type DefaultSinks<STATE, PROPS, ACTIONS, DATA, CALCULATED, SINK_RETURNS extends NonStateSinkReturns = {}> = {
|
|
87
|
-
STATE?: SinkValue<STATE, PROPS, ACTIONS, DATA, STATE, CALCULATED>;
|
|
88
|
-
EVENTS?: SinkValue<STATE, PROPS, ACTIONS, DATA, ResolvedNonStateSinkReturns<SINK_RETURNS>['EVENTS'], CALCULATED>;
|
|
89
|
-
LOG?: SinkValue<STATE, PROPS, ACTIONS, DATA, ResolvedNonStateSinkReturns<SINK_RETURNS>['LOG'], CALCULATED>;
|
|
90
|
-
PARENT?: SinkValue<STATE, PROPS, ACTIONS, DATA, ResolvedNonStateSinkReturns<SINK_RETURNS>['PARENT'], CALCULATED>;
|
|
91
|
-
EFFECT?: EffectReducer<STATE, PROPS, ACTIONS, DATA, CALCULATED>;
|
|
88
|
+
type DefaultSinks<STATE, PROPS, ACTIONS, DATA, CALCULATED, SINK_RETURNS extends NonStateSinkReturns = {}, CONTEXT = {}> = {
|
|
89
|
+
STATE?: SinkValue<STATE, PROPS, ACTIONS, DATA, STATE, CALCULATED, CONTEXT>;
|
|
90
|
+
EVENTS?: SinkValue<STATE, PROPS, ACTIONS, DATA, ResolvedNonStateSinkReturns<SINK_RETURNS>['EVENTS'], CALCULATED, CONTEXT>;
|
|
91
|
+
LOG?: SinkValue<STATE, PROPS, ACTIONS, DATA, ResolvedNonStateSinkReturns<SINK_RETURNS>['LOG'], CALCULATED, CONTEXT>;
|
|
92
|
+
PARENT?: SinkValue<STATE, PROPS, ACTIONS, DATA, ResolvedNonStateSinkReturns<SINK_RETURNS>['PARENT'], CALCULATED, CONTEXT>;
|
|
93
|
+
EFFECT?: EffectReducer<STATE, PROPS, ACTIONS, DATA, CALCULATED, CONTEXT>;
|
|
92
94
|
}
|
|
93
95
|
|
|
94
|
-
type CustomDriverSinks<STATE, PROPS, DRIVERS, ACTIONS, ACTION_ENTRY, CALCULATED> = keyof DRIVERS extends never
|
|
96
|
+
type CustomDriverSinks<STATE, PROPS, DRIVERS, ACTIONS, ACTION_ENTRY, CALCULATED, CONTEXT = {}> = keyof DRIVERS extends never
|
|
95
97
|
? {
|
|
96
|
-
[driver: string]: SinkValue<STATE, PROPS, ACTIONS, any, any, CALCULATED>
|
|
98
|
+
[driver: string]: SinkValue<STATE, PROPS, ACTIONS, any, any, CALCULATED, CONTEXT>
|
|
97
99
|
}
|
|
98
100
|
: {
|
|
99
101
|
[DRIVER_KEY in keyof DRIVERS]: SinkValue<
|
|
@@ -102,15 +104,16 @@ type CustomDriverSinks<STATE, PROPS, DRIVERS, ACTIONS, ACTION_ENTRY, CALCULATED>
|
|
|
102
104
|
ACTIONS,
|
|
103
105
|
ACTION_ENTRY,
|
|
104
106
|
DRIVERS[DRIVER_KEY] extends { source: any; sink: any } ? DRIVERS[DRIVER_KEY]['sink'] : any,
|
|
105
|
-
CALCULATED
|
|
107
|
+
CALCULATED,
|
|
108
|
+
CONTEXT
|
|
106
109
|
>
|
|
107
110
|
}
|
|
108
111
|
|
|
109
|
-
type ModelEntry<STATE, PROPS, DRIVERS, ACTIONS, ACTION_ENTRY, CALCULATED, SINK_RETURNS extends NonStateSinkReturns = {}> =
|
|
110
|
-
| SinkValue<STATE, PROPS, ACTIONS, ACTION_ENTRY, STATE, CALCULATED>
|
|
112
|
+
type ModelEntry<STATE, PROPS, DRIVERS, ACTIONS, ACTION_ENTRY, CALCULATED, SINK_RETURNS extends NonStateSinkReturns = {}, CONTEXT = {}> =
|
|
113
|
+
| SinkValue<STATE, PROPS, ACTIONS, ACTION_ENTRY, STATE, CALCULATED, CONTEXT>
|
|
111
114
|
| Partial<
|
|
112
|
-
DefaultSinks<STATE, PROPS, ACTIONS, ACTION_ENTRY, CALCULATED, SINK_RETURNS> &
|
|
113
|
-
CustomDriverSinks<STATE, PROPS, DRIVERS, ACTIONS, ACTION_ENTRY, CALCULATED>
|
|
115
|
+
DefaultSinks<STATE, PROPS, ACTIONS, ACTION_ENTRY, CALCULATED, SINK_RETURNS, CONTEXT> &
|
|
116
|
+
CustomDriverSinks<STATE, PROPS, DRIVERS, ACTIONS, ACTION_ENTRY, CALCULATED, CONTEXT>
|
|
114
117
|
>
|
|
115
118
|
|
|
116
119
|
type WithDefaultActions<STATE, ACTIONS> = ACTIONS & {
|
|
@@ -120,7 +123,7 @@ type WithDefaultActions<STATE, ACTIONS> = ACTIONS & {
|
|
|
120
123
|
DISPOSE?: never;
|
|
121
124
|
}
|
|
122
125
|
|
|
123
|
-
type ComponentModel<STATE, PROPS, DRIVERS, ACTIONS, CALCULATED, SINK_RETURNS extends NonStateSinkReturns = {}> = keyof ACTIONS extends never
|
|
126
|
+
type ComponentModel<STATE, PROPS, DRIVERS, ACTIONS, CALCULATED, SINK_RETURNS extends NonStateSinkReturns = {}, CONTEXT = {}> = keyof ACTIONS extends never
|
|
124
127
|
? {
|
|
125
128
|
[action: string]: ModelEntry<
|
|
126
129
|
STATE,
|
|
@@ -129,7 +132,8 @@ type ComponentModel<STATE, PROPS, DRIVERS, ACTIONS, CALCULATED, SINK_RETURNS ext
|
|
|
129
132
|
WithDefaultActions<STATE, { [action: string]: any }>,
|
|
130
133
|
any,
|
|
131
134
|
CALCULATED,
|
|
132
|
-
SINK_RETURNS
|
|
135
|
+
SINK_RETURNS,
|
|
136
|
+
CONTEXT
|
|
133
137
|
>
|
|
134
138
|
}
|
|
135
139
|
: {
|
|
@@ -140,7 +144,8 @@ type ComponentModel<STATE, PROPS, DRIVERS, ACTIONS, CALCULATED, SINK_RETURNS ext
|
|
|
140
144
|
WithDefaultActions<STATE, ACTIONS>,
|
|
141
145
|
WithDefaultActions<STATE, ACTIONS>[ACTION_KEY],
|
|
142
146
|
CALCULATED,
|
|
143
|
-
SINK_RETURNS
|
|
147
|
+
SINK_RETURNS,
|
|
148
|
+
CONTEXT
|
|
144
149
|
>
|
|
145
150
|
}
|
|
146
151
|
|
|
@@ -259,7 +264,7 @@ export type Component<
|
|
|
259
264
|
DOMSourceName?: string;
|
|
260
265
|
stateSourceName?: string;
|
|
261
266
|
requestSourceName?: string;
|
|
262
|
-
model?: ComponentModel<STATE, PROPS, FixDrivers<DRIVERS>, ACTIONS, CALCULATED, SINK_RETURNS>;
|
|
267
|
+
model?: ComponentModel<STATE, PROPS, FixDrivers<DRIVERS>, ACTIONS, CALCULATED, SINK_RETURNS, CONTEXT>;
|
|
263
268
|
intent?: ComponentIntent<STATE & CALCULATED, FixDrivers<DRIVERS>, ACTIONS>;
|
|
264
269
|
initialState?: STATE;
|
|
265
270
|
calculated?: Calculated<STATE, CALCULATED>;
|
package/src/vike/onRenderHtml.ts
CHANGED
|
@@ -50,11 +50,30 @@ export function onRenderHtml(pageContext: PageContext) {
|
|
|
50
50
|
const { Page, config } = pageContext
|
|
51
51
|
const data = pageContext.data || {}
|
|
52
52
|
|
|
53
|
-
// SPA mode: return empty shell, let the client render everything
|
|
53
|
+
// SPA mode: return empty shell, let the client render everything.
|
|
54
|
+
// Head component and meta tags are still included — they're static
|
|
55
|
+
// metadata that should be present regardless of SSR being disabled.
|
|
54
56
|
if (config.ssr === false) {
|
|
55
57
|
const lang = config.lang || 'en'
|
|
56
58
|
const title = config.title || ''
|
|
59
|
+
const description = config.description || ''
|
|
60
|
+
const favicon = config.favicon || ''
|
|
57
61
|
const titleTag = title ? `<title>${esc(title)}</title>` : ''
|
|
62
|
+
const descTag = description
|
|
63
|
+
? `<meta name="description" content="${esc(description)}">`
|
|
64
|
+
: ''
|
|
65
|
+
const faviconTag = favicon
|
|
66
|
+
? `<link rel="icon" href="${esc(favicon)}">`
|
|
67
|
+
: ''
|
|
68
|
+
|
|
69
|
+
let headContent = ''
|
|
70
|
+
if (config.Head && typeof config.Head === 'function') {
|
|
71
|
+
try {
|
|
72
|
+
headContent = renderToString(config.Head, { state: {} })
|
|
73
|
+
} catch (_) {
|
|
74
|
+
// Head rendering failure is non-fatal
|
|
75
|
+
}
|
|
76
|
+
}
|
|
58
77
|
|
|
59
78
|
const spaHtml = `<!DOCTYPE html>
|
|
60
79
|
<html lang="${lang}">
|
|
@@ -62,6 +81,9 @@ export function onRenderHtml(pageContext: PageContext) {
|
|
|
62
81
|
<meta charset="UTF-8">
|
|
63
82
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
64
83
|
${titleTag}
|
|
84
|
+
${descTag}
|
|
85
|
+
${faviconTag}
|
|
86
|
+
${headContent}
|
|
65
87
|
</head>
|
|
66
88
|
<body>
|
|
67
89
|
<div id="page-view"></div>
|