diff --git a/compiler/generate/index.js b/compiler/generate/index.js index ead297fa2e..1c25c3e639 100644 --- a/compiler/generate/index.js +++ b/compiler/generate/index.js @@ -516,6 +516,7 @@ export default function generate ( parsed, source, options ) { }; this.root = options.root; + this.yield = options.yield; ${initStatements.join( '\n\n' )} } diff --git a/compiler/generate/visitors/Element.js b/compiler/generate/visitors/Element.js index 7b050cdb1a..6728f4cd42 100644 --- a/compiler/generate/visitors/Element.js +++ b/compiler/generate/visitors/Element.js @@ -1,9 +1,11 @@ import deindent from '../utils/deindent.js'; import addComponentAttributes from './attributes/addComponentAttributes.js'; import addElementAttributes from './attributes/addElementAttributes.js'; +import counter from '../utils/counter.js'; export default { enter ( generator, node ) { + const hasChildren = node.children.length > 0 const isComponent = node.name in generator.components; const name = generator.current.counter( isComponent ? `${node.name[0].toLowerCase()}${node.name.slice( 1 )}` : node.name ); @@ -27,13 +29,49 @@ export default { addComponentAttributes( generator, node, local ); + const componentInitProperties = [ + `target: ${!isToplevel ? generator.current.target: 'null'}`, + 'root: component.root || component' + ]; + // Component has children + if ( hasChildren ) { + const yieldName = `render${name}YieldFragment`; + + // {{YIELD STUFF}} + generator.push({ + useAnchor: true, + name: generator.current.counter(yieldName), + target: 'target', + localElementDepth: 0, + + initStatements: [], + mountStatements: [], + updateStatements: [], + teardownStatements: [], + + counter: counter() + }); + + node.children.forEach( generator.visit ); + generator.addRenderer( generator.current ); + generator.pop(); + + // Don't render children twice + node.children = []; + + generator.current.initStatements.push(`var ${name}_yieldFragment = ${yieldName}( root, component );`); + generator.current.updateStatements.push(`${name}_yieldFragment.update ( changed, root );`) + + componentInitProperties.push(`yield: ${name}_yieldFragment`); + } + + const statements = []; + if ( local.staticAttributes.length || local.dynamicAttributes.length || local.bindings.length ) { const initialProps = local.staticAttributes .concat( local.dynamicAttributes ) .map( attribute => `${attribute.name}: ${attribute.value}` ); - const statements = []; - if ( initialProps.length ) { statements.push( deindent` var ${name}_initialData = { @@ -53,24 +91,17 @@ export default { statements.push( bindings.join( '\n' ) ); } + componentInitProperties.push(`data: ${name}_initialData`); + } - local.init.unshift( deindent` - ${statements.join( '\n\n' )} + local.init.unshift( deindent` + ${statements.join( '\n\n' )} + + var ${name} = new template.components.${node.name}({ + ${componentInitProperties.join(',\n')} + }); + ` ); - var ${name} = new template.components.${node.name}({ - target: ${!isToplevel ? generator.current.target: 'null'}, - root: component.root || component, - data: ${name}_initialData - }); - ` ); - } else { - local.init.unshift( deindent` - var ${name} = new template.components.${node.name}({ - target: ${!isToplevel ? generator.current.target: 'null'}, - root: component.root || component - }); - ` ); - } if ( isToplevel ) { local.mount.unshift( `${name}.mount( target, anchor );` ); diff --git a/compiler/generate/visitors/YieldTag.js b/compiler/generate/visitors/YieldTag.js new file mode 100644 index 0000000000..a9fa5604cf --- /dev/null +++ b/compiler/generate/visitors/YieldTag.js @@ -0,0 +1,9 @@ +import deindent from '../utils/deindent.js'; + +export default { + enter ( generator, node ) { + const anchor = generator.createAnchor( 'yield', 'yield' ); + generator.current.mountStatements.push(`component.yield && component.yield.mount( ${generator.current.target}, ${anchor} );`); + generator.current.teardownStatements.push(`component.yield && component.yield.teardown( detach );`); + } +}; diff --git a/compiler/generate/visitors/index.js b/compiler/generate/visitors/index.js index 064669762f..70ba9e3298 100644 --- a/compiler/generate/visitors/index.js +++ b/compiler/generate/visitors/index.js @@ -4,6 +4,7 @@ import Element from './Element.js'; import IfBlock from './IfBlock.js'; import MustacheTag from './MustacheTag.js'; import Text from './Text.js'; +import YieldTag from './YieldTag.js'; export default { Comment, @@ -11,5 +12,6 @@ export default { Element, IfBlock, MustacheTag, - Text + Text, + YieldTag }; diff --git a/test/compiler/component-yield-if/Widget.html b/test/compiler/component-yield-if/Widget.html new file mode 100644 index 0000000000..7dbf91afb5 --- /dev/null +++ b/test/compiler/component-yield-if/Widget.html @@ -0,0 +1,15 @@ +
+ {{#if show}} + {{yield}} + {{/if}} +
+ diff --git a/test/compiler/component-yield-if/_config.js b/test/compiler/component-yield-if/_config.js new file mode 100644 index 0000000000..fad768230d --- /dev/null +++ b/test/compiler/component-yield-if/_config.js @@ -0,0 +1,13 @@ +export default { + html: 'Hello
World
{{yield}}
diff --git a/test/compiler/component-yield-parent/_config.js b/test/compiler/component-yield-parent/_config.js new file mode 100644 index 0000000000..28b8e175de --- /dev/null +++ b/test/compiler/component-yield-parent/_config.js @@ -0,0 +1,9 @@ +export default { + html: 'Hello
World
Hello
' +} diff --git a/test/compiler/component-yield/main.html b/test/compiler/component-yield/main.html new file mode 100644 index 0000000000..7d5cbf7180 --- /dev/null +++ b/test/compiler/component-yield/main.html @@ -0,0 +1,15 @@ ++ Hello + {{#if test}} + {{yield}} + {{/if}} +
+