Skip to content

Commit e291893

Browse files
authored
Merge pull request #2880 from cudr/head_html_fix
repair dynamic {@html} in head
2 parents ed72aea + 7071ce8 commit e291893

File tree

14 files changed

+142
-17
lines changed

14 files changed

+142
-17
lines changed

src/compile/render-dom/Block.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ export default class Block {
164164

165165
if (parent_node) {
166166
this.builders.mount.add_line(`@append(${parent_node}, ${name});`);
167-
if (parent_node === 'document.head') this.builders.destroy.add_line(`@detach(${name});`);
167+
if (parent_node === 'document.head' && !no_detach) this.builders.destroy.add_line(`@detach(${name});`);
168168
} else {
169169
this.builders.mount.add_line(`@insert(#target, ${name}, anchor);`);
170170
if (!no_detach) this.builders.destroy.add_conditional('detaching', `@detach(${name});`);

src/compile/render-dom/wrappers/Head.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,6 @@ export default class HeadWrapper extends Wrapper {
3030
}
3131

3232
render(block: Block, parent_node: string, parent_nodes: string) {
33-
this.fragment.render(block, 'document.head', null);
33+
this.fragment.render(block, 'document.head', 'nodes');
3434
}
35-
}
35+
}

src/compile/render-dom/wrappers/IfBlock.ts

+14-9
Original file line numberDiff line numberDiff line change
@@ -154,16 +154,18 @@ export default class IfBlockWrapper extends Wrapper {
154154

155155
const vars = { name, anchor, if_name, has_else, has_transitions };
156156

157+
const detaching = (parent_node && parent_node !== 'document.head') ? '' : 'detaching';
158+
157159
if (this.node.else) {
158160
if (has_outros) {
159-
this.render_compound_with_outros(block, parent_node, parent_nodes, dynamic, vars);
161+
this.render_compound_with_outros(block, parent_node, parent_nodes, dynamic, vars, detaching);
160162

161163
block.builders.outro.add_line(`if (${name}) ${name}.o();`);
162164
} else {
163-
this.render_compound(block, parent_node, parent_nodes, dynamic, vars);
165+
this.render_compound(block, parent_node, parent_nodes, dynamic, vars, detaching);
164166
}
165167
} else {
166-
this.render_simple(block, parent_node, parent_nodes, dynamic, vars);
168+
this.render_simple(block, parent_node, parent_nodes, dynamic, vars, detaching);
167169

168170
if (has_outros) {
169171
block.builders.outro.add_line(`if (${name}) ${name}.o();`);
@@ -201,7 +203,8 @@ export default class IfBlockWrapper extends Wrapper {
201203
parent_node: string,
202204
parent_nodes: string,
203205
dynamic,
204-
{ name, anchor, has_else, if_name, has_transitions }
206+
{ name, anchor, has_else, if_name, has_transitions },
207+
detaching
205208
) {
206209
const select_block_type = this.renderer.component.get_unique_name(`select_block_type`);
207210
const current_block_type = block.get_unique_name(`current_block_type`);
@@ -254,7 +257,7 @@ export default class IfBlockWrapper extends Wrapper {
254257
`);
255258
}
256259

257-
block.builders.destroy.add_line(`${if_name}${name}.d(${parent_node ? '' : 'detaching'});`);
260+
block.builders.destroy.add_line(`${if_name}${name}.d(${detaching});`);
258261
}
259262

260263
// if any of the siblings have outros, we need to keep references to the blocks
@@ -264,7 +267,8 @@ export default class IfBlockWrapper extends Wrapper {
264267
parent_node: string,
265268
parent_nodes: string,
266269
dynamic,
267-
{ name, anchor, has_else, has_transitions }
270+
{ name, anchor, has_else, has_transitions },
271+
detaching
268272
) {
269273
const select_block_type = this.renderer.component.get_unique_name(`select_block_type`);
270274
const current_block_type_index = block.get_unique_name(`current_block_type_index`);
@@ -375,7 +379,7 @@ export default class IfBlockWrapper extends Wrapper {
375379
}
376380

377381
block.builders.destroy.add_line(deindent`
378-
${if_current_block_type_index}${if_blocks}[${current_block_type_index}].d(${parent_node ? '' : 'detaching'});
382+
${if_current_block_type_index}${if_blocks}[${current_block_type_index}].d(${detaching});
379383
`);
380384
}
381385

@@ -384,7 +388,8 @@ export default class IfBlockWrapper extends Wrapper {
384388
parent_node: string,
385389
parent_nodes: string,
386390
dynamic,
387-
{ name, anchor, if_name, has_transitions }
391+
{ name, anchor, if_name, has_transitions },
392+
detaching
388393
) {
389394
const branch = this.branches[0];
390395

@@ -450,6 +455,6 @@ export default class IfBlockWrapper extends Wrapper {
450455
}
451456
`);
452457

453-
block.builders.destroy.add_line(`${if_name}${name}.d(${parent_node ? '' : 'detaching'});`);
458+
block.builders.destroy.add_line(`${if_name}${name}.d(${detaching});`);
454459
}
455460
}

src/compile/render-dom/wrappers/RawMustacheTag.ts

+12-3
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,18 @@ export default class RawMustacheTagWrapper extends Tag {
2222
render(block: Block, parent_node: string, parent_nodes: string) {
2323
const name = this.var;
2424

25+
const in_head = parent_node === 'document.head';
26+
const needs_anchors = !parent_node || in_head;
27+
28+
// if in head always needs anchors
29+
if (in_head) {
30+
this.prev = null;
31+
this.next = null;
32+
}
33+
2534
// TODO use is_dom_node instead of type === 'Element'?
26-
const needs_anchor_before = this.prev ? this.prev.node.type !== 'Element' : !parent_node;
27-
const needs_anchor_after = this.next ? this.next.node.type !== 'Element' : !parent_node;
35+
const needs_anchor_before = this.prev ? this.prev.node.type !== 'Element' : needs_anchors;
36+
const needs_anchor_after = this.next ? this.next.node.type !== 'Element' : needs_anchors;
2837

2938
const anchor_before = needs_anchor_before
3039
? block.get_unique_name(`${name}_before`)
@@ -90,7 +99,7 @@ export default class RawMustacheTagWrapper extends Tag {
9099

91100
block.builders.mount.add_line(insert(init));
92101

93-
if (!parent_node) {
102+
if (needs_anchors) {
94103
block.builders.destroy.add_conditional('detaching', needs_anchor_before
95104
? `${detach}\n@detach(${anchor_before});`
96105
: detach);

test/runtime/samples/head-if-block/_config.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ export default {
99
component.condition = true;
1010
assert.equal(window.document.title, 'woo!!!');
1111
}
12-
};
12+
};

test/runtime/samples/head-if-block/main.svelte

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@
66
{#if condition}
77
<title>woo!!!</title>
88
{/if}
9-
</svelte:head>
9+
</svelte:head>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
export default {
2+
props: {
3+
condition: false
4+
},
5+
6+
test({ assert, component, target, window }) {
7+
assert.equal(window.document.title, '');
8+
assert.equal(Boolean(window.document.getElementById('meta')), true);
9+
10+
component.condition = true;
11+
assert.equal(window.document.title, 'woo!!!');
12+
assert.equal(window.document.getElementById('meta'), null);
13+
}
14+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<script>
2+
export let condition;
3+
</script>
4+
5+
<svelte:head>
6+
{#if condition}
7+
<title>woo!!!</title>
8+
{:else}
9+
<meta id="meta" name="title" content="woo!!!"/>
10+
{/if}
11+
</svelte:head>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
const foo = '<script type="application/json">{ "foo": "true" }</script>';
2+
const bar = '<script type="application/json">{ "bar": "true" }</script>';
3+
4+
export default {
5+
props: {
6+
condition: false,
7+
foo,
8+
bar
9+
},
10+
11+
test({ assert, component, window }) {
12+
assert.equal(window.document.head.innerHTML.includes(foo), false);
13+
assert.equal(window.document.head.innerHTML.includes(bar), true);
14+
15+
component.condition = true;
16+
assert.equal(window.document.head.innerHTML.includes(foo), true);
17+
assert.equal(window.document.head.innerHTML.includes(bar), false);
18+
}
19+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<script>
2+
export let condition, foo, bar;
3+
</script>
4+
5+
<svelte:head>
6+
{#if condition}
7+
{@html foo}
8+
{:else}
9+
{@html bar}
10+
{/if}
11+
</svelte:head>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<script>
2+
export let bar;
3+
</script>
4+
5+
<svelte:head>
6+
<meta id="meta" name="title" content="bar!!!"/>
7+
{#if true}
8+
{@html bar}
9+
{/if}
10+
<title>bar!!!</title>
11+
</svelte:head>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<script>
2+
export let foo;
3+
</script>
4+
5+
<svelte:head>
6+
{@html foo}
7+
</svelte:head>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
const foo = '<script type="application/json">{ "foo": "true" }</script>';
2+
const bar = '<script type="application/json">{ "bar": "true" }</script>';
3+
4+
export default {
5+
props: {
6+
condition: 1,
7+
foo,
8+
bar
9+
},
10+
11+
test({ assert, component, window }) {
12+
assert.equal(window.document.head.innerHTML.includes(foo), true);
13+
14+
component.condition = false;
15+
assert.equal(window.document.head.innerHTML.includes(foo), false);
16+
17+
component.condition = 2;
18+
assert.equal(window.document.title, 'bar!!!');
19+
assert.equal(window.document.head.innerHTML.includes(bar), true);
20+
assert.equal(Boolean(window.document.getElementById('meta')), true);
21+
22+
component.condition = false;
23+
assert.equal(window.document.head.innerHTML.includes(bar), false);
24+
assert.equal(window.document.getElementById('meta'), null);
25+
}
26+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<script>
2+
import Foo from './Foo.svelte';
3+
import Bar from './Bar.svelte';
4+
5+
export let condition, foo, bar;
6+
</script>
7+
8+
{#if condition === 1}
9+
<Foo {foo} />
10+
{:else if condition === 2}
11+
<Bar {bar} />
12+
{/if}

0 commit comments

Comments
 (0)