diff --git a/.changeset/proud-cycles-hunt.md b/.changeset/proud-cycles-hunt.md deleted file mode 100644 index 5f0f88cb69..0000000000 --- a/.changeset/proud-cycles-hunt.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'svelte': patch ---- - -fix: align `disclose-version` exports specification diff --git a/.changeset/six-teachers-divide.md b/.changeset/six-teachers-divide.md deleted file mode 100644 index a11f257fef..0000000000 --- a/.changeset/six-teachers-divide.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'svelte': patch ---- - -fix: check srcset when hydrating to prevent needless requests diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c92e8a5355..b8e948b3a4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,7 +7,7 @@ permissions: contents: read # to fetch code (actions/checkout) env: - # We only install Chromium manually + # We only install Chromium manually PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: '1' jobs: diff --git a/documentation/blog/2020-07-17-svelte-and-typescript.md b/documentation/blog/2020-07-17-svelte-and-typescript.md index bcca836d4e..a6e07242ec 100644 --- a/documentation/blog/2020-07-17-svelte-and-typescript.md +++ b/documentation/blog/2020-07-17-svelte-and-typescript.md @@ -16,13 +16,9 @@ We think it'll give you a much nicer development experience — one that also sc ## Try it now -You can start a new Svelte TypeScript project using the [normal template](https://github.com/sveltejs/template) and by running `node scripts/setupTypeScript.js` before you do anything else: +You can start a new Svelte TypeScript project using Svelte's official scaffolding CLI by running `npm create svelte@latest` and following the prompts. This sets up a new SvelteKit project for you. -```bash -npx degit sveltejs/template svelte-typescript-app -cd svelte-typescript-app -node scripts/setupTypeScript.js -``` +Alternatively you can run `npm create vite@latest myapp -- --template svelte-ts` to scaffold a Vite project using Svelte and TypeScript. If you're a VS Code user, make sure you're using the (new) [official extension](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode), which replaces the popular extension by James Birtles. Later in this blog post, we'll detail the individual steps involved in using TypeScript in an existing Svelte project. diff --git a/documentation/docs/05-misc/04-v4-migration-guide.md b/documentation/docs/05-misc/04-v4-migration-guide.md index 0f660b68a1..4b634a978e 100644 --- a/documentation/docs/05-misc/04-v4-migration-guide.md +++ b/documentation/docs/05-misc/04-v4-migration-guide.md @@ -121,7 +121,18 @@ The migration script will do both automatically for you. ([#8512](https://github ## Transitions are local by default -Transitions are now local by default to prevent confusion around page navigations. To make them global, add the `|global` modifier. The migration script will do this automatically for you. ([#6686](https://github.com/sveltejs/svelte/issues/6686)) +Transitions are now local by default to prevent confusion around page navigations. "local" means that a transition will not play if it's within a nested control flow block (`each/if/await/key`) and not the direct parent block but a block above it is created/destroyed. In the following example, the `slide` intro animation will only play when `success` goes from `false` to `true`, but it will _not_ play when `show` goes from `false` to `true`: + +```svelte +{#if show} + ... + {#if success} +

Success

+ {/each} +{/if} +``` + +To make transitions global, add the `|global` modifier - then they will play when _any_ control flow block above is created/destroyed. The migration script will do this automatically for you. ([#6686](https://github.com/sveltejs/svelte/issues/6686)) ## Default slot bindings @@ -148,6 +159,10 @@ This makes slot bindings more consistent as the behavior is undefined when for e The order in which preprocessors are applied has changed. Now, preprocessors are executed in order, and within one group, the order is markup, script, style. Each preprocessor must also have a name. ([#8618](https://github.com/sveltejs/svelte/issues/8618)) +## New eslint package + +`eslint-plugin-svelte3` is deprecated. It may still work with Svelte 4 but we make no guarantees about that. We recommend switching to our new package [eslint-plugin-svelte](https://github.com/sveltejs/eslint-plugin-svelte). See [this Github post](https://github.com/sveltejs/kit/issues/10242#issuecomment-1610798405) for an instruction how to migrate. Alternatively, you can create a new project using `npm create svelte@latest`, select the eslint (and possibly TypeScript) option and then copy over the related files into your existing project. + ## Other breaking changes - the `inert` attribute is now applied to outroing elements to make them invisible to assistive technology and prevent interaction. ([#8628](https://github.com/sveltejs/svelte/pull/8628)) diff --git a/documentation/tutorial/02-reactivity/01-reactive-assignments/app-a/App.svelte b/documentation/tutorial/02-reactivity/01-reactive-assignments/app-a/App.svelte index 836e573dc6..8b1569bffb 100644 --- a/documentation/tutorial/02-reactivity/01-reactive-assignments/app-a/App.svelte +++ b/documentation/tutorial/02-reactivity/01-reactive-assignments/app-a/App.svelte @@ -10,3 +10,9 @@ Clicked {count} {count === 1 ? 'time' : 'times'} + + diff --git a/documentation/tutorial/02-reactivity/01-reactive-assignments/app-b/App.svelte b/documentation/tutorial/02-reactivity/01-reactive-assignments/app-b/App.svelte index 382b2ee9e0..d51ca2e068 100644 --- a/documentation/tutorial/02-reactivity/01-reactive-assignments/app-b/App.svelte +++ b/documentation/tutorial/02-reactivity/01-reactive-assignments/app-b/App.svelte @@ -10,3 +10,9 @@ Clicked {count} {count === 1 ? 'time' : 'times'} + + diff --git a/documentation/tutorial/05-events/02-inline-handlers/text.md b/documentation/tutorial/05-events/02-inline-handlers/text.md index 2fe1c48e2c..99ae43c429 100644 --- a/documentation/tutorial/05-events/02-inline-handlers/text.md +++ b/documentation/tutorial/05-events/02-inline-handlers/text.md @@ -10,6 +10,4 @@ You can also declare event handlers inline: ``` -The quote marks are optional, but they're helpful for syntax highlighting in some environments. - > In some frameworks you may see recommendations to avoid inline event handlers for performance reasons, particularly inside loops. That advice doesn't apply to Svelte — the compiler will always do the right thing, whichever form you choose. diff --git a/documentation/tutorial/10-transitions/09-key-blocks/text.md b/documentation/tutorial/10-transitions/09-key-blocks/text.md index 7a2e6eaca7..d0d9163d0d 100644 --- a/documentation/tutorial/10-transitions/09-key-blocks/text.md +++ b/documentation/tutorial/10-transitions/09-key-blocks/text.md @@ -5,8 +5,10 @@ title: Key blocks Key blocks destroy and recreate their contents when the value of an expression changes. ```svelte -{#key value} -
{value}
+{#key number} + + {number} + {/key} ``` diff --git a/package.json b/package.json index 47afc17e58..e0f1bdcfd9 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "build": "pnpm -r --filter=./packages/* build", "build:sites": "pnpm -r --filter=./sites/* build", "check": "cd packages/svelte && pnpm build && cd ../../ && pnpm -r check", - "lint": "pnpm -r lint", + "lint": "cd packages/svelte && pnpm build && cd ../../ && pnpm -r lint", "format": "pnpm -r format", "changeset:version": "changeset version && pnpm -r generate:version && git add --all", "changeset:publish": "changeset publish" diff --git a/packages/svelte/.prettierignore b/packages/svelte/.prettierignore index 3f6fbefc04..fef52b1e8f 100644 --- a/packages/svelte/.prettierignore +++ b/packages/svelte/.prettierignore @@ -16,6 +16,7 @@ sites/svelte.dev/.vercel /test/**/expected* /test/**/_output /test/**/shards/*.test.js +/test/hydration/samples/raw-repair/_after.html /types !rollup.config.js !vitest.config.js diff --git a/packages/svelte/CHANGELOG.md b/packages/svelte/CHANGELOG.md index ffa517208d..94dd154174 100644 --- a/packages/svelte/CHANGELOG.md +++ b/packages/svelte/CHANGELOG.md @@ -1,5 +1,33 @@ # svelte +## 4.0.4 + +### Patch Changes + +- fix: claim svg tags in raw mustache tags correctly ([#8910](https://github.com/sveltejs/svelte/pull/8910)) + +- fix: repair invalid raw html content during hydration ([#8912](https://github.com/sveltejs/svelte/pull/8912)) + +## 4.0.3 + +### Patch Changes + +- fix: handle falsy srcset values ([#8901](https://github.com/sveltejs/svelte/pull/8901)) + +## 4.0.2 + +### Patch Changes + +- fix: reflect all custom element prop updates back to attribute ([#8898](https://github.com/sveltejs/svelte/pull/8898)) + +- fix: shrink custom element baseline a bit ([#8858](https://github.com/sveltejs/svelte/pull/8858)) + +- fix: use non-destructive hydration for all `@html` tags ([#8880](https://github.com/sveltejs/svelte/pull/8880)) + +- fix: align `disclose-version` exports specification ([#8874](https://github.com/sveltejs/svelte/pull/8874)) + +- fix: check srcset when hydrating to prevent needless requests ([#8868](https://github.com/sveltejs/svelte/pull/8868)) + ## 4.0.1 ### Patch Changes diff --git a/packages/svelte/package.json b/packages/svelte/package.json index 0b554d0efa..d65541b130 100644 --- a/packages/svelte/package.json +++ b/packages/svelte/package.json @@ -1,6 +1,6 @@ { "name": "svelte", - "version": "4.0.1", + "version": "4.0.4", "description": "Cybernetically enhanced web apps", "type": "module", "module": "src/runtime/index.js", @@ -74,7 +74,7 @@ "types": "types/index.d.ts", "scripts": { "format": "prettier . --cache --plugin-search-dir=. --write", - "check": "prettier . --cache --plugin-search-dir=. --check", + "check": "tsc --noEmit", "test": "vitest run && echo \"manually check that there are no type errors in test/types by opening the files in there\"", "build": "rollup -c && pnpm types", "generate:version": "node ./scripts/generate-version.js", @@ -82,7 +82,7 @@ "posttest": "agadoo src/internal/index.js", "prepublishOnly": "pnpm build", "types": "node ./scripts/generate-dts.js", - "lint": "eslint \"{src,test}/**/*.{ts,js}\" --cache" + "lint": "prettier . --cache --plugin-search-dir=. --check && eslint \"{src,test}/**/*.{ts,js}\" --cache" }, "repository": { "type": "git", diff --git a/packages/svelte/src/compiler/compile/render_dom/wrappers/RawMustacheTag.js b/packages/svelte/src/compiler/compile/render_dom/wrappers/RawMustacheTag.js index 11a838ab8e..cc382a9b0b 100644 --- a/packages/svelte/src/compiler/compile/render_dom/wrappers/RawMustacheTag.js +++ b/packages/svelte/src/compiler/compile/render_dom/wrappers/RawMustacheTag.js @@ -26,7 +26,7 @@ export default class RawMustacheTagWrapper extends Tag { render(block, parent_node, _parent_nodes) { const in_head = is_head(parent_node); const can_use_innerhtml = !in_head && parent_node && !this.prev && !this.next; - if (can_use_innerhtml) { + if (can_use_innerhtml && !this.renderer.options.hydratable) { /** @param {import('estree').Node} content */ const insert = (content) => b`${parent_node}.innerHTML = ${content};`[0]; const { init } = this.rename_this_method(block, (content) => insert(content)); diff --git a/packages/svelte/src/runtime/internal/Component.js b/packages/svelte/src/runtime/internal/Component.js index a1da213da3..4733b1d745 100644 --- a/packages/svelte/src/runtime/internal/Component.js +++ b/packages/svelte/src/runtime/internal/Component.js @@ -13,7 +13,9 @@ import { start_hydrating, end_hydrating, get_custom_elements_slots, - insert + insert, + element, + attr } from './dom.js'; import { transition_in } from './transitions.js'; @@ -157,23 +159,29 @@ export let SvelteElement; if (typeof HTMLElement === 'function') { SvelteElement = class extends HTMLElement { - $$componentCtor; - $$slots; - $$component; - $$connected = false; - $$data = {}; - $$reflecting = false; - /** @type {Record} */ - $$props_definition = {}; - /** @type {Record} */ - $$listeners = {}; - /** @type {Map} */ - $$listener_unsubscribe_fns = new Map(); + /** The Svelte component constructor */ + $$ctor; + /** Slots */ + $$s; + /** The Svelte component instance */ + $$c; + /** Whether or not the custom element is connected */ + $$cn = false; + /** Component props data */ + $$d = {}; + /** `true` if currently in the process of reflecting component props back to attributes */ + $$r = false; + /** @type {Record} Props definition (name, reflected, type etc) */ + $$p_d = {}; + /** @type {Record} Event listeners */ + $$l = {}; + /** @type {Map} Event listener unsubscribe functions */ + $$l_u = new Map(); constructor($$componentCtor, $$slots, use_shadow_dom) { super(); - this.$$componentCtor = $$componentCtor; - this.$$slots = $$slots; + this.$$ctor = $$componentCtor; + this.$$s = $$slots; if (use_shadow_dom) { this.attachShadow({ mode: 'open' }); } @@ -183,32 +191,32 @@ if (typeof HTMLElement === 'function') { // We can't determine upfront if the event is a custom event or not, so we have to // listen to both. If someone uses a custom event with the same name as a regular // browser event, this fires twice - we can't avoid that. - this.$$listeners[type] = this.$$listeners[type] || []; - this.$$listeners[type].push(listener); - if (this.$$component) { - const unsub = this.$$component.$on(type, listener); - this.$$listener_unsubscribe_fns.set(listener, unsub); + this.$$l[type] = this.$$l[type] || []; + this.$$l[type].push(listener); + if (this.$$c) { + const unsub = this.$$c.$on(type, listener); + this.$$l_u.set(listener, unsub); } super.addEventListener(type, listener, options); } removeEventListener(type, listener, options) { super.removeEventListener(type, listener, options); - if (this.$$component) { - const unsub = this.$$listener_unsubscribe_fns.get(listener); + if (this.$$c) { + const unsub = this.$$l_u.get(listener); if (unsub) { unsub(); - this.$$listener_unsubscribe_fns.delete(listener); + this.$$l_u.delete(listener); } } } async connectedCallback() { - this.$$connected = true; - if (!this.$$component) { + this.$$cn = true; + if (!this.$$c) { // We wait one tick to let possible child slot elements be created/mounted await Promise.resolve(); - if (!this.$$connected) { + if (!this.$$cn) { return; } function create_slot(name) { @@ -216,9 +224,9 @@ if (typeof HTMLElement === 'function') { let node; const obj = { c: function create() { - node = document.createElement('slot'); + node = element('slot'); if (name !== 'default') { - node.setAttribute('name', name); + attr(node, 'name', name); } }, /** @@ -239,74 +247,89 @@ if (typeof HTMLElement === 'function') { } const $$slots = {}; const existing_slots = get_custom_elements_slots(this); - for (const name of this.$$slots) { + for (const name of this.$$s) { if (name in existing_slots) { $$slots[name] = [create_slot(name)]; } } for (const attribute of this.attributes) { // this.$$data takes precedence over this.attributes - const name = this.$$get_prop_name(attribute.name); - if (!(name in this.$$data)) { - this.$$data[name] = get_custom_element_value( - name, - attribute.value, - this.$$props_definition, - 'toProp' - ); + const name = this.$$g_p(attribute.name); + if (!(name in this.$$d)) { + this.$$d[name] = get_custom_element_value(name, attribute.value, this.$$p_d, 'toProp'); } } - this.$$component = new this.$$componentCtor({ + this.$$c = new this.$$ctor({ target: this.shadowRoot || this, props: { - ...this.$$data, + ...this.$$d, $$slots, $$scope: { ctx: [] } } }); - for (const type in this.$$listeners) { - for (const listener of this.$$listeners[type]) { - const unsub = this.$$component.$on(type, listener); - this.$$listener_unsubscribe_fns.set(listener, unsub); + + // Reflect component props as attributes + const reflect_attributes = () => { + this.$$r = true; + for (const key in this.$$p_d) { + this.$$d[key] = this.$$c.$$.ctx[this.$$c.$$.props[key]]; + if (this.$$p_d[key].reflect) { + const attribute_value = get_custom_element_value( + key, + this.$$d[key], + this.$$p_d, + 'toAttribute' + ); + if (attribute_value == null) { + this.removeAttribute(key); + } else { + this.setAttribute(this.$$p_d[key].attribute || key, attribute_value); + } + } + } + this.$$r = false; + }; + this.$$c.$$.after_update.push(reflect_attributes); + reflect_attributes(); // once initially because after_update is added too late for first render + + for (const type in this.$$l) { + for (const listener of this.$$l[type]) { + const unsub = this.$$c.$on(type, listener); + this.$$l_u.set(listener, unsub); } } - this.$$listeners = {}; + this.$$l = {}; } } // We don't need this when working within Svelte code, but for compatibility of people using this outside of Svelte // and setting attributes through setAttribute etc, this is helpful attributeChangedCallback(attr, _oldValue, newValue) { - if (this.$$reflecting) return; - attr = this.$$get_prop_name(attr); - this.$$data[attr] = get_custom_element_value( - attr, - newValue, - this.$$props_definition, - 'toProp' - ); - this.$$component?.$set({ [attr]: this.$$data[attr] }); + if (this.$$r) return; + attr = this.$$g_p(attr); + this.$$d[attr] = get_custom_element_value(attr, newValue, this.$$p_d, 'toProp'); + this.$$c?.$set({ [attr]: this.$$d[attr] }); } disconnectedCallback() { - this.$$connected = false; + this.$$cn = false; // In a microtask, because this could be a move within the DOM Promise.resolve().then(() => { - if (!this.$$connected) { - this.$$component.$destroy(); - this.$$component = undefined; + if (!this.$$cn) { + this.$$c.$destroy(); + this.$$c = undefined; } }); } - $$get_prop_name(attribute_name) { + $$g_p(attribute_name) { return ( - Object.keys(this.$$props_definition).find( + Object.keys(this.$$p_d).find( (key) => - this.$$props_definition[key].attribute === attribute_name || - (!this.$$props_definition[key].attribute && key.toLowerCase() === attribute_name) + this.$$p_d[key].attribute === attribute_name || + (!this.$$p_d[key].attribute && key.toLowerCase() === attribute_name) ) || attribute_name ); } @@ -371,7 +394,7 @@ export function create_custom_element( const Class = class extends SvelteElement { constructor() { super(Component, slots, use_shadow_dom); - this.$$props_definition = props_definition; + this.$$p_d = props_definition; } static get observedAttributes() { return Object.keys(props_definition).map((key) => @@ -382,36 +405,19 @@ export function create_custom_element( Object.keys(props_definition).forEach((prop) => { Object.defineProperty(Class.prototype, prop, { get() { - return this.$$component && prop in this.$$component - ? this.$$component[prop] - : this.$$data[prop]; + return this.$$c && prop in this.$$c ? this.$$c[prop] : this.$$d[prop]; }, set(value) { value = get_custom_element_value(prop, value, props_definition); - this.$$data[prop] = value; - this.$$component?.$set({ [prop]: value }); - if (props_definition[prop].reflect) { - this.$$reflecting = true; - const attribute_value = get_custom_element_value( - prop, - value, - props_definition, - 'toAttribute' - ); - if (attribute_value == null) { - this.removeAttribute(prop); - } else { - this.setAttribute(props_definition[prop].attribute || prop, attribute_value); - } - this.$$reflecting = false; - } + this.$$d[prop] = value; + this.$$c?.$set({ [prop]: value }); } }); }); accessors.forEach((accessor) => { Object.defineProperty(Class.prototype, accessor, { get() { - return this.$$component?.[accessor]; + return this.$$c?.[accessor]; } }); }); diff --git a/packages/svelte/src/runtime/internal/dom.js b/packages/svelte/src/runtime/internal/dom.js index e1969c5514..72cb8ab75b 100644 --- a/packages/svelte/src/runtime/internal/dom.js +++ b/packages/svelte/src/runtime/internal/dom.js @@ -777,14 +777,14 @@ export function claim_comment(nodes, data) { ); } -function find_comment(nodes, text, start) { +function get_comment_idx(nodes, text, start) { for (let i = start; i < nodes.length; i += 1) { const node = nodes[i]; if (node.nodeType === 8 /* comment node */ && node.textContent.trim() === text) { return i; } } - return nodes.length; + return -1; } /** @@ -793,11 +793,12 @@ function find_comment(nodes, text, start) { */ export function claim_html_tag(nodes, is_svg) { // find html opening tag - const start_index = find_comment(nodes, 'HTML_TAG_START', 0); - const end_index = find_comment(nodes, 'HTML_TAG_END', start_index); - if (start_index === end_index) { - return new HtmlTagHydration(undefined, is_svg); + const start_index = get_comment_idx(nodes, 'HTML_TAG_START', 0); + const end_index = get_comment_idx(nodes, 'HTML_TAG_END', start_index + 1); + if (start_index === -1 || end_index === -1) { + return new HtmlTagHydration(is_svg); } + init_claim_info(nodes); const html_tag_nodes = nodes.splice(start_index, end_index - start_index + 1); detach(html_tag_nodes[0]); @@ -807,7 +808,7 @@ export function claim_html_tag(nodes, is_svg) { n.claim_order = nodes.claim_info.total_claimed; nodes.claim_info.total_claimed += 1; } - return new HtmlTagHydration(claimed_nodes, is_svg); + return new HtmlTagHydration(is_svg, claimed_nodes); } /** @@ -1048,17 +1049,13 @@ export class HtmlTag { * @default false */ is_svg = false; - // parent for creating node - /** */ + /** parent for creating node */ e = undefined; - // html tag nodes - /** */ + /** html tag nodes */ n = undefined; - // target - /** */ + /** target */ t = undefined; - // anchor - /** */ + /** anchor */ a = undefined; constructor(is_svg = false) { this.is_svg = is_svg; @@ -1134,13 +1131,11 @@ export class HtmlTag { } } -/** - * @extends HtmlTag */ export class HtmlTagHydration extends HtmlTag { - // hydration claimed nodes - /** */ + /** @type {Element[]} hydration claimed nodes */ l = undefined; - constructor(claimed_nodes, is_svg = false) { + + constructor(is_svg = false, claimed_nodes) { super(is_svg); this.e = this.n = null; this.l = claimed_nodes; diff --git a/packages/svelte/src/runtime/internal/utils.js b/packages/svelte/src/runtime/internal/utils.js index 190c4534c6..ec39c0d9e4 100644 --- a/packages/svelte/src/runtime/internal/utils.js +++ b/packages/svelte/src/runtime/internal/utils.js @@ -90,12 +90,12 @@ function split_srcset(srcset) { /** * @param {HTMLSourceElement | HTMLImageElement} element_srcset - * @param {string} srcset + * @param {string | undefined | null} srcset * @returns {boolean} */ export function srcset_url_equal(element_srcset, srcset) { const element_urls = split_srcset(element_srcset.srcset); - const urls = split_srcset(srcset); + const urls = split_srcset(srcset || ''); return ( urls.length === element_urls.length && diff --git a/packages/svelte/src/shared/version.js b/packages/svelte/src/shared/version.js index 835c2fda5b..e286ec644f 100644 --- a/packages/svelte/src/shared/version.js +++ b/packages/svelte/src/shared/version.js @@ -6,5 +6,5 @@ * https://svelte.dev/docs/svelte-compiler#svelte-version * @type {string} */ -export const VERSION = '4.0.1'; +export const VERSION = '4.0.4'; export const PUBLIC_VERSION = '4'; diff --git a/packages/svelte/svelte-4.0.0.tgz b/packages/svelte/svelte-4.0.0.tgz deleted file mode 100644 index 8c527a3fd8..0000000000 Binary files a/packages/svelte/svelte-4.0.0.tgz and /dev/null differ diff --git a/packages/svelte/test/hydration/samples/raw-repair/_after.html b/packages/svelte/test/hydration/samples/raw-repair/_after.html new file mode 100644 index 0000000000..31cdc12015 --- /dev/null +++ b/packages/svelte/test/hydration/samples/raw-repair/_after.html @@ -0,0 +1,2 @@ +

invalid

+

invalid

\ No newline at end of file diff --git a/packages/svelte/test/hydration/samples/raw-repair/_before.html b/packages/svelte/test/hydration/samples/raw-repair/_before.html new file mode 100644 index 0000000000..fe958bece5 --- /dev/null +++ b/packages/svelte/test/hydration/samples/raw-repair/_before.html @@ -0,0 +1,8 @@ +

+

invalid

+ +

+

+

invalid

+ +

diff --git a/packages/svelte/test/hydration/samples/raw-repair/inner.svelte b/packages/svelte/test/hydration/samples/raw-repair/inner.svelte new file mode 100644 index 0000000000..a2df6c9ded --- /dev/null +++ b/packages/svelte/test/hydration/samples/raw-repair/inner.svelte @@ -0,0 +1,5 @@ + + +

{@html content}

diff --git a/packages/svelte/test/hydration/samples/raw-repair/main.svelte b/packages/svelte/test/hydration/samples/raw-repair/main.svelte new file mode 100644 index 0000000000..41deb9d3e6 --- /dev/null +++ b/packages/svelte/test/hydration/samples/raw-repair/main.svelte @@ -0,0 +1,7 @@ + + + + +

{@html '

invalid

'}

diff --git a/packages/svelte/test/hydration/samples/raw-svg/_after.html b/packages/svelte/test/hydration/samples/raw-svg/_after.html new file mode 100644 index 0000000000..801d9627cd --- /dev/null +++ b/packages/svelte/test/hydration/samples/raw-svg/_after.html @@ -0,0 +1,3 @@ + + + diff --git a/packages/svelte/test/hydration/samples/raw-svg/_before.html b/packages/svelte/test/hydration/samples/raw-svg/_before.html new file mode 100644 index 0000000000..2a1285938d --- /dev/null +++ b/packages/svelte/test/hydration/samples/raw-svg/_before.html @@ -0,0 +1,5 @@ + + + + + diff --git a/packages/svelte/test/hydration/samples/raw-svg/_config.js b/packages/svelte/test/hydration/samples/raw-svg/_config.js new file mode 100644 index 0000000000..ffcc89e7ff --- /dev/null +++ b/packages/svelte/test/hydration/samples/raw-svg/_config.js @@ -0,0 +1,14 @@ +export default { + snapshot(target) { + const svg = target.querySelector('svg'); + + return { + svg, + circle: svg.querySelector('circle') + }; + }, + test(assert, _, snapshot) { + assert.instanceOf(snapshot.svg, SVGElement); + assert.instanceOf(snapshot.circle, SVGElement); + } +}; diff --git a/packages/svelte/test/hydration/samples/raw-svg/main.svelte b/packages/svelte/test/hydration/samples/raw-svg/main.svelte new file mode 100644 index 0000000000..1b9310e09b --- /dev/null +++ b/packages/svelte/test/hydration/samples/raw-svg/main.svelte @@ -0,0 +1 @@ +{@html ''} \ No newline at end of file diff --git a/packages/svelte/test/hydration/samples/raw/_after.html b/packages/svelte/test/hydration/samples/raw/_after.html index d58c6f9d4d..f465f3094f 100644 --- a/packages/svelte/test/hydration/samples/raw/_after.html +++ b/packages/svelte/test/hydration/samples/raw/_after.html @@ -1,4 +1,2 @@ -

this is some html

and so is this

- diff --git a/packages/svelte/test/hydration/samples/raw/_before.html b/packages/svelte/test/hydration/samples/raw/_before.html index f465f3094f..de20b90f6c 100644 --- a/packages/svelte/test/hydration/samples/raw/_before.html +++ b/packages/svelte/test/hydration/samples/raw/_before.html @@ -1,2 +1,4 @@ +

this is some html

and so is this

+ diff --git a/packages/svelte/test/hydration/samples/raw/_config.js b/packages/svelte/test/hydration/samples/raw/_config.js index 14ba7b12c1..829079d4f0 100644 --- a/packages/svelte/test/hydration/samples/raw/_config.js +++ b/packages/svelte/test/hydration/samples/raw/_config.js @@ -1,6 +1,4 @@ export default { - skip: true, // existing nodes are blown away - props: { raw: '

this is some html

and so is this

' }, diff --git a/packages/svelte/test/hydration/samples/raw/main.svelte b/packages/svelte/test/hydration/samples/raw/main.svelte index 105e9e0581..94278521dd 100644 --- a/packages/svelte/test/hydration/samples/raw/main.svelte +++ b/packages/svelte/test/hydration/samples/raw/main.svelte @@ -1 +1,5 @@ -{@html raw} \ No newline at end of file + + +{@html raw} diff --git a/packages/svelte/test/runtime-browser/custom-elements-samples/reflect-attributes/main.svelte b/packages/svelte/test/runtime-browser/custom-elements-samples/reflect-attributes/main.svelte index 0e36f0143c..a662227a13 100644 --- a/packages/svelte/test/runtime-browser/custom-elements-samples/reflect-attributes/main.svelte +++ b/packages/svelte/test/runtime-browser/custom-elements-samples/reflect-attributes/main.svelte @@ -1,19 +1,20 @@
hi

hi

- + +