From b1b47696b17626f760d15d5e2b0644fcc9dc1cf6 Mon Sep 17 00:00:00 2001 From: Rich-Harris Date: Tue, 22 Nov 2016 13:58:37 -0500 Subject: [PATCH] implement elseif --- compiler/parse/state/mustache.js | 41 +++++++- test/compiler/if-block-elseif/_config.js | 23 +++++ test/compiler/if-block-elseif/main.html | 7 ++ test/parser/if-block-elseif/input.html | 5 + test/parser/if-block-elseif/output.json | 113 +++++++++++++++++++++++ 5 files changed, 186 insertions(+), 3 deletions(-) create mode 100644 test/compiler/if-block-elseif/_config.js create mode 100644 test/compiler/if-block-elseif/main.html create mode 100644 test/parser/if-block-elseif/input.html create mode 100644 test/parser/if-block-elseif/output.json diff --git a/compiler/parse/state/mustache.js b/compiler/parse/state/mustache.js index 818a597cd3..7827e7649d 100644 --- a/compiler/parse/state/mustache.js +++ b/compiler/parse/state/mustache.js @@ -16,8 +16,7 @@ export default function mustache ( parser ) { let expected; if ( block.type === 'ElseBlock' ) { - // TODO need to strip whitespace from else blocks - block.end = start; + // TODO need to strip whitespace from else and elseif blocks parser.stack.pop(); block = parser.current(); } @@ -34,6 +33,16 @@ export default function mustache ( parser ) { parser.allowWhitespace(); parser.eat( '}}', true ); + while ( block.elseif ) { + block.end = parser.index; + parser.stack.pop(); + block = parser.current(); + } + + if ( block.else ) { + block.else.end = start; + } + // strip leading/trailing whitespace as necessary if ( !block.children.length ) parser.error( `Empty block`, block.start ); const firstChild = block.children[0]; @@ -57,7 +66,33 @@ export default function mustache ( parser ) { } else if ( parser.eat( 'elseif' ) ) { - throw new Error( 'TODO elseif' ); + const block = parser.current(); + if ( block.type !== 'IfBlock' ) parser.error( 'Cannot have an {{elseif ...}} block outside an {{#if ...}} block' ); + + parser.requireWhitespace(); + + const expression = readExpression( parser ); + + parser.allowWhitespace(); + parser.eat( '}}', true ); + + block.else = { + start: parser.index, + end: null, + type: 'ElseBlock', + children: [ + { + start: parser.index, + end: null, + type: 'IfBlock', + elseif: true, + expression, + children: [] + } + ] + }; + + parser.stack.push( block.else.children[0] ); } else if ( parser.eat( 'else' ) ) { diff --git a/test/compiler/if-block-elseif/_config.js b/test/compiler/if-block-elseif/_config.js new file mode 100644 index 0000000000..50f6b7eac9 --- /dev/null +++ b/test/compiler/if-block-elseif/_config.js @@ -0,0 +1,23 @@ +export default { + data: { + x: 11 + }, + + html: ` +

x is greater than 10

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

x is less than 5

+ ` ); + + component.set({ x: 6 }); + assert.htmlEqual( target.innerHTML, ` +

x is between 5 and 10

+ ` ); + + component.teardown(); + } +}; diff --git a/test/compiler/if-block-elseif/main.html b/test/compiler/if-block-elseif/main.html new file mode 100644 index 0000000000..254d7a2202 --- /dev/null +++ b/test/compiler/if-block-elseif/main.html @@ -0,0 +1,7 @@ +{{#if x > 10}} +

x is greater than 10

+{{elseif x < 5}} +

x is less than 5

+{{else}} +

x is between 5 and 10

+{{/if}} diff --git a/test/parser/if-block-elseif/input.html b/test/parser/if-block-elseif/input.html new file mode 100644 index 0000000000..e6beff2348 --- /dev/null +++ b/test/parser/if-block-elseif/input.html @@ -0,0 +1,5 @@ +{{#if x > 10}} +

x is greater than 10

+{{elseif x < 5}} +

x is less than 5

+{{/if}} diff --git a/test/parser/if-block-elseif/output.json b/test/parser/if-block-elseif/output.json new file mode 100644 index 0000000000..7f30edb314 --- /dev/null +++ b/test/parser/if-block-elseif/output.json @@ -0,0 +1,113 @@ +{ + "html": { + "start": 0, + "end": 93, + "type": "Fragment", + "children": [ + { + "start": 0, + "end": 93, + "type": "IfBlock", + "expression": { + "start": 6, + "end": 12, + "type": "BinaryExpression", + "operator": ">", + "left": { + "start": 6, + "end": 7, + "type": "Identifier", + "name": "x" + }, + "right": { + "start": 10, + "end": 12, + "type": "Literal", + "value": 10, + "raw": "10" + } + }, + "children": [ + { + "start": 16, + "end": 43, + "type": "Element", + "name": "p", + "attributes": [], + "children": [ + { + "start": 19, + "end": 39, + "type": "Text", + "data": "x is greater than 10" + } + ] + } + ], + "else": { + "start": 60, + "end": 86, + "type": "ElseBlock", + "children": [ + { + "start": 60, + "end": 93, + "type": "IfBlock", + "elseif": true, + "expression": { + "start": 53, + "end": 58, + "type": "BinaryExpression", + "operator": "<", + "left": { + "start": 53, + "end": 54, + "type": "Identifier", + "name": "x" + }, + "right": { + "start": 57, + "end": 58, + "type": "Literal", + "value": 5, + "raw": "5" + } + }, + "children": [ + { + "start": 60, + "end": 62, + "type": "Text", + "data": "\n\t" + }, + { + "start": 62, + "end": 85, + "type": "Element", + "name": "p", + "attributes": [], + "children": [ + { + "start": 65, + "end": 81, + "type": "Text", + "data": "x is less than 5" + } + ] + }, + { + "start": 85, + "end": 86, + "type": "Text", + "data": "\n" + } + ] + } + ] + } + } + ] + }, + "css": null, + "js": null +}