Merge branch 'yield-next' of https://github.com/FWeinb/svelte into FWeinb-yield-next

pull/120/head
Rich-Harris 8 years ago
commit 172f0c9d6b

@ -521,6 +521,7 @@ export default function generate ( parsed, source, options ) {
};
this.root = options.root;
this.yield = options.yield;
${initStatements.join( '\n\n' )}
}

@ -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 );
@ -28,13 +30,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 = {
@ -54,24 +92,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 );` );

@ -0,0 +1,7 @@
export default {
enter ( generator ) {
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 );`);
}
};

@ -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
};

@ -177,6 +177,19 @@ export default function mustache ( parser ) {
parser.stack.push( block );
}
// {{yield}}
else if ( parser.eat( 'yield' ) ) {
parser.allowWhitespace();
parser.eat( '}}', true );
parser.current().children.push({
start,
end: parser.index,
type: 'YieldTag'
});
}
else {
const expression = readExpression( parser );

@ -0,0 +1,15 @@
<p>
{{#if show}}
{{yield}}
{{/if}}
</p>
<script>
export default {
data(){
return {
show: false
}
}
}
</script>

@ -0,0 +1,13 @@
export default {
html: '<div><p></p></div>',
test ( assert, component, target ) {
const widget = component.refs.widget;
assert.equal( widget.get( 'show' ), false );
widget.set({show: true});
assert.equal( target.innerHTML, '<div><p>Hello<!--yield--><!--#if show--></p></div>' );
component.set({data: 'World'});
assert.equal( target.innerHTML, '<div><p>World<!--yield--><!--#if show--></p></div>' );
widget.set({show: false});
assert.equal( target.innerHTML, '<div><p><!--#if show--></p></div>' );
}
}

@ -0,0 +1,14 @@
<div>
<Widget ref:widget>{{data}}</Widget>
</div>
<script>
import Widget from './Widget.html'
export default {
components: { Widget },
data(){
return {
data: "Hello"
}
}
}
</script>

@ -0,0 +1,9 @@
export default {
html: '<div><p>Hello</p></div>',
test ( assert, component, target ) {
assert.equal( component.get( 'data' ), 'Hello' );
component.set({data: 'World'})
assert.equal( component.get( 'data' ), 'World' );
assert.equal( target.innerHTML, '<div><p>World<!--yield--></p></div>' );
}
}

@ -0,0 +1,14 @@
<div>
<Widget>{{data}}</Widget>
</div>
<script>
import Widget from './Widget.html'
export default {
components: { Widget },
data(){
return {
data: "Hello"
}
}
}
</script>

@ -0,0 +1,3 @@
export default {
html: '<p>Hello</p>'
}

@ -0,0 +1,15 @@
<p>
Hello
{{#if test}}
{{yield}}
{{/if}}
</p>
<script>
export default {
data(){
return {
test: true
}
}
}
</script>

@ -0,0 +1,14 @@
{
"html": {
"start": 0,
"end": 9,
"type": "Fragment",
"children": [
{
"start": 0,
"end": 9,
"type": "YieldTag"
}
]
}
}
Loading…
Cancel
Save