diff --git a/src/compiler/compile/render_dom/wrappers/Head.ts b/src/compiler/compile/render_dom/wrappers/Head.ts index e0b723d6dd..3869994ae4 100644 --- a/src/compiler/compile/render_dom/wrappers/Head.ts +++ b/src/compiler/compile/render_dom/wrappers/Head.ts @@ -36,7 +36,7 @@ export default class HeadWrapper extends Wrapper { let nodes; if (this.renderer.options.hydratable && this.fragment.nodes.length) { nodes = block.get_unique_name('head_nodes'); - block.chunks.claim.push(b`const ${nodes} = @query_selector_all('[data-svelte="${this.node.id}"]', @_document.head);`); + block.chunks.claim.push(b`const ${nodes} = @head_selector('${this.node.id}', @_document.head);`); } this.fragment.render(block, x`@_document.head` as unknown as Identifier, nodes); diff --git a/src/compiler/compile/render_ssr/handlers/HtmlTag.ts b/src/compiler/compile/render_ssr/handlers/HtmlTag.ts index cd62b95981..33b2f0ca38 100644 --- a/src/compiler/compile/render_ssr/handlers/HtmlTag.ts +++ b/src/compiler/compile/render_ssr/handlers/HtmlTag.ts @@ -3,7 +3,13 @@ import RawMustacheTag from '../../nodes/RawMustacheTag'; import { Expression } from 'estree'; export default function(node: RawMustacheTag, renderer: Renderer, options: RenderOptions) { - if (options.hydratable) renderer.add_string(''); + if (options.hydratable) { + renderer.add_string(``); + } + renderer.add_expression(node.expression.node as Expression); - if (options.hydratable) renderer.add_string(''); + + if (options.hydratable) { + renderer.add_string(``); + } } diff --git a/src/runtime/internal/dom.ts b/src/runtime/internal/dom.ts index 072506629c..318a4b2cad 100644 --- a/src/runtime/internal/dom.ts +++ b/src/runtime/internal/dom.ts @@ -477,11 +477,14 @@ export function claim_space(nodes) { return claim_text(nodes, ' '); } -function find_comment(nodes, text, start) { +function find_html_tag_comment(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; + if (node.nodeType === 8 /* comment node */) { + const value = node.textContent.trim(); + if (value === text || value.startsWith(text + ' data-svelte="') === true) { + return i; + } } } return nodes.length; @@ -490,8 +493,8 @@ function find_comment(nodes, text, start) { export function claim_html_tag(nodes, is_svg: boolean) { // 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); + const start_index = find_html_tag_comment(nodes, 'HTML_TAG_START', 0); + const end_index = find_html_tag_comment(nodes, 'HTML_TAG_END', start_index); if (start_index === end_index) { return new HtmlTagHydration(undefined, is_svg); } @@ -640,6 +643,25 @@ export function query_selector_all(selector: string, parent: HTMLElement = docum return Array.from(parent.querySelectorAll(selector)) as ChildNodeArray; } +export function head_selector(nodeId: string, head: HTMLElement) { + const result = []; + let started = 0; + for (const node of head.childNodes) { + if (node.nodeType === 8 /* comment node */ && node.textContent.trim() === `HTML_TAG_END data-svelte="${nodeId}"`) { + started -= 1; + result.push(node); + } else if (node.nodeType === 8 /* comment node */ && node.textContent.trim() === `HTML_TAG_START data-svelte="${nodeId}"`) { + started += 1; + result.push(node); + } else if (started > 0) { + result.push(node); + } else if (node.nodeType === 1 /* element node */ && (node).getAttribute('data-svelte') === nodeId) { + result.push(node); + } + } + return result; +} + export class HtmlTag { private is_svg = false; // parent for creating node diff --git a/test/hydration/samples/head-html/Nested.svelte b/test/hydration/samples/head-html/Nested.svelte new file mode 100644 index 0000000000..bd79aa3f19 --- /dev/null +++ b/test/hydration/samples/head-html/Nested.svelte @@ -0,0 +1,4 @@ + + + {@html ''} + diff --git a/test/hydration/samples/head-html/_after.html b/test/hydration/samples/head-html/_after.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/hydration/samples/head-html/_after_head.html b/test/hydration/samples/head-html/_after_head.html new file mode 100644 index 0000000000..64de976385 --- /dev/null +++ b/test/hydration/samples/head-html/_after_head.html @@ -0,0 +1,7 @@ + + + + + + + diff --git a/test/hydration/samples/head-html/_before.html b/test/hydration/samples/head-html/_before.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/hydration/samples/head-html/_before_head.html b/test/hydration/samples/head-html/_before_head.html new file mode 100644 index 0000000000..64de976385 --- /dev/null +++ b/test/hydration/samples/head-html/_before_head.html @@ -0,0 +1,7 @@ + + + + + + + diff --git a/test/hydration/samples/head-html/main.svelte b/test/hydration/samples/head-html/main.svelte new file mode 100644 index 0000000000..69ed401172 --- /dev/null +++ b/test/hydration/samples/head-html/main.svelte @@ -0,0 +1,9 @@ + + + + {@html ''} + + +