parse each blocks correctly

pull/31/head
Rich Harris 9 years ago
parent fe80374bd3
commit c4b1b548cc

@ -143,4 +143,54 @@ describe( 'parse', () => {
js: null
});
});
it( 'parses an {{#each}}...{{/each}} block', () => {
const template = `{{#each animals as animal}}<p>{{animal}}</p>{{/each}}`;
assert.deepEqual( parse( template ), {
html: {
start: 0,
end: 53,
type: 'Fragment',
children: [
{
start: 0,
end: 53,
type: 'EachBlock',
expression: {
start: 8,
end: 15,
type: 'Identifier',
name: 'animals'
},
context: 'animal',
children: [
{
start: 27,
end: 44,
type: 'Element',
name: 'p',
attributes: [],
children: [
{
start: 30,
end: 40,
type: 'MustacheTag',
expression: {
start: 32,
end: 38,
type: 'Identifier',
name: 'animal'
}
}
]
}
]
}
]
},
css: null,
js: null
});
});
});

@ -39,6 +39,15 @@ export default function parse ( template ) {
}
},
read ( pattern ) {
const match = pattern.exec( this.template.slice( this.index ) );
if ( !match || match.index !== 0 ) return null;
parser.index += match[0].length;
return match[0];
},
readUntil ( pattern ) {
const match = pattern.exec( this.template.slice( this.index ) );
return this.template.slice( this.index, match ? ( this.index += match.index ) : this.template.length );

@ -1,5 +1,7 @@
import readExpression from '../read/expression.js';
const validIdentifier = /[a-zA-Z_$][a-zA-Z0-9_$]*/;
export default function mustache ( parser ) {
const start = parser.index;
parser.index += 2;
@ -45,9 +47,6 @@ export default function mustache ( parser ) {
const expression = readExpression( parser );
parser.allowWhitespace();
parser.eat( '}}', true );
const block = {
start,
end: null,
@ -56,6 +55,20 @@ export default function mustache ( parser ) {
children: []
};
parser.allowWhitespace();
// {{#each}} blocks must declare a context {{#each list as item}}
if ( type === 'EachBlock' ) {
parser.eat( 'as', true );
parser.requireWhitespace();
block.context = parser.read( validIdentifier ); // TODO check it's not a keyword
parser.allowWhitespace();
}
parser.eat( '}}', true );
parser.current().children.push( block );
parser.stack.push( block );
}

@ -0,0 +1,15 @@
import * as assert from 'assert';
export default {
description: '{{#each}}...{{/each}} block',
data: {
animals: [ 'alpaca', 'baboon', 'capybara' ]
},
html: '<p>alpaca</p><p>baboon</p><p>capybara</p><!--#each animals-->',
test ( component, target ) {
component.set({ animals: [ 'alpaca', 'baboon', 'caribou', 'dogfish' ] });
assert.equal( target.innerHTML, '<p>alpaca</p><p>baboon</p><p>caribou</p><p>dogfish</p><!--#each animals-->' );
component.set({ animals: [] });
assert.equal( target.innerHTML, '<!--#each animals-->' );
}
};

@ -0,0 +1,3 @@
{{#each animals as animal}}
<p>{{animal}}</p>
{{/each}}
Loading…
Cancel
Save