0
0
mirror of https://github.com/sveltejs/svelte.git synced 2024-12-01 17:30:59 +01:00

support $$props and $$restProps for custom elements (#5608)

This commit is contained in:
Tan Li Hau 2020-10-29 03:33:03 +08:00 committed by GitHub
parent 0ca36a16b5
commit 6fa3e91b5d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 67 additions and 2 deletions

View File

@ -2,6 +2,7 @@
## Unreleased
* Fix `$$props` and `$$restProps` when compiling to a custom element ([#5482](https://github.com/sveltejs/svelte/issues/5482))
* Add `Element` and `Node` to known globals ([#5586](https://github.com/sveltejs/svelte/issues/5586))
## 3.29.4

View File

@ -474,7 +474,7 @@ export default function dom(
${css.code && b`this.shadowRoot.innerHTML = \`<style>${css.code.replace(/\\/g, '\\\\')}${options.dev ? `\n/*# sourceMappingURL=${css.map.toUrl()} */` : ''}</style>\`;`}
@init(this, { target: this.shadowRoot }, ${definition}, ${has_create_fragment ? 'create_fragment': 'null'}, ${not_equal}, ${prop_indexes}, ${dirty});
@init(this, { target: this.shadowRoot, props: @attribute_to_object(this.attributes) }, ${definition}, ${has_create_fragment ? 'create_fragment': 'null'}, ${not_equal}, ${prop_indexes}, ${dirty});
${dev_props_check}

View File

@ -360,3 +360,11 @@ export class HtmlTag {
this.n.forEach(detach);
}
}
export function attribute_to_object(attributes) {
const result = {};
for (const attribute of attributes) {
result[attribute.name] = attribute.value;
}
return result;
}

View File

@ -31,3 +31,24 @@ export function equal(a, b, message) {
export function ok(condition, message) {
if (!condition) throw new Error(message || `Expected ${condition} to be truthy`);
}
export function htmlEqual(actual, expected, message) {
return deepEqual(
normalizeHtml(window, actual),
normalizeHtml(window, expected),
message
);
}
function normalizeHtml(window, html) {
try {
const node = window.document.createElement('div');
node.innerHTML = html
.replace(/<!--.*?-->/g, '')
.replace(/>[\s\r\n]+</g, '><')
.trim();
return node.innerHTML.replace(/<\/?noscript\/?>/g, '');
} catch (err) {
throw new Error(`Failed to normalize HTML:\n${html}`);
}
}

View File

@ -0,0 +1,10 @@
<svelte:options tag="custom-element"/>
<script>
export let name;
</script>
<p>name: {name}</p>
<p>$$props: {JSON.stringify($$props)}</p>
<p>$$restProps: {JSON.stringify($$restProps)}</p>

View File

@ -0,0 +1,13 @@
import * as assert from 'assert';
import './main.svelte';
export default function (target) {
target.innerHTML = '<custom-element name="world" answer="42" test="svelte"></custom-element>';
const el = target.querySelector('custom-element');
assert.htmlEqual(el.shadowRoot.innerHTML, `
<p>name: world</p>
<p>$$props: {"name":"world","answer":"42","test":"svelte"}</p>
<p>$$restProps: {"answer":"42","test":"svelte"}</p>
`);
}

View File

@ -1,6 +1,7 @@
/* generated by Svelte vX.Y.Z */
import {
SvelteElement,
attribute_to_object,
detach,
element,
init,
@ -34,7 +35,18 @@ class Component extends SvelteElement {
constructor(options) {
super();
this.shadowRoot.innerHTML = `<style>div{animation:foo 1s}@keyframes foo{0%{opacity:0}100%{opacity:1}}</style>`;
init(this, { target: this.shadowRoot }, null, create_fragment, safe_not_equal, {});
init(
this,
{
target: this.shadowRoot,
props: attribute_to_object(this.attributes)
},
null,
create_fragment,
safe_not_equal,
{}
);
if (options) {
if (options.target) {