| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  | import { | 
					
						
							|  |  |  |   ddescribe, | 
					
						
							|  |  |  |   describe, | 
					
						
							|  |  |  |   it, | 
					
						
							|  |  |  |   iit, | 
					
						
							|  |  |  |   xit, | 
					
						
							|  |  |  |   expect, | 
					
						
							|  |  |  |   beforeEach, | 
					
						
							|  |  |  |   afterEach | 
					
						
							|  |  |  | } from 'angular2/testing_internal'; | 
					
						
							| 
									
										
										
										
											2015-11-10 15:56:25 -08:00
										 |  |  | import {BaseException} from 'angular2/src/facade/exceptions'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  | import { | 
					
						
							|  |  |  |   tokenizeHtml, | 
					
						
							|  |  |  |   HtmlToken, | 
					
						
							|  |  |  |   HtmlTokenType, | 
					
						
							|  |  |  |   HtmlTokenError | 
					
						
							|  |  |  | } from 'angular2/src/compiler/html_lexer'; | 
					
						
							| 
									
										
										
										
											2015-11-10 15:56:25 -08:00
										 |  |  | import {ParseSourceSpan, ParseLocation, ParseSourceFile} from 'angular2/src/compiler/parse_util'; | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | export function main() { | 
					
						
							|  |  |  |   describe('HtmlLexer', () => { | 
					
						
							|  |  |  |     describe('line/column numbers', () => { | 
					
						
							|  |  |  |       it('should work without newlines', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeLineColumn('<t>a</t>')) | 
					
						
							|  |  |  |             .toEqual([ | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_START, '0:0'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_END, '0:2'], | 
					
						
							|  |  |  |               [HtmlTokenType.TEXT, '0:3'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_CLOSE, '0:4'], | 
					
						
							|  |  |  |               [HtmlTokenType.EOF, '0:8'] | 
					
						
							|  |  |  |             ]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should work with one newline', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeLineColumn('<t>\na</t>')) | 
					
						
							|  |  |  |             .toEqual([ | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_START, '0:0'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_END, '0:2'], | 
					
						
							|  |  |  |               [HtmlTokenType.TEXT, '0:3'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_CLOSE, '1:1'], | 
					
						
							|  |  |  |               [HtmlTokenType.EOF, '1:5'] | 
					
						
							|  |  |  |             ]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should work with multiple newlines', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeLineColumn('<t\n>\na</t>')) | 
					
						
							|  |  |  |             .toEqual([ | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_START, '0:0'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_END, '1:0'], | 
					
						
							|  |  |  |               [HtmlTokenType.TEXT, '1:1'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_CLOSE, '2:1'], | 
					
						
							|  |  |  |               [HtmlTokenType.EOF, '2:5'] | 
					
						
							|  |  |  |             ]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							| 
									
										
										
										
											2015-12-04 23:12:31 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |       it('should work with CR and LF', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeLineColumn('<t\n>\r\na\r</t>')) | 
					
						
							|  |  |  |             .toEqual([ | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_START, '0:0'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_END, '1:0'], | 
					
						
							|  |  |  |               [HtmlTokenType.TEXT, '1:1'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_CLOSE, '2:1'], | 
					
						
							|  |  |  |               [HtmlTokenType.EOF, '2:5'] | 
					
						
							|  |  |  |             ]); | 
					
						
							| 
									
										
										
										
											2015-12-04 23:12:31 -08:00
										 |  |  |       }); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     describe('comments', () => { | 
					
						
							|  |  |  |       it('should parse comments', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeParts('<!--t\ne\rs\r\nt-->')) | 
					
						
							|  |  |  |             .toEqual([ | 
					
						
							|  |  |  |               [HtmlTokenType.COMMENT_START], | 
					
						
							|  |  |  |               [HtmlTokenType.RAW_TEXT, 't\ne\ns\nt'], | 
					
						
							|  |  |  |               [HtmlTokenType.COMMENT_END], | 
					
						
							|  |  |  |               [HtmlTokenType.EOF] | 
					
						
							|  |  |  |             ]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-04 23:12:31 -08:00
										 |  |  |       it('should store the locations', | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |          () => {expect(tokenizeAndHumanizeSourceSpans('<!--t\ne\rs\r\nt-->')) | 
					
						
							|  |  |  |                     .toEqual([ | 
					
						
							|  |  |  |                       [HtmlTokenType.COMMENT_START, '<!--'], | 
					
						
							|  |  |  |                       [HtmlTokenType.RAW_TEXT, 't\ne\rs\r\nt'], | 
					
						
							|  |  |  |                       [HtmlTokenType.COMMENT_END, '-->'], | 
					
						
							|  |  |  |                       [HtmlTokenType.EOF, ''] | 
					
						
							|  |  |  |                     ])}); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |       it('should report <!- without -', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeErrors('<!-a')) | 
					
						
							|  |  |  |             .toEqual([[HtmlTokenType.COMMENT_START, 'Unexpected character "a"', '0:3']]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should report missing end comment', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeErrors('<!--')) | 
					
						
							|  |  |  |             .toEqual([[HtmlTokenType.RAW_TEXT, 'Unexpected character "EOF"', '0:4']]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     describe('doctype', () => { | 
					
						
							|  |  |  |       it('should parse doctypes', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeParts('<!doctype html>')) | 
					
						
							|  |  |  |             .toEqual([[HtmlTokenType.DOC_TYPE, 'doctype html'], [HtmlTokenType.EOF]]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should store the locations', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeSourceSpans('<!doctype html>')) | 
					
						
							|  |  |  |             .toEqual([[HtmlTokenType.DOC_TYPE, '<!doctype html>'], [HtmlTokenType.EOF, '']]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should report missing end doctype', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeErrors('<!')) | 
					
						
							|  |  |  |             .toEqual([[HtmlTokenType.DOC_TYPE, 'Unexpected character "EOF"', '0:2']]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-21 11:32:58 -08:00
										 |  |  |     describe('CDATA', () => { | 
					
						
							|  |  |  |       it('should parse CDATA', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeParts('<![CDATA[t\ne\rs\r\nt]]>')) | 
					
						
							|  |  |  |             .toEqual([ | 
					
						
							|  |  |  |               [HtmlTokenType.CDATA_START], | 
					
						
							|  |  |  |               [HtmlTokenType.RAW_TEXT, 't\ne\ns\nt'], | 
					
						
							|  |  |  |               [HtmlTokenType.CDATA_END], | 
					
						
							|  |  |  |               [HtmlTokenType.EOF] | 
					
						
							|  |  |  |             ]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should store the locations', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeSourceSpans('<![CDATA[t\ne\rs\r\nt]]>')) | 
					
						
							|  |  |  |             .toEqual([ | 
					
						
							|  |  |  |               [HtmlTokenType.CDATA_START, '<![CDATA['], | 
					
						
							|  |  |  |               [HtmlTokenType.RAW_TEXT, 't\ne\rs\r\nt'], | 
					
						
							|  |  |  |               [HtmlTokenType.CDATA_END, ']]>'], | 
					
						
							|  |  |  |               [HtmlTokenType.EOF, ''] | 
					
						
							|  |  |  |             ]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-21 11:32:58 -08:00
										 |  |  |       it('should report <![ without CDATA[', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeErrors('<![a')) | 
					
						
							|  |  |  |             .toEqual([[HtmlTokenType.CDATA_START, 'Unexpected character "a"', '0:3']]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should report missing end cdata', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeErrors('<![CDATA[')) | 
					
						
							|  |  |  |             .toEqual([[HtmlTokenType.RAW_TEXT, 'Unexpected character "EOF"', '0:9']]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     describe('open tags', () => { | 
					
						
							|  |  |  |       it('should parse open tags without prefix', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeParts('<test>')) | 
					
						
							|  |  |  |             .toEqual([ | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_START, null, 'test'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_END], | 
					
						
							|  |  |  |               [HtmlTokenType.EOF] | 
					
						
							|  |  |  |             ]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should parse namespace prefix', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeParts('<ns1:test>')) | 
					
						
							|  |  |  |             .toEqual([ | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_START, 'ns1', 'test'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_END], | 
					
						
							|  |  |  |               [HtmlTokenType.EOF] | 
					
						
							|  |  |  |             ]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should parse void tags', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeParts('<test/>')) | 
					
						
							|  |  |  |             .toEqual([ | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_START, null, 'test'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_END_VOID], | 
					
						
							|  |  |  |               [HtmlTokenType.EOF] | 
					
						
							|  |  |  |             ]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-06 13:12:41 -08:00
										 |  |  |       it('should allow whitespace after the tag name', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeParts('<test >')) | 
					
						
							|  |  |  |             .toEqual([ | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_START, null, 'test'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_END], | 
					
						
							|  |  |  |               [HtmlTokenType.EOF] | 
					
						
							|  |  |  |             ]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should store the locations', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeSourceSpans('<test>')) | 
					
						
							|  |  |  |             .toEqual([ | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_START, '<test'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_END, '>'], | 
					
						
							|  |  |  |               [HtmlTokenType.EOF, ''] | 
					
						
							|  |  |  |             ]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     describe('attributes', () => { | 
					
						
							|  |  |  |       it('should parse attributes without prefix', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeParts('<t a>')) | 
					
						
							|  |  |  |             .toEqual([ | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_START, null, 't'], | 
					
						
							|  |  |  |               [HtmlTokenType.ATTR_NAME, null, 'a'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_END], | 
					
						
							|  |  |  |               [HtmlTokenType.EOF] | 
					
						
							|  |  |  |             ]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should parse attributes with prefix', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeParts('<t ns1:a>')) | 
					
						
							|  |  |  |             .toEqual([ | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_START, null, 't'], | 
					
						
							|  |  |  |               [HtmlTokenType.ATTR_NAME, 'ns1', 'a'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_END], | 
					
						
							|  |  |  |               [HtmlTokenType.EOF] | 
					
						
							|  |  |  |             ]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should parse attributes whose prefix is not valid', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeParts('<t (ns1:a)>')) | 
					
						
							|  |  |  |             .toEqual([ | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_START, null, 't'], | 
					
						
							|  |  |  |               [HtmlTokenType.ATTR_NAME, null, '(ns1:a)'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_END], | 
					
						
							|  |  |  |               [HtmlTokenType.EOF] | 
					
						
							|  |  |  |             ]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should parse attributes with single quote value', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeParts("<t a='b'>")) | 
					
						
							|  |  |  |             .toEqual([ | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_START, null, 't'], | 
					
						
							|  |  |  |               [HtmlTokenType.ATTR_NAME, null, 'a'], | 
					
						
							|  |  |  |               [HtmlTokenType.ATTR_VALUE, 'b'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_END], | 
					
						
							|  |  |  |               [HtmlTokenType.EOF] | 
					
						
							|  |  |  |             ]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should parse attributes with double quote value', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeParts('<t a="b">')) | 
					
						
							|  |  |  |             .toEqual([ | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_START, null, 't'], | 
					
						
							|  |  |  |               [HtmlTokenType.ATTR_NAME, null, 'a'], | 
					
						
							|  |  |  |               [HtmlTokenType.ATTR_VALUE, 'b'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_END], | 
					
						
							|  |  |  |               [HtmlTokenType.EOF] | 
					
						
							|  |  |  |             ]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should parse attributes with unquoted value', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeParts('<t a=b>')) | 
					
						
							|  |  |  |             .toEqual([ | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_START, null, 't'], | 
					
						
							|  |  |  |               [HtmlTokenType.ATTR_NAME, null, 'a'], | 
					
						
							|  |  |  |               [HtmlTokenType.ATTR_VALUE, 'b'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_END], | 
					
						
							|  |  |  |               [HtmlTokenType.EOF] | 
					
						
							|  |  |  |             ]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should allow whitespace', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeParts('<t a = b >')) | 
					
						
							|  |  |  |             .toEqual([ | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_START, null, 't'], | 
					
						
							|  |  |  |               [HtmlTokenType.ATTR_NAME, null, 'a'], | 
					
						
							|  |  |  |               [HtmlTokenType.ATTR_VALUE, 'b'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_END], | 
					
						
							|  |  |  |               [HtmlTokenType.EOF] | 
					
						
							|  |  |  |             ]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should parse attributes with entities in values', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeParts('<t a="AA">')) | 
					
						
							|  |  |  |             .toEqual([ | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_START, null, 't'], | 
					
						
							|  |  |  |               [HtmlTokenType.ATTR_NAME, null, 'a'], | 
					
						
							|  |  |  |               [HtmlTokenType.ATTR_VALUE, 'AA'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_END], | 
					
						
							|  |  |  |               [HtmlTokenType.EOF] | 
					
						
							|  |  |  |             ]); | 
					
						
							| 
									
										
										
										
											2015-11-10 15:56:25 -08:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should not decode entities without trailing ";"', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeParts('<t a="&" b="c&&d">')) | 
					
						
							|  |  |  |             .toEqual([ | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_START, null, 't'], | 
					
						
							|  |  |  |               [HtmlTokenType.ATTR_NAME, null, 'a'], | 
					
						
							|  |  |  |               [HtmlTokenType.ATTR_VALUE, '&'], | 
					
						
							|  |  |  |               [HtmlTokenType.ATTR_NAME, null, 'b'], | 
					
						
							|  |  |  |               [HtmlTokenType.ATTR_VALUE, 'c&&d'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_END], | 
					
						
							|  |  |  |               [HtmlTokenType.EOF] | 
					
						
							|  |  |  |             ]); | 
					
						
							| 
									
										
										
										
											2015-11-10 15:56:25 -08:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should parse attributes with "&" in values', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeParts('<t a="b && c &">')) | 
					
						
							|  |  |  |             .toEqual([ | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_START, null, 't'], | 
					
						
							|  |  |  |               [HtmlTokenType.ATTR_NAME, null, 'a'], | 
					
						
							|  |  |  |               [HtmlTokenType.ATTR_VALUE, 'b && c &'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_END], | 
					
						
							|  |  |  |               [HtmlTokenType.EOF] | 
					
						
							|  |  |  |             ]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-04 23:12:31 -08:00
										 |  |  |       it('should parse values with CR and LF', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeParts("<t a='t\ne\rs\r\nt'>")) | 
					
						
							|  |  |  |             .toEqual([ | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_START, null, 't'], | 
					
						
							|  |  |  |               [HtmlTokenType.ATTR_NAME, null, 'a'], | 
					
						
							|  |  |  |               [HtmlTokenType.ATTR_VALUE, 't\ne\ns\nt'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_END], | 
					
						
							|  |  |  |               [HtmlTokenType.EOF] | 
					
						
							|  |  |  |             ]); | 
					
						
							| 
									
										
										
										
											2015-12-04 23:12:31 -08:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       it('should store the locations', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeSourceSpans('<t a=b>')) | 
					
						
							|  |  |  |             .toEqual([ | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_START, '<t'], | 
					
						
							|  |  |  |               [HtmlTokenType.ATTR_NAME, 'a'], | 
					
						
							|  |  |  |               [HtmlTokenType.ATTR_VALUE, 'b'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_END, '>'], | 
					
						
							|  |  |  |               [HtmlTokenType.EOF, ''] | 
					
						
							|  |  |  |             ]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     describe('closing tags', () => { | 
					
						
							|  |  |  |       it('should parse closing tags without prefix', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeParts('</test>')) | 
					
						
							|  |  |  |             .toEqual([[HtmlTokenType.TAG_CLOSE, null, 'test'], [HtmlTokenType.EOF]]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should parse closing tags with prefix', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeParts('</ns1:test>')) | 
					
						
							|  |  |  |             .toEqual([[HtmlTokenType.TAG_CLOSE, 'ns1', 'test'], [HtmlTokenType.EOF]]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should allow whitespace', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeParts('</ test >')) | 
					
						
							|  |  |  |             .toEqual([[HtmlTokenType.TAG_CLOSE, null, 'test'], [HtmlTokenType.EOF]]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should store the locations', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeSourceSpans('</test>')) | 
					
						
							|  |  |  |             .toEqual([[HtmlTokenType.TAG_CLOSE, '</test>'], [HtmlTokenType.EOF, '']]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should report missing name after </', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeErrors('</')) | 
					
						
							|  |  |  |             .toEqual([[HtmlTokenType.TAG_CLOSE, 'Unexpected character "EOF"', '0:2']]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should report missing >', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeErrors('</test')) | 
					
						
							|  |  |  |             .toEqual([[HtmlTokenType.TAG_CLOSE, 'Unexpected character "EOF"', '0:6']]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     describe('entities', () => { | 
					
						
							|  |  |  |       it('should parse named entities', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeParts('a&b')) | 
					
						
							|  |  |  |             .toEqual([[HtmlTokenType.TEXT, 'a&b'], [HtmlTokenType.EOF]]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should parse hexadecimal entities', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeParts('AA')) | 
					
						
							|  |  |  |             .toEqual([[HtmlTokenType.TEXT, 'AA'], [HtmlTokenType.EOF]]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should parse decimal entities', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeParts('A')) | 
					
						
							|  |  |  |             .toEqual([[HtmlTokenType.TEXT, 'A'], [HtmlTokenType.EOF]]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should store the locations', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeSourceSpans('a&b')) | 
					
						
							|  |  |  |             .toEqual([[HtmlTokenType.TEXT, 'a&b'], [HtmlTokenType.EOF, '']]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 15:56:25 -08:00
										 |  |  |       it('should report malformed/unknown entities', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeErrors('&tbo;')) | 
					
						
							|  |  |  |             .toEqual([ | 
					
						
							|  |  |  |               [ | 
					
						
							|  |  |  |                 HtmlTokenType.TEXT, | 
					
						
							|  |  |  |                 'Unknown entity "tbo" - use the "&#<decimal>;" or  "&#x<hex>;" syntax', | 
					
						
							|  |  |  |                 '0:0' | 
					
						
							|  |  |  |               ] | 
					
						
							|  |  |  |             ]); | 
					
						
							|  |  |  |         expect(tokenizeAndHumanizeErrors('&#asdf;')) | 
					
						
							|  |  |  |             .toEqual([[HtmlTokenType.TEXT, 'Unexpected character "s"', '0:3']]); | 
					
						
							|  |  |  |         expect(tokenizeAndHumanizeErrors('
sdf;')) | 
					
						
							|  |  |  |             .toEqual([[HtmlTokenType.TEXT, 'Unexpected character "s"', '0:4']]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(tokenizeAndHumanizeErrors('઼')) | 
					
						
							|  |  |  |             .toEqual([[HtmlTokenType.TEXT, 'Unexpected character "EOF"', '0:6']]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     describe('regular text', () => { | 
					
						
							|  |  |  |       it('should parse text', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeParts('a')) | 
					
						
							|  |  |  |             .toEqual([[HtmlTokenType.TEXT, 'a'], [HtmlTokenType.EOF]]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-04 23:12:31 -08:00
										 |  |  |       it('should handle CR & LF', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeParts('t\ne\rs\r\nt')) | 
					
						
							|  |  |  |             .toEqual([[HtmlTokenType.TEXT, 't\ne\ns\nt'], [HtmlTokenType.EOF]]); | 
					
						
							| 
									
										
										
										
											2015-12-04 23:12:31 -08:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       it('should parse entities', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeParts('a&b')) | 
					
						
							|  |  |  |             .toEqual([[HtmlTokenType.TEXT, 'a&b'], [HtmlTokenType.EOF]]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 15:56:25 -08:00
										 |  |  |       it('should parse text starting with "&"', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeParts('a && b &')) | 
					
						
							|  |  |  |             .toEqual([[HtmlTokenType.TEXT, 'a && b &'], [HtmlTokenType.EOF]]); | 
					
						
							| 
									
										
										
										
											2015-11-10 15:56:25 -08:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       it('should store the locations', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeSourceSpans('a')) | 
					
						
							|  |  |  |             .toEqual([[HtmlTokenType.TEXT, 'a'], [HtmlTokenType.EOF, '']]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							| 
									
										
										
										
											2015-12-06 13:11:00 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |       it('should allow "<" in text nodes', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeParts('{{ a < b ? c : d }}')) | 
					
						
							|  |  |  |             .toEqual([[HtmlTokenType.TEXT, '{{ a < b ? c : d }}'], [HtmlTokenType.EOF]]); | 
					
						
							| 
									
										
										
										
											2015-12-06 13:11:00 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeSourceSpans('<p>a<b</p>')) | 
					
						
							|  |  |  |             .toEqual([ | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_START, '<p'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_END, '>'], | 
					
						
							|  |  |  |               [HtmlTokenType.TEXT, 'a<b'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_CLOSE, '</p>'], | 
					
						
							|  |  |  |               [HtmlTokenType.EOF, ''], | 
					
						
							|  |  |  |             ]); | 
					
						
							| 
									
										
										
										
											2015-12-06 13:12:41 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeParts('< a>')) | 
					
						
							|  |  |  |             .toEqual([[HtmlTokenType.TEXT, '< a>'], [HtmlTokenType.EOF]]); | 
					
						
							| 
									
										
										
										
											2015-12-06 13:11:00 -08:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // TODO(vicb): make the lexer aware of Angular expressions
 | 
					
						
							|  |  |  |       // see https://github.com/angular/angular/issues/5679
 | 
					
						
							|  |  |  |       it('should parse valid start tag in interpolation', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeParts('{{ a <b && c > d }}')) | 
					
						
							|  |  |  |             .toEqual([ | 
					
						
							|  |  |  |               [HtmlTokenType.TEXT, '{{ a '], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_START, null, 'b'], | 
					
						
							|  |  |  |               [HtmlTokenType.ATTR_NAME, null, '&&'], | 
					
						
							|  |  |  |               [HtmlTokenType.ATTR_NAME, null, 'c'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_END], | 
					
						
							|  |  |  |               [HtmlTokenType.TEXT, ' d }}'], | 
					
						
							|  |  |  |               [HtmlTokenType.EOF] | 
					
						
							|  |  |  |             ]); | 
					
						
							| 
									
										
										
										
											2015-12-06 13:11:00 -08:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     describe('raw text', () => { | 
					
						
							|  |  |  |       it('should parse text', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeParts(`<script>t\ne\rs\r\nt</script>`)) | 
					
						
							|  |  |  |             .toEqual([ | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_START, null, 'script'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_END], | 
					
						
							|  |  |  |               [HtmlTokenType.RAW_TEXT, 't\ne\ns\nt'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_CLOSE, null, 'script'], | 
					
						
							|  |  |  |               [HtmlTokenType.EOF] | 
					
						
							|  |  |  |             ]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should not detect entities', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeParts(`<script>&</SCRIPT>`)) | 
					
						
							|  |  |  |             .toEqual([ | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_START, null, 'script'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_END], | 
					
						
							|  |  |  |               [HtmlTokenType.RAW_TEXT, '&'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_CLOSE, null, 'script'], | 
					
						
							|  |  |  |               [HtmlTokenType.EOF] | 
					
						
							|  |  |  |             ]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should ignore other opening tags', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeParts(`<script>a<div></script>`)) | 
					
						
							|  |  |  |             .toEqual([ | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_START, null, 'script'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_END], | 
					
						
							|  |  |  |               [HtmlTokenType.RAW_TEXT, 'a<div>'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_CLOSE, null, 'script'], | 
					
						
							|  |  |  |               [HtmlTokenType.EOF] | 
					
						
							|  |  |  |             ]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should ignore other closing tags', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeParts(`<script>a</test></script>`)) | 
					
						
							|  |  |  |             .toEqual([ | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_START, null, 'script'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_END], | 
					
						
							|  |  |  |               [HtmlTokenType.RAW_TEXT, 'a</test>'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_CLOSE, null, 'script'], | 
					
						
							|  |  |  |               [HtmlTokenType.EOF] | 
					
						
							|  |  |  |             ]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should store the locations', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeSourceSpans(`<script>a</script>`)) | 
					
						
							|  |  |  |             .toEqual([ | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_START, '<script'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_END, '>'], | 
					
						
							|  |  |  |               [HtmlTokenType.RAW_TEXT, 'a'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_CLOSE, '</script>'], | 
					
						
							|  |  |  |               [HtmlTokenType.EOF, ''] | 
					
						
							|  |  |  |             ]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     describe('escapable raw text', () => { | 
					
						
							|  |  |  |       it('should parse text', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeParts(`<title>t\ne\rs\r\nt</title>`)) | 
					
						
							|  |  |  |             .toEqual([ | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_START, null, 'title'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_END], | 
					
						
							|  |  |  |               [HtmlTokenType.ESCAPABLE_RAW_TEXT, 't\ne\ns\nt'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_CLOSE, null, 'title'], | 
					
						
							|  |  |  |               [HtmlTokenType.EOF] | 
					
						
							|  |  |  |             ]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should detect entities', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeParts(`<title>&</title>`)) | 
					
						
							|  |  |  |             .toEqual([ | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_START, null, 'title'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_END], | 
					
						
							|  |  |  |               [HtmlTokenType.ESCAPABLE_RAW_TEXT, '&'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_CLOSE, null, 'title'], | 
					
						
							|  |  |  |               [HtmlTokenType.EOF] | 
					
						
							|  |  |  |             ]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should ignore other opening tags', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeParts(`<title>a<div></title>`)) | 
					
						
							|  |  |  |             .toEqual([ | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_START, null, 'title'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_END], | 
					
						
							|  |  |  |               [HtmlTokenType.ESCAPABLE_RAW_TEXT, 'a<div>'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_CLOSE, null, 'title'], | 
					
						
							|  |  |  |               [HtmlTokenType.EOF] | 
					
						
							|  |  |  |             ]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should ignore other closing tags', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeParts(`<title>a</test></title>`)) | 
					
						
							|  |  |  |             .toEqual([ | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_START, null, 'title'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_END], | 
					
						
							|  |  |  |               [HtmlTokenType.ESCAPABLE_RAW_TEXT, 'a</test>'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_CLOSE, null, 'title'], | 
					
						
							|  |  |  |               [HtmlTokenType.EOF] | 
					
						
							|  |  |  |             ]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should store the locations', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeSourceSpans(`<title>a</title>`)) | 
					
						
							|  |  |  |             .toEqual([ | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_START, '<title'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_END, '>'], | 
					
						
							|  |  |  |               [HtmlTokenType.ESCAPABLE_RAW_TEXT, 'a'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_CLOSE, '</title>'], | 
					
						
							|  |  |  |               [HtmlTokenType.EOF, ''] | 
					
						
							|  |  |  |             ]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 15:56:25 -08:00
										 |  |  |     describe('errors', () => { | 
					
						
							|  |  |  |       it('should include 2 lines of context in message', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         let src = "111\n222\n333\nE\n444\n555\n666\n"; | 
					
						
							| 
									
										
										
										
											2015-11-10 15:56:25 -08:00
										 |  |  |         let file = new ParseSourceFile(src, 'file://'); | 
					
						
							|  |  |  |         let location = new ParseLocation(file, 12, 123, 456); | 
					
						
							| 
									
										
										
										
											2016-02-16 16:46:51 -08:00
										 |  |  |         let span = new ParseSourceSpan(location, location); | 
					
						
							|  |  |  |         let error = new HtmlTokenError('**ERROR**', null, span); | 
					
						
							| 
									
										
										
										
											2015-11-10 15:56:25 -08:00
										 |  |  |         expect(error.toString()) | 
					
						
							|  |  |  |             .toEqual(`**ERROR** ("\n222\n333\n[ERROR ->]E\n444\n555\n"): file://@123:456`); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-21 11:32:58 -08:00
										 |  |  |     describe('unicode characters', () => { | 
					
						
							|  |  |  |       it('should support unicode characters', () => { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |         expect(tokenizeAndHumanizeSourceSpans(`<p>İ</p>`)) | 
					
						
							|  |  |  |             .toEqual([ | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_START, '<p'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_OPEN_END, '>'], | 
					
						
							|  |  |  |               [HtmlTokenType.TEXT, 'İ'], | 
					
						
							|  |  |  |               [HtmlTokenType.TAG_CLOSE, '</p>'], | 
					
						
							|  |  |  |               [HtmlTokenType.EOF, ''] | 
					
						
							|  |  |  |             ]); | 
					
						
							| 
									
										
										
										
											2015-12-21 11:32:58 -08:00
										 |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function tokenizeWithoutErrors(input: string): HtmlToken[] { | 
					
						
							|  |  |  |   var tokenizeResult = tokenizeHtml(input, 'someUrl'); | 
					
						
							|  |  |  |   if (tokenizeResult.errors.length > 0) { | 
					
						
							|  |  |  |     var errorString = tokenizeResult.errors.join('\n'); | 
					
						
							|  |  |  |     throw new BaseException(`Unexpected parse errors:\n${errorString}`); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return tokenizeResult.tokens; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function tokenizeAndHumanizeParts(input: string): any[] { | 
					
						
							|  |  |  |   return tokenizeWithoutErrors(input).map(token => [<any>token.type].concat(token.parts)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function tokenizeAndHumanizeSourceSpans(input: string): any[] { | 
					
						
							|  |  |  |   return tokenizeWithoutErrors(input).map(token => [<any>token.type, token.sourceSpan.toString()]); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function humanizeLineColumn(location: ParseLocation): string { | 
					
						
							|  |  |  |   return `${location.line}:${location.col}`; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function tokenizeAndHumanizeLineColumn(input: string): any[] { | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |   return tokenizeWithoutErrors(input) | 
					
						
							|  |  |  |       .map(token => [<any>token.type, humanizeLineColumn(token.sourceSpan.start)]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function tokenizeAndHumanizeErrors(input: string): any[] { | 
					
						
							|  |  |  |   return tokenizeHtml(input, 'someUrl') | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |       .errors.map(tokenError => [ | 
					
						
							|  |  |  |         <any>tokenError.tokenType, | 
					
						
							|  |  |  |         tokenError.msg, | 
					
						
							|  |  |  |         humanizeLineColumn(tokenError.span.start) | 
					
						
							|  |  |  |       ]); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:34:21 -07:00
										 |  |  | } |