From 975a9745785f30816d9eda19fc59711dcee3920c Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Sun, 10 Sep 2017 13:10:03 -0400 Subject: [PATCH] use anchors for slotted content - fixes #822 --- src/generators/dom/preprocess.ts | 2 ++ src/generators/dom/visitors/EachBlock.ts | 2 +- src/generators/dom/visitors/IfBlock.ts | 16 ++++++++-------- src/generators/dom/visitors/shared/isDomNode.ts | 6 ++++-- .../samples/component-slot-if-block/Nested.html | 3 +++ .../samples/component-slot-if-block/_config.js | 16 ++++++++++++++++ .../samples/component-slot-if-block/main.html | 17 +++++++++++++++++ 7 files changed, 51 insertions(+), 11 deletions(-) create mode 100644 test/runtime/samples/component-slot-if-block/Nested.html create mode 100644 test/runtime/samples/component-slot-if-block/_config.js create mode 100644 test/runtime/samples/component-slot-if-block/main.html diff --git a/src/generators/dom/preprocess.ts b/src/generators/dom/preprocess.ts index b945c902b9..e9aff13652 100644 --- a/src/generators/dom/preprocess.ts +++ b/src/generators/dom/preprocess.ts @@ -412,6 +412,8 @@ function preprocessChildren( lastChild = null; cleaned.forEach((child: Node, i: number) => { + child.parent = node; + const preprocessor = preprocessors[child.type]; if (preprocessor) preprocessor(generator, block, state, child, inEachBlock, elementStack, componentStack, stripWhitespace, cleaned[i + 1] || nextSibling); diff --git a/src/generators/dom/visitors/EachBlock.ts b/src/generators/dom/visitors/EachBlock.ts index 333c29ce6b..e0d941511e 100644 --- a/src/generators/dom/visitors/EachBlock.ts +++ b/src/generators/dom/visitors/EachBlock.ts @@ -21,7 +21,7 @@ export default function visitEachBlock( const iterations = block.getUniqueName(`${each_block}_iterations`); const params = block.params.join(', '); - const needsAnchor = node.next ? !isDomNode(node.next) : !state.parentNode; + const needsAnchor = node.next ? !isDomNode(node.next, generator) : !state.parentNode; const anchor = needsAnchor ? block.getUniqueName(`${each_block}_anchor`) : (node.next && node.next.var) || 'null'; diff --git a/src/generators/dom/visitors/IfBlock.ts b/src/generators/dom/visitors/IfBlock.ts index 7f4f80fc18..0deaf6b395 100644 --- a/src/generators/dom/visitors/IfBlock.ts +++ b/src/generators/dom/visitors/IfBlock.ts @@ -80,7 +80,7 @@ export default function visitIfBlock( ) { const name = node.var; - const needsAnchor = node.next ? !isDomNode(node.next) : !state.parentNode; + const needsAnchor = node.next ? !isDomNode(node.next, generator) : !state.parentNode || !isDomNode(node.parent, generator); const anchor = needsAnchor ? block.getUniqueName(`${name}_anchor`) : (node.next && node.next.var) || 'null'; @@ -94,7 +94,7 @@ export default function visitIfBlock( const dynamic = branches[0].hasUpdateMethod; // can use [0] as proxy for all, since they necessarily have the same value const hasOutros = branches[0].hasOutroMethod; - const vars = { name, anchor, params, if_name, hasElse }; + const vars = { name, needsAnchor, anchor, params, if_name, hasElse }; if (node.else) { if (hasOutros) { @@ -137,7 +137,7 @@ function simple( node: Node, branch, dynamic, - { name, anchor, params, if_name } + { name, needsAnchor, anchor, params, if_name } ) { block.builders.init.addBlock(deindent` var ${name} = (${branch.condition}) && ${branch.block}(${params}, #component); @@ -152,7 +152,7 @@ function simple( `if (${name}) ${name}.${mountOrIntro}(${targetNode}, ${anchorNode});` ); - const parentNode = state.parentNode || `${anchor}.parentNode`; + const parentNode = (state.parentNode && !needsAnchor) ? state.parentNode : `${anchor}.parentNode`; const enter = dynamic ? branch.hasIntroMethod @@ -227,7 +227,7 @@ function compound( node: Node, branches, dynamic, - { name, anchor, params, hasElse, if_name } + { name, needsAnchor, anchor, params, hasElse, if_name } ) { const select_block_type = generator.getUniqueName(`select_block_type`); const current_block_type = block.getUniqueName(`current_block_type`); @@ -255,7 +255,7 @@ function compound( `${if_name}${name}.${mountOrIntro}(${targetNode}, ${anchorNode});` ); - const parentNode = state.parentNode || `${anchor}.parentNode`; + const parentNode = (state.parentNode && !needsAnchor) ? state.parentNode : `${anchor}.parentNode`; const changeBlock = deindent` ${hasElse @@ -303,7 +303,7 @@ function compoundWithOutros( node: Node, branches, dynamic, - { name, anchor, params, hasElse } + { name, needsAnchor, anchor, params, hasElse } ) { const select_block_type = block.getUniqueName(`select_block_type`); const current_block_type_index = block.getUniqueName(`current_block_type_index`); @@ -354,7 +354,7 @@ function compoundWithOutros( `${if_current_block_type_index}${if_blocks}[${current_block_type_index}].${mountOrIntro}(${targetNode}, ${anchorNode});` ); - const parentNode = state.parentNode || `${anchor}.parentNode`; + const parentNode = (state.parentNode && !needsAnchor) ? state.parentNode : `${anchor}.parentNode`; const destroyOldBlock = deindent` ${name}.outro(function() { diff --git a/src/generators/dom/visitors/shared/isDomNode.ts b/src/generators/dom/visitors/shared/isDomNode.ts index 256aa65f4e..18304e3ff1 100644 --- a/src/generators/dom/visitors/shared/isDomNode.ts +++ b/src/generators/dom/visitors/shared/isDomNode.ts @@ -1,5 +1,7 @@ +import { DomGenerator } from '../../index'; import { Node } from '../../../../interfaces'; -export default function isDomNode(node: Node) { - return node.type === 'Element' || node.type === 'Text' || node.type === 'MustacheTag'; +export default function isDomNode(node: Node, generator: DomGenerator) { + if (node.type === 'Element') return !generator.components.has(node.name); + return node.type === 'Text' || node.type === 'MustacheTag'; } \ No newline at end of file diff --git a/test/runtime/samples/component-slot-if-block/Nested.html b/test/runtime/samples/component-slot-if-block/Nested.html new file mode 100644 index 0000000000..8213363fa0 --- /dev/null +++ b/test/runtime/samples/component-slot-if-block/Nested.html @@ -0,0 +1,3 @@ +
+ +
\ No newline at end of file diff --git a/test/runtime/samples/component-slot-if-block/_config.js b/test/runtime/samples/component-slot-if-block/_config.js new file mode 100644 index 0000000000..126ca78b2e --- /dev/null +++ b/test/runtime/samples/component-slot-if-block/_config.js @@ -0,0 +1,16 @@ +export default { + html: ` +
+

unconditional

+
`, + + test(assert, component, target) { + component.set({ foo: true }); + assert.htmlEqual(target.innerHTML, ` +
+

unconditional

+

conditional

+
+ `); + } +}; diff --git a/test/runtime/samples/component-slot-if-block/main.html b/test/runtime/samples/component-slot-if-block/main.html new file mode 100644 index 0000000000..95f975000a --- /dev/null +++ b/test/runtime/samples/component-slot-if-block/main.html @@ -0,0 +1,17 @@ + +

unconditional

+ + {{#if foo}} +

conditional

+ {{/if}} +
+ + \ No newline at end of file