diff --git a/modules/core/src/compiler/pipeline/text_interpolation_parser.js b/modules/core/src/compiler/pipeline/text_interpolation_parser.js index 4300201de1..cf1588ccdc 100644 --- a/modules/core/src/compiler/pipeline/text_interpolation_parser.js +++ b/modules/core/src/compiler/pipeline/text_interpolation_parser.js @@ -1,4 +1,4 @@ -import {RegExpWrapper, StringWrapper} from 'facade/lang'; +import {RegExpWrapper, StringWrapper, isPresent} from 'facade/lang'; import {Node, DOM} from 'facade/dom'; import {CompileStep} from './compile_step'; @@ -7,6 +7,7 @@ import {CompileControl} from './compile_control'; // TODO(tbosch): Cannot make this const/final right now because of the transpiler... var INTERPOLATION_REGEXP = RegExpWrapper.create('\\{\\{(.*?)\\}\\}'); +var QUOTE_REGEXP = RegExpWrapper.create("'"); /** * Parses interpolations in direct text child nodes of the current element. @@ -27,23 +28,30 @@ export class TextInterpolationParser extends CompileStep { } _parseTextNode(pipelineElement, node, nodeIndex) { - // TODO: escape fixed string quotes - // TODO: add braces around the expression - // TODO: suppress empty strings - // TODO: add stringify formatter + // TODO: add stringify formatter when we support formatters var parts = StringWrapper.split(node.nodeValue, INTERPOLATION_REGEXP); if (parts.length > 1) { + var expression = ''; for (var i=0; i 0) { + expressionPart = "'" + StringWrapper.replaceAll(parts[i], QUOTE_REGEXP, "\\'") + "'"; + } } else { // expression - parts[i] = "" + parts[i] + ""; + expressionPart = "(" + parts[i] + ")"; + } + if (isPresent(expressionPart)) { + if (expression.length > 0) { + expression += '+'; + } + expression += expressionPart; } } DOM.setText(node, ' '); - pipelineElement.addTextNodeBinding(nodeIndex, parts.join('+')); + pipelineElement.addTextNodeBinding(nodeIndex, expression); } } } diff --git a/modules/core/test/compiler/pipeline/text_interpolation_parser_spec.js b/modules/core/test/compiler/pipeline/text_interpolation_parser_spec.js index e73cc181f5..886b884164 100644 --- a/modules/core/test/compiler/pipeline/text_interpolation_parser_spec.js +++ b/modules/core/test/compiler/pipeline/text_interpolation_parser_spec.js @@ -13,15 +13,32 @@ export function main() { it('should find text interpolation in normal elements', () => { var results = createPipeline().process(createElement('
{{expr1}}{{expr2}}
')); var bindings = results[0].textNodeBindings; - expect(MapWrapper.get(bindings, 0)).toEqual("''+expr1+''"); - expect(MapWrapper.get(bindings, 2)).toEqual("''+expr2+''"); + expect(MapWrapper.get(bindings, 0)).toEqual("(expr1)"); + expect(MapWrapper.get(bindings, 2)).toEqual("(expr2)"); }); it('should find text interpolation in template elements', () => { var results = createPipeline().process(createElement('')); var bindings = results[0].textNodeBindings; - expect(MapWrapper.get(bindings, 0)).toEqual("''+expr1+''"); - expect(MapWrapper.get(bindings, 2)).toEqual("''+expr2+''"); + expect(MapWrapper.get(bindings, 0)).toEqual("(expr1)"); + expect(MapWrapper.get(bindings, 2)).toEqual("(expr2)"); + }); + + it('should allow multiple expressions', () => { + var results = createPipeline().process(createElement('
{{expr1}}{{expr2}}
')); + var bindings = results[0].textNodeBindings; + expect(MapWrapper.get(bindings, 0)).toEqual("(expr1)+(expr2)"); + }); + + it('should allow fixed text before, in between and after expressions', () => { + var results = createPipeline().process(createElement('
a{{expr1}}b{{expr2}}c
')); + var bindings = results[0].textNodeBindings; + expect(MapWrapper.get(bindings, 0)).toEqual("'a'+(expr1)+'b'+(expr2)+'c'"); + }); + + it('should escape quotes in fixed parts', () => { + var results = createPipeline().process(createElement("
'\"a{{expr1}}
")); + expect(MapWrapper.get(results[0].textNodeBindings, 0)).toEqual("'\\'\"a'+(expr1)"); }); }); } diff --git a/modules/facade/src/lang.dart b/modules/facade/src/lang.dart index aab695d4e6..989c7fd9e2 100644 --- a/modules/facade/src/lang.dart +++ b/modules/facade/src/lang.dart @@ -76,6 +76,10 @@ class StringWrapper { static equals(String s, String s2) { return s == s2; } + + static String replaceAll(String s, RegExp from, String replace) { + return s.replaceAll(from, replace); + } } class StringJoiner { diff --git a/modules/facade/src/lang.es6 b/modules/facade/src/lang.es6 index 62c66aef1b..552bffd571 100644 --- a/modules/facade/src/lang.es6 +++ b/modules/facade/src/lang.es6 @@ -66,6 +66,10 @@ export class StringWrapper { static equals(s:string, s2:string) { return s === s2; } + + static replaceAll(s:string, from:RegExp, replace:string) { + return s.replace(from.multiple, replace); + } } export class StringJoiner {