From 6c473a3466d724bdd4d4a315b79bae52f72aa72b Mon Sep 17 00:00:00 2001 From: Fabrice Weinberg Date: Mon, 5 Dec 2016 00:56:45 +0100 Subject: [PATCH] Initial implementation of {{yield}}-generator --- compiler/generate/index.js | 1 + compiler/generate/visitors/Element.js | 67 ++++++++++++++----- compiler/generate/visitors/YieldTag.js | 9 +++ compiler/generate/visitors/index.js | 4 +- test/compiler/component-yield-if/Widget.html | 15 +++++ test/compiler/component-yield-if/_config.js | 13 ++++ test/compiler/component-yield-if/main.html | 14 ++++ .../component-yield-parent/Widget.html | 1 + .../component-yield-parent/_config.js | 9 +++ .../compiler/component-yield-parent/main.html | 14 ++++ test/compiler/component-yield/_config.js | 3 + test/compiler/component-yield/main.html | 15 +++++ 12 files changed, 146 insertions(+), 19 deletions(-) create mode 100644 compiler/generate/visitors/YieldTag.js create mode 100644 test/compiler/component-yield-if/Widget.html create mode 100644 test/compiler/component-yield-if/_config.js create mode 100644 test/compiler/component-yield-if/main.html create mode 100644 test/compiler/component-yield-parent/Widget.html create mode 100644 test/compiler/component-yield-parent/_config.js create mode 100644 test/compiler/component-yield-parent/main.html create mode 100644 test/compiler/component-yield/_config.js create mode 100644 test/compiler/component-yield/main.html 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: '

', + test ( assert, component, target ) { + const widget = component.refs.widget; + assert.equal( widget.get( 'show' ), false ); + widget.set({show: true}); + assert.equal( target.innerHTML, '

Hello

' ); + component.set({data: 'World'}); + assert.equal( target.innerHTML, '

World

' ); + widget.set({show: false}); + assert.equal( target.innerHTML, '

' ); + } +} diff --git a/test/compiler/component-yield-if/main.html b/test/compiler/component-yield-if/main.html new file mode 100644 index 0000000000..61f0909984 --- /dev/null +++ b/test/compiler/component-yield-if/main.html @@ -0,0 +1,14 @@ +
+ {{data}} +
+ diff --git a/test/compiler/component-yield-parent/Widget.html b/test/compiler/component-yield-parent/Widget.html new file mode 100644 index 0000000000..e147954fa0 --- /dev/null +++ b/test/compiler/component-yield-parent/Widget.html @@ -0,0 +1 @@ +

{{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

', + test ( assert, component, target ) { + assert.equal( component.get( 'data' ), 'Hello' ); + component.set({data: 'World'}) + assert.equal( component.get( 'data' ), 'World' ); + assert.equal( target.innerHTML, '

World

' ); + } +} diff --git a/test/compiler/component-yield-parent/main.html b/test/compiler/component-yield-parent/main.html new file mode 100644 index 0000000000..8a043a6ca7 --- /dev/null +++ b/test/compiler/component-yield-parent/main.html @@ -0,0 +1,14 @@ +
+ {{data}} +
+ diff --git a/test/compiler/component-yield/_config.js b/test/compiler/component-yield/_config.js new file mode 100644 index 0000000000..fcf00b5072 --- /dev/null +++ b/test/compiler/component-yield/_config.js @@ -0,0 +1,3 @@ +export default { + html: '

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}} +

+