mirror of https://github.com/sveltejs/svelte
parent
b145035a00
commit
81bd13173b
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'svelte': minor
|
||||||
|
---
|
||||||
|
|
||||||
|
feat: add `<svelte:html>` element
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
title: <svelte:html>
|
||||||
|
---
|
||||||
|
|
||||||
|
```svelte
|
||||||
|
<svelte:html attribute={value} onevent={handler} />
|
||||||
|
```
|
||||||
|
|
||||||
|
Similarly to `<svelte:body>`, this element allows you to add properties and listeners to events on `document.documentElement`. This is useful for attributes such as `lang` which influence how the browser interprets the content.
|
||||||
|
|
||||||
|
As with `<svelte:window>`, `<svelte:document>` and `<svelte:body>`, this element may only appear the top level of your component and must never be inside a block or element.
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
/** @import { AST } from '#compiler' */
|
||||||
|
/** @import { Context } from '../types' */
|
||||||
|
import * as e from '../../../errors.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {AST.SvelteHTML} node
|
||||||
|
* @param {Context} context
|
||||||
|
*/
|
||||||
|
export function SvelteHTML(node, context) {
|
||||||
|
for (const attribute of node.attributes) {
|
||||||
|
if (attribute.type !== 'Attribute') {
|
||||||
|
e.svelte_html_illegal_attribute(attribute);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.fragment.nodes.length > 0) {
|
||||||
|
e.svelte_meta_invalid_content(node, node.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
context.next();
|
||||||
|
}
|
||||||
@ -0,0 +1,53 @@
|
|||||||
|
/** @import { ExpressionStatement } from 'estree' */
|
||||||
|
/** @import { AST } from '#compiler' */
|
||||||
|
/** @import { ComponentContext } from '../types' */
|
||||||
|
import { is_dom_property, normalize_attribute } from '../../../../../utils.js';
|
||||||
|
import { is_ignored } from '../../../../state.js';
|
||||||
|
import { is_event_attribute } from '../../../../utils/ast.js';
|
||||||
|
import * as b from '../../../../utils/builders.js';
|
||||||
|
import { build_attribute_value } from './shared/element.js';
|
||||||
|
import { visit_event_attribute } from './shared/events.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {AST.SvelteHTML} element
|
||||||
|
* @param {ComponentContext} context
|
||||||
|
*/
|
||||||
|
export function SvelteHTML(element, context) {
|
||||||
|
const node_id = b.id('$.document.documentElement');
|
||||||
|
|
||||||
|
for (const attribute of element.attributes) {
|
||||||
|
if (attribute.type === 'Attribute') {
|
||||||
|
if (is_event_attribute(attribute)) {
|
||||||
|
visit_event_attribute(attribute, context);
|
||||||
|
} else {
|
||||||
|
const name = normalize_attribute(attribute.name);
|
||||||
|
const { value, has_state } = build_attribute_value(attribute.value, context);
|
||||||
|
|
||||||
|
/** @type {ExpressionStatement} */
|
||||||
|
let update;
|
||||||
|
|
||||||
|
if (name === 'class') {
|
||||||
|
update = b.stmt(b.call('$.set_class', node_id, value));
|
||||||
|
} else if (is_dom_property(name)) {
|
||||||
|
update = b.stmt(b.assignment('=', b.member(node_id, name), value));
|
||||||
|
} else {
|
||||||
|
update = b.stmt(
|
||||||
|
b.call(
|
||||||
|
'$.set_attribute',
|
||||||
|
node_id,
|
||||||
|
b.literal(name),
|
||||||
|
value,
|
||||||
|
is_ignored(element, 'hydration_attribute_changed') && b.true
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_state) {
|
||||||
|
context.state.update.push(update);
|
||||||
|
} else {
|
||||||
|
context.state.init.push(update);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
/** @import { Property } from 'estree' */
|
||||||
|
/** @import { AST } from '#compiler' */
|
||||||
|
/** @import { ComponentContext } from '../types.js' */
|
||||||
|
import { normalize_attribute } from '../../../../../utils.js';
|
||||||
|
import { is_event_attribute } from '../../../../utils/ast.js';
|
||||||
|
import * as b from '../../../../utils/builders.js';
|
||||||
|
import { build_attribute_value } from './shared/utils.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {AST.SvelteHTML} element
|
||||||
|
* @param {ComponentContext} context
|
||||||
|
*/
|
||||||
|
export function SvelteHTML(element, context) {
|
||||||
|
/** @type {Property[]} */
|
||||||
|
const attributes = [];
|
||||||
|
|
||||||
|
for (const attribute of element.attributes) {
|
||||||
|
if (attribute.type === 'Attribute' && !is_event_attribute(attribute)) {
|
||||||
|
const name = normalize_attribute(attribute.name);
|
||||||
|
const value = build_attribute_value(attribute.value, context);
|
||||||
|
attributes.push(b.init(name, value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
context.state.template.push(
|
||||||
|
b.stmt(b.call('$.svelte_html', b.id('$$payload'), b.object(attributes)))
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
/** @import { Payload } from '#server' */
|
||||||
|
|
||||||
|
import { escape } from '..';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Payload} payload
|
||||||
|
* @param {Record<string, string>} attributes
|
||||||
|
*/
|
||||||
|
export function svelte_html(payload, attributes) {
|
||||||
|
for (const name in attributes) {
|
||||||
|
payload.htmlAttributes.set(name, escape(attributes[name], true));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
import { test } from '../../test';
|
||||||
|
|
||||||
|
export default test({
|
||||||
|
async test({ assert }) {
|
||||||
|
assert.deepEqual(document.documentElement.lang, 'de');
|
||||||
|
}
|
||||||
|
});
|
||||||
@ -0,0 +1 @@
|
|||||||
|
<svelte:html lang="de"></svelte:html>
|
||||||
@ -0,0 +1 @@
|
|||||||
|
<svelte:html foo="bar"></svelte:html>
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
import { test } from '../../test';
|
||||||
|
|
||||||
|
export default test({
|
||||||
|
htmlAttributes: 'foo="bar"'
|
||||||
|
});
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
<script>
|
||||||
|
import Nested from './Nested.svelte';
|
||||||
|
let ignored;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svelte:html foo="foo" onevent={ignored}></svelte:html>
|
||||||
|
|
||||||
|
<Nested/>
|
||||||
Loading…
Reference in new issue