Skip to content

Commit f16f4d1

Browse files
committed
feat: support server-rendering attributes of <svelte:html> blocks
Companion to sveltejs/svelte#14397
1 parent fb146e7 commit f16f4d1

File tree

6 files changed

+26
-3
lines changed

6 files changed

+26
-3
lines changed

Diff for: .changeset/tricky-garlics-mate.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@sveltejs/kit': minor
3+
---
4+
5+
feat: support server-rendering attributes of `<svelte:html>` blocks

Diff for: documentation/docs/10-getting-started/30-project-structure.md

+1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ The `src` directory contains the meat of your project. Everything except `src/ro
4848
- `%sveltekit.assets%` — either [`paths.assets`](configuration#paths), if specified, or a relative path to [`paths.base`](configuration#paths)
4949
- `%sveltekit.nonce%` — a [CSP](configuration#csp) nonce for manually included links and scripts, if used
5050
- `%sveltekit.env.[NAME]%` - this will be replaced at render time with the `[NAME]` environment variable, which must begin with the [`publicPrefix`](configuration#env) (usually `PUBLIC_`). It will fallback to `''` if not matched.
51+
- `%svelte.htmlAttributes%` — the attributes collected from `<svelte:html>` blocks
5152
- `error.html` is the page that is rendered when everything else fails. It can contain the following placeholders:
5253
- `%sveltekit.status%` — the HTTP status
5354
- `%sveltekit.error.message%` — the error message

Diff for: packages/kit/src/core/sync/write_server.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import { set_private_env, set_public_env, set_safe_public_env } from '${runtime_
3737
export const options = {
3838
app_dir: ${s(config.kit.appDir)},
3939
app_template_contains_nonce: ${template.includes('%sveltekit.nonce%')},
40+
app_template_contains_svelte_htmlAttributes: ${template.includes('%svelte.htmlAttributes%')},
4041
csp: ${s(config.kit.csp)},
4142
csrf_check_origin: ${s(config.kit.csrf.checkOrigin)},
4243
embedded: ${config.kit.embedded},
@@ -47,7 +48,8 @@ export const options = {
4748
root,
4849
service_worker: ${has_service_worker},
4950
templates: {
50-
app: ({ head, body, assets, nonce, env }) => ${s(template)
51+
app: ({ html_attributes, head, body, assets, nonce, env }) => ${s(template)
52+
.replace('%svelte.htmlAttributes%', '" + html_attributes + "')
5153
.replace('%sveltekit.head%', '" + head + "')
5254
.replace('%sveltekit.body%', '" + body + "')
5355
.replace(/%sveltekit\.assets%/g, '" + assets + "')

Diff for: packages/kit/src/runtime/server/page/render.js

+14-1
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,17 @@ export async function render_response({
191191
}
192192
}
193193
} else {
194-
rendered = { head: '', html: '', css: { code: '', map: null } };
194+
rendered = { head: '', html: '', css: { code: '', map: null }, htmlAttributes: '' };
195+
}
196+
197+
if (
198+
!options.app_template_contains_svelte_htmlAttributes &&
199+
// @ts-expect-error only exists in later versions of Svelte 5
200+
rendered.htmlAttributes
201+
) {
202+
console.warn(
203+
'One or more components used `<svelte:html>` to output attributes to the HTML tag but app.html does not contain %svelte.htmlAttributes% to render them. The attributes will be ignored.'
204+
);
195205
}
196206

197207
let head = '';
@@ -458,6 +468,9 @@ export async function render_response({
458468
head += rendered.head;
459469

460470
const html = options.templates.app({
471+
// @ts-expect-error only exists in later versions of Svelte 5
472+
html_attributes: rendered.htmlAttributes ?? '',
473+
461474
head,
462475
body,
463476
assets,

Diff for: packages/kit/src/types/internal.d.ts

+2
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,7 @@ export type SSRNodeLoader = () => Promise<SSRNode>;
355355
export interface SSROptions {
356356
app_dir: string;
357357
app_template_contains_nonce: boolean;
358+
app_template_contains_svelte_htmlAttributes: boolean;
358359
csp: ValidatedConfig['kit']['csp'];
359360
csrf_check_origin: boolean;
360361
embedded: boolean;
@@ -366,6 +367,7 @@ export interface SSROptions {
366367
service_worker: boolean;
367368
templates: {
368369
app(values: {
370+
htmlAttributes: string;
369371
head: string;
370372
body: string;
371373
assets: string;

Diff for: playgrounds/basic/src/app.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!doctype html>
2-
<html lang="en">
2+
<html %svelte.htmlAttributes% lang="en">
33
<head>
44
<meta charset="utf-8" />
55
<link rel="icon" href="%sveltekit.assets%/favicon.png" />

0 commit comments

Comments
 (0)