diff --git a/modules/@angular/compiler/src/compiler.ts b/modules/@angular/compiler/src/compiler.ts index 24580037ae..4d853ce9a2 100644 --- a/modules/@angular/compiler/src/compiler.ts +++ b/modules/@angular/compiler/src/compiler.ts @@ -41,6 +41,7 @@ function _createCompilerConfig() { */ export const COMPILER_PROVIDERS: Array = /*@ts2dart_const*/[ + /*@ts2dart_Provider*/ {provide: CompilerConfig, useFactory: _createCompilerConfig, deps: []}, Lexer, Parser, HtmlParser, @@ -50,7 +51,6 @@ export const COMPILER_PROVIDERS: Array DEFAULT_PACKAGE_URL_PROVIDER, StyleCompiler, ViewCompiler, - /*@ts2dart_Provider*/ {provide: CompilerConfig, useFactory: _createCompilerConfig, deps: []}, RuntimeCompiler, /*@ts2dart_Provider*/ {provide: ComponentResolver, useExisting: RuntimeCompiler}, DomElementSchemaRegistry, diff --git a/modules/@angular/compiler/src/config.ts b/modules/@angular/compiler/src/config.ts index fe29bfa7f4..0232928542 100644 --- a/modules/@angular/compiler/src/config.ts +++ b/modules/@angular/compiler/src/config.ts @@ -5,12 +5,17 @@ import {CompileIdentifierMetadata} from './compile_metadata'; export class CompilerConfig { public renderTypes: RenderTypes; + public interpolateRegexp: RegExp; constructor(public genDebugInfo: boolean, public logBindingUpdate: boolean, - public useJit: boolean, renderTypes: RenderTypes = null) { + public useJit: boolean, renderTypes: RenderTypes = null, interpolateRegexp: RegExp = null) { if (isBlank(renderTypes)) { renderTypes = new DefaultRenderTypes(); } this.renderTypes = renderTypes; + if (isBlank(interpolateRegexp)) { + interpolateRegexp = DEFAULT_INTERPOLATE_REGEXP; + } + this.interpolateRegexp = interpolateRegexp; } } @@ -36,3 +41,8 @@ export class DefaultRenderTypes implements RenderTypes { renderNode = null; renderEvent = null; } + +/** + * A regexp pattern used to interpolate in default. + */ +export var DEFAULT_INTERPOLATE_REGEXP = /\{\{([\s\S]*?)\}\}/g; diff --git a/modules/@angular/compiler/src/expression_parser/parser.ts b/modules/@angular/compiler/src/expression_parser/parser.ts index 349b0642a7..8a4850fc49 100644 --- a/modules/@angular/compiler/src/expression_parser/parser.ts +++ b/modules/@angular/compiler/src/expression_parser/parser.ts @@ -1,4 +1,4 @@ -import {Injectable} from '@angular/core'; +import {Injectable, Inject} from '@angular/core'; import {isBlank, isPresent, StringWrapper} from '../../src/facade/lang'; import {BaseException} from '../../src/facade/exceptions'; import {ListWrapper} from '../../src/facade/collection'; @@ -46,11 +46,10 @@ import { AstVisitor, Quote } from './ast'; +import {CompilerConfig} from '../config'; var _implicitReceiver = new ImplicitReceiver(); -// TODO(tbosch): Cannot make this const/final right now because of the transpiler... -var INTERPOLATION_REGEXP = /\{\{([\s\S]*?)\}\}/g; class ParseException extends BaseException { constructor(message: string, input: string, errLocation: string, ctxLocation?: any) { @@ -69,7 +68,9 @@ export class TemplateBindingParseResult { @Injectable() export class Parser { constructor(/** @internal */ - public _lexer: Lexer) {} + public _lexer: Lexer, + /** @internal */ + public _config: CompilerConfig) {} parseAction(input: string, location: any): ASTWithSource { this._checkNoInterpolation(input, location); @@ -137,7 +138,7 @@ export class Parser { } splitInterpolation(input: string, location: string): SplitInterpolation { - var parts = StringWrapper.split(input, INTERPOLATION_REGEXP); + var parts = StringWrapper.split(input, this._config.interpolateRegexp); if (parts.length <= 1) { return null; } @@ -187,7 +188,7 @@ export class Parser { } private _checkNoInterpolation(input: string, location: any): void { - var parts = StringWrapper.split(input, INTERPOLATION_REGEXP); + var parts = StringWrapper.split(input, this._config.interpolateRegexp); if (parts.length > 1) { throw new ParseException('Got interpolation ({{}}) where expression was expected', input, `at column ${this._findInterpolationErrorColumn(parts, 1)} in`, diff --git a/modules/@angular/compiler/test/expression_parser/parser_spec.ts b/modules/@angular/compiler/test/expression_parser/parser_spec.ts index de3c298905..6f28992b9b 100644 --- a/modules/@angular/compiler/test/expression_parser/parser_spec.ts +++ b/modules/@angular/compiler/test/expression_parser/parser_spec.ts @@ -2,11 +2,12 @@ import {ddescribe, describe, it, xit, iit, expect, beforeEach} from '@angular/co import {isBlank, isPresent} from '../../src/facade/lang'; import {Parser} from '@angular/compiler/src/expression_parser/parser'; import {Unparser} from './unparser'; +import {CompilerConfig} from '@angular/compiler'; import {Lexer} from '@angular/compiler/src/expression_parser/lexer'; import {BindingPipe, LiteralPrimitive, AST} from '@angular/compiler/src/expression_parser/ast'; export function main() { - function createParser() { return new Parser(new Lexer()); } + function createParser() { return new Parser(new Lexer(), new CompilerConfig(true, true, true)); } function parseAction(text, location = null): any { return createParser().parseAction(text, location); @@ -453,6 +454,14 @@ export function main() { checkInterpolation(`{{ 'foo' +\n 'bar' +\r 'baz' }}`, `{{ "foo" + "bar" + "baz" }}`); }); + it('should support custom interpolation regexp', () => { + var customParser = new Parser(new Lexer(), new CompilerConfig(true, true, true, null, /<<([\s\S]*?)>>/g)); + var ast = (customParser.parseInterpolation('<< a >>', null) as any).ast; + expect(ast.strings).toEqual(['', '']); + expect(ast.expressions.length).toEqual(1); + expect(ast.expressions[0].name).toEqual('a'); + }); + describe("comments", () => { it('should ignore comments in interpolation expressions', () => { checkInterpolation('{{a //comment}}', '{{ a }}'); }); diff --git a/modules/@angular/compiler/test/i18n/i18n_html_parser_spec.ts b/modules/@angular/compiler/test/i18n/i18n_html_parser_spec.ts index 6e4d59703b..5ab2da30e6 100644 --- a/modules/@angular/compiler/test/i18n/i18n_html_parser_spec.ts +++ b/modules/@angular/compiler/test/i18n/i18n_html_parser_spec.ts @@ -1,6 +1,7 @@ import {describe, expect, it, iit, ddescribe} from "@angular/core/testing/testing_internal"; import {I18nHtmlParser} from "@angular/compiler/src/i18n/i18n_html_parser"; import {Message, id} from "@angular/compiler/src/i18n/message"; +import {CompilerConfig} from "@angular/compiler/src/config"; import {Parser} from "@angular/compiler/src/expression_parser/parser"; import {Lexer} from "@angular/compiler/src/expression_parser/lexer"; import {StringMapWrapper} from "../../src/facade/collection"; @@ -14,7 +15,7 @@ export function main() { describe('I18nHtmlParser', () => { function parse(template: string, messages: {[key: string]: string}, implicitTags: string[] = [], implicitAttrs: {[k: string]: string[]} = {}): HtmlParseTreeResult { - var parser = new Parser(new Lexer()); + var parser = new Parser(new Lexer(), new CompilerConfig(true, true, true)); let htmlParser = new HtmlParser(); let msgs = ''; diff --git a/modules/@angular/compiler/test/i18n/message_extractor_spec.ts b/modules/@angular/compiler/test/i18n/message_extractor_spec.ts index 9438888e0d..8a9f521fe2 100644 --- a/modules/@angular/compiler/test/i18n/message_extractor_spec.ts +++ b/modules/@angular/compiler/test/i18n/message_extractor_spec.ts @@ -11,6 +11,7 @@ import { } from '@angular/core/testing/testing_internal'; import {HtmlParser} from '@angular/compiler/src/html_parser'; +import {CompilerConfig} from '@angular/compiler/src/config'; import {MessageExtractor, removeDuplicates} from '@angular/compiler/src/i18n/message_extractor'; import {Message} from '@angular/compiler/src/i18n/message'; import {Parser} from '@angular/compiler/src/expression_parser/parser'; @@ -22,7 +23,7 @@ export function main() { beforeEach(() => { let htmlParser = new HtmlParser(); - var parser = new Parser(new Lexer()); + var parser = new Parser(new Lexer(), new CompilerConfig(true, true, true)); extractor = new MessageExtractor(htmlParser, parser, ['i18n-tag'], {'i18n-el': ['trans']}); }); diff --git a/modules/@angular/compiler/test/offline_compiler_util.ts b/modules/@angular/compiler/test/offline_compiler_util.ts index dd1fbc6847..a4dd8dec2c 100644 --- a/modules/@angular/compiler/test/offline_compiler_util.ts +++ b/modules/@angular/compiler/test/offline_compiler_util.ts @@ -50,10 +50,11 @@ function _createOfflineCompiler(xhr: MockXHR, emitter: OutputEmitter): OfflineCo xhr.when(`${THIS_MODULE_PATH}/offline_compiler_compa.html`, 'Hello World {{user}}!'); var htmlParser = new HtmlParser(); var normalizer = new DirectiveNormalizer(xhr, urlResolver, htmlParser); + var config = new CompilerConfig(true, true, true); return new OfflineCompiler( - normalizer, new TemplateParser(new Parser(new Lexer()), new MockSchemaRegistry({}, {}), + normalizer, new TemplateParser(new Parser(new Lexer(), config), new MockSchemaRegistry({}, {}), htmlParser, new Console(), []), - new StyleCompiler(urlResolver), new ViewCompiler(new CompilerConfig(true, true, true)), + new StyleCompiler(urlResolver), new ViewCompiler(config), emitter, xhr); } @@ -79,4 +80,4 @@ export class SimpleJsImportGenerator implements ImportGenerator { return importedUrlStr; } } -} \ No newline at end of file +} diff --git a/modules/@angular/compiler_cli/src/codegen.ts b/modules/@angular/compiler_cli/src/codegen.ts index 1eaac18236..fb40de747a 100644 --- a/modules/@angular/compiler_cli/src/codegen.ts +++ b/modules/@angular/compiler_cli/src/codegen.ts @@ -157,12 +157,13 @@ export class CodeGenerator { StaticAndDynamicReflectionCapabilities.install(staticReflector); const htmlParser = new HtmlParser(); const normalizer = new DirectiveNormalizer(xhr, urlResolver, htmlParser); - const parser = new Parser(new Lexer()); + const config = new compiler.CompilerConfig(true, true, true); + const parser = new Parser(new Lexer(), config); const tmplParser = new TemplateParser(parser, new DomElementSchemaRegistry(), htmlParser, /*console*/ null, []); const offlineCompiler = new compiler.OfflineCompiler( normalizer, tmplParser, new StyleCompiler(urlResolver), - new ViewCompiler(new compiler.CompilerConfig(true, true, true)), + new ViewCompiler(config), new TypeScriptEmitter(reflectorHost), xhr); const resolver = new CompileMetadataResolver( new compiler.DirectiveResolver(staticReflector), new compiler.PipeResolver(staticReflector), diff --git a/modules_dart/transform/lib/src/transform/common/ng_compiler.dart b/modules_dart/transform/lib/src/transform/common/ng_compiler.dart index 994b4d8351..13c8db1d5e 100644 --- a/modules_dart/transform/lib/src/transform/common/ng_compiler.dart +++ b/modules_dart/transform/lib/src/transform/common/ng_compiler.dart @@ -24,7 +24,7 @@ OfflineCompiler createTemplateCompiler(AssetReader reader, var _urlResolver = createOfflineCompileUrlResolver(); // TODO(yjbanov): add router AST transformer when ready - var parser = new ng.Parser(new ng.Lexer()); + var parser = new ng.Parser(new ng.Lexer(), compilerConfig); var _htmlParser = _createHtmlParser(translations, parser); var templateParser = new TemplateParser( diff --git a/tools/public_api_guard/public_api_spec.ts b/tools/public_api_guard/public_api_spec.ts index c2be6953b3..7720f37482 100644 --- a/tools/public_api_guard/public_api_spec.ts +++ b/tools/public_api_guard/public_api_spec.ts @@ -1046,8 +1046,9 @@ const COMPILER = [ 'CompileQueryMetadata.selectors:Array', 'CompileQueryMetadata.toJson():{[key:string]:any}', 'CompilerConfig', - 'CompilerConfig.constructor(genDebugInfo:boolean, logBindingUpdate:boolean, useJit:boolean, renderTypes:RenderTypes)', + 'CompilerConfig.constructor(genDebugInfo:boolean, logBindingUpdate:boolean, useJit:boolean, renderTypes:RenderTypes, interpolateRegexp:RegExp)', 'CompilerConfig.renderTypes:RenderTypes', + 'CompilerConfig.interpolateRegexp:RegExp', 'CompileTemplateMetadata', 'CompileTemplateMetadata.animations:CompileAnimationEntryMetadata[]', 'CompileTemplateMetadata.constructor({encapsulation,template,templateUrl,styles,styleUrls,animations,ngContentSelectors}:{encapsulation?:ViewEncapsulation, template?:string, templateUrl?:string, styles?:string[], styleUrls?:string[], ngContentSelectors?:string[], animations?:CompileAnimationEntryMetadata[]})',