| 
									
										
										
										
											2016-04-07 17:17:50 -07:00
										 |  |  | import {CompileTypeMetadata, CompileDirectiveMetadata, CompileTemplateMetadata} from './directive_metadata'; | 
					
						
							| 
									
										
										
										
											2015-11-06 17:34:07 -08:00
										 |  |  | import {isPresent, isBlank} from 'angular2/src/facade/lang'; | 
					
						
							|  |  |  | import {BaseException} from 'angular2/src/facade/exceptions'; | 
					
						
							| 
									
										
										
										
											2016-02-08 13:24:09 -08:00
										 |  |  | import {PromiseWrapper} from 'angular2/src/facade/async'; | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-05 14:07:57 -08:00
										 |  |  | import {XHR} from 'angular2/src/compiler/xhr'; | 
					
						
							|  |  |  | import {UrlResolver} from 'angular2/src/compiler/url_resolver'; | 
					
						
							| 
									
										
										
										
											2015-10-14 09:39:40 -07:00
										 |  |  | import {extractStyleUrls, isStyleUrlResolvable} from './style_url_resolver'; | 
					
						
							| 
									
										
										
										
											2015-09-14 15:59:09 -07:00
										 |  |  | import {Injectable} from 'angular2/src/core/di'; | 
					
						
							| 
									
										
										
										
											2015-10-05 10:10:07 -07:00
										 |  |  | import {ViewEncapsulation} from 'angular2/src/core/metadata/view'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-07 17:17:50 -07:00
										 |  |  | import {HtmlAstVisitor, HtmlElementAst, HtmlTextAst, HtmlAttrAst, HtmlAst, HtmlCommentAst, htmlVisitAll} from './html_ast'; | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  | import {HtmlParser} from './html_parser'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  | import {preparseElement, PreparsedElement, PreparsedElementType} from './template_preparser'; | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-14 15:59:09 -07:00
										 |  |  | @Injectable() | 
					
						
							|  |  |  | export class TemplateNormalizer { | 
					
						
							| 
									
										
										
										
											2016-04-07 17:17:50 -07:00
										 |  |  |   constructor( | 
					
						
							|  |  |  |       private _xhr: XHR, private _urlResolver: UrlResolver, private _htmlParser: HtmlParser) {} | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-07 17:17:50 -07:00
										 |  |  |   normalizeTemplate(directiveType: CompileTypeMetadata, template: CompileTemplateMetadata): | 
					
						
							|  |  |  |       Promise<CompileTemplateMetadata> { | 
					
						
							| 
									
										
										
										
											2015-09-14 15:59:09 -07:00
										 |  |  |     if (isPresent(template.template)) { | 
					
						
							|  |  |  |       return PromiseWrapper.resolve(this.normalizeLoadedTemplate( | 
					
						
							| 
									
										
										
										
											2015-10-01 10:07:49 -07:00
										 |  |  |           directiveType, template, template.template, directiveType.moduleUrl)); | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |     } else if (isPresent(template.templateUrl)) { | 
					
						
							| 
									
										
										
										
											2015-10-01 10:07:49 -07:00
										 |  |  |       var sourceAbsUrl = this._urlResolver.resolve(directiveType.moduleUrl, template.templateUrl); | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |       return this._xhr.get(sourceAbsUrl) | 
					
						
							| 
									
										
										
										
											2016-04-07 17:17:50 -07:00
										 |  |  |           .then( | 
					
						
							|  |  |  |               templateContent => this.normalizeLoadedTemplate( | 
					
						
							|  |  |  |                   directiveType, template, templateContent, sourceAbsUrl)); | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |     } else { | 
					
						
							|  |  |  |       throw new BaseException(`No template specified for component ${directiveType.name}`); | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-07 17:17:50 -07:00
										 |  |  |   normalizeLoadedTemplate( | 
					
						
							|  |  |  |       directiveType: CompileTypeMetadata, templateMeta: CompileTemplateMetadata, template: string, | 
					
						
							|  |  |  |       templateAbsUrl: string): CompileTemplateMetadata { | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |     var rootNodesAndErrors = this._htmlParser.parse(template, directiveType.name); | 
					
						
							|  |  |  |     if (rootNodesAndErrors.errors.length > 0) { | 
					
						
							|  |  |  |       var errorString = rootNodesAndErrors.errors.join('\n'); | 
					
						
							|  |  |  |       throw new BaseException(`Template parse errors:\n${errorString}`); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |     var visitor = new TemplatePreparseVisitor(); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |     htmlVisitAll(visitor, rootNodesAndErrors.rootNodes); | 
					
						
							| 
									
										
										
										
											2015-09-14 15:59:09 -07:00
										 |  |  |     var allStyles = templateMeta.styles.concat(visitor.styles); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     var allStyleAbsUrls = | 
					
						
							| 
									
										
										
										
											2015-10-09 09:07:58 -07:00
										 |  |  |         visitor.styleUrls.filter(isStyleUrlResolvable) | 
					
						
							| 
									
										
										
										
											2015-10-27 14:00:15 -07:00
										 |  |  |             .map(url => this._urlResolver.resolve(templateAbsUrl, url)) | 
					
						
							| 
									
										
										
										
											2015-10-09 09:07:58 -07:00
										 |  |  |             .concat(templateMeta.styleUrls.filter(isStyleUrlResolvable) | 
					
						
							| 
									
										
										
										
											2015-10-27 14:00:15 -07:00
										 |  |  |                         .map(url => this._urlResolver.resolve(directiveType.moduleUrl, url))); | 
					
						
							| 
									
										
										
										
											2015-10-23 00:17:30 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-02 15:07:31 -07:00
										 |  |  |     var allResolvedStyles = allStyles.map(style => { | 
					
						
							| 
									
										
										
										
											2015-10-14 09:39:40 -07:00
										 |  |  |       var styleWithImports = extractStyleUrls(this._urlResolver, templateAbsUrl, style); | 
					
						
							| 
									
										
										
										
											2015-09-14 15:59:09 -07:00
										 |  |  |       styleWithImports.styleUrls.forEach(styleUrl => allStyleAbsUrls.push(styleUrl)); | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |       return styleWithImports.style; | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2015-10-23 00:17:30 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |     var encapsulation = templateMeta.encapsulation; | 
					
						
							|  |  |  |     if (encapsulation === ViewEncapsulation.Emulated && allResolvedStyles.length === 0 && | 
					
						
							|  |  |  |         allStyleAbsUrls.length === 0) { | 
					
						
							|  |  |  |       encapsulation = ViewEncapsulation.None; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return new CompileTemplateMetadata({ | 
					
						
							|  |  |  |       encapsulation: encapsulation, | 
					
						
							|  |  |  |       template: template, | 
					
						
							|  |  |  |       templateUrl: templateAbsUrl, | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |       styles: allResolvedStyles, | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |       styleUrls: allStyleAbsUrls, | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |       ngContentSelectors: visitor.ngContentSelectors | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class TemplatePreparseVisitor implements HtmlAstVisitor { | 
					
						
							|  |  |  |   ngContentSelectors: string[] = []; | 
					
						
							|  |  |  |   styles: string[] = []; | 
					
						
							|  |  |  |   styleUrls: string[] = []; | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |   ngNonBindableStackCount: number = 0; | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |   visitElement(ast: HtmlElementAst, context: any): any { | 
					
						
							|  |  |  |     var preparsedElement = preparseElement(ast); | 
					
						
							|  |  |  |     switch (preparsedElement.type) { | 
					
						
							|  |  |  |       case PreparsedElementType.NG_CONTENT: | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |         if (this.ngNonBindableStackCount === 0) { | 
					
						
							|  |  |  |           this.ngContentSelectors.push(preparsedElement.selectAttr); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |         break; | 
					
						
							|  |  |  |       case PreparsedElementType.STYLE: | 
					
						
							|  |  |  |         var textContent = ''; | 
					
						
							|  |  |  |         ast.children.forEach(child => { | 
					
						
							|  |  |  |           if (child instanceof HtmlTextAst) { | 
					
						
							|  |  |  |             textContent += (<HtmlTextAst>child).value; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         this.styles.push(textContent); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |       case PreparsedElementType.STYLESHEET: | 
					
						
							|  |  |  |         this.styleUrls.push(preparsedElement.hrefAttr); | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2016-01-25 17:57:29 -08:00
										 |  |  |       default: | 
					
						
							|  |  |  |         // DDC reports this as error. See:
 | 
					
						
							|  |  |  |         // https://github.com/dart-lang/dev_compiler/issues/428
 | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |     if (preparsedElement.nonBindable) { | 
					
						
							|  |  |  |       this.ngNonBindableStackCount++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     htmlVisitAll(this, ast.children); | 
					
						
							|  |  |  |     if (preparsedElement.nonBindable) { | 
					
						
							|  |  |  |       this.ngNonBindableStackCount--; | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |     return null; | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-03-06 20:21:20 -08:00
										 |  |  |   visitComment(ast: HtmlCommentAst, context: any): any { return null; } | 
					
						
							| 
									
										
										
										
											2015-09-18 10:33:23 -07:00
										 |  |  |   visitAttr(ast: HtmlAttrAst, context: any): any { return null; } | 
					
						
							|  |  |  |   visitText(ast: HtmlTextAst, context: any): any { return null; } | 
					
						
							| 
									
										
										
										
											2015-08-25 15:36:02 -07:00
										 |  |  | } |