2016-06-23 09:47:54 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/ * *  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  @license 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-19 12:08:49 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  Copyright  Google  LLC  All  Rights  Reserved . 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-23 09:47:54 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Use  of  this  source  code  is  governed  by  an  MIT - style  license  that  can  be 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  found  in  the  LICENSE  file  at  https : //angular.io/license
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * / 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-08-01 12:19:09 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								import  *  as  html  from  '../../src/ml_parser/ast' ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  { HtmlParser ,  ParseTreeResult ,  TreeError }  from  '../../src/ml_parser/html_parser' ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  { TokenType }  from  '../../src/ml_parser/lexer' ;  
						 
					
						
							
								
									
										
										
										
											2016-07-21 11:41:25 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								import  { ParseError }  from  '../../src/parse_util' ;  
						 
					
						
							
								
									
										
										
										
											2016-06-09 14:53:03 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-07-21 13:56:58 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								import  { humanizeDom ,  humanizeDomSourceSpans ,  humanizeLineColumn }  from  './ast_spec_utils' ;  
						 
					
						
							
								
									
										
										
										
											2015-08-25 15:36:02 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-12-16 14:42:55 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2015-10-07 09:34:21 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								  describe ( 'HtmlParser' ,  ( )  = >  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-11-12 14:08:58 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    let  parser : HtmlParser ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-22 17:25:42 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-04-08 10:14:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    beforeEach ( ( )  = >  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      parser  =  new  HtmlParser ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-08-25 15:36:02 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-10-07 09:34:21 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    describe ( 'parse' ,  ( )  = >  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-09-11 13:35:46 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								      describe ( 'text nodes' ,  ( )  = >  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        it ( 'should parse root level text nodes' ,  ( )  = >  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-21 13:56:58 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          expect ( humanizeDom ( parser . parse ( 'a' ,  'TestComp' ) ) ) . toEqual ( [ [ html . Text ,  'a' ,  0 ] ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-09-11 13:35:46 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        it ( 'should parse text nodes inside regular elements' ,  ( )  = >  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          expect ( humanizeDom ( parser . parse ( '<div>a</div>' ,  'TestComp' ) ) ) . toEqual ( [ 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-21 13:56:58 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            [ html . Element ,  'div' ,  0 ] ,  [ html . Text ,  'a' ,  1 ] 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-09-11 13:35:46 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-08-25 15:36:02 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-01-09 13:16:46 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        it ( 'should parse text nodes inside <ng-template> elements' ,  ( )  = >  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( humanizeDom ( parser . parse ( '<ng-template>a</ng-template>' ,  'TestComp' ) ) ) . toEqual ( [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Element ,  'ng-template' ,  0 ] ,  [ html . Text ,  'a' ,  1 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-11-10 15:56:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        it ( 'should parse CDATA' ,  ( )  = >  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          expect ( humanizeDom ( parser . parse ( '<![CDATA[text]]>' ,  'TestComp' ) ) ) . toEqual ( [ 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-21 13:56:58 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            [ html . Text ,  'text' ,  0 ] 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-09-11 13:35:46 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												fix(compiler): normalize line endings in ICU expansions (#36741)
The html parser already normalizes line endings (converting `\r\n` to `\n`)
for most text in templates but it was missing the expressions of ICU expansions.
In ViewEngine backticked literal strings, used to define inline templates,
were already normalized by the TypeScript parser.
In Ivy we are parsing the raw text of the source file directly so the line
endings need to be manually normalized.
This change ensures that inline templates have the line endings of ICU
expression normalized correctly, which matches the ViewEngine.
In ViewEngine external templates, defined in HTML files, the behavior was
different, since TypeScript was not normalizing the line endings.
Specifically, ICU expansion "expressions" are not being normalized.
This is a problem because it means that i18n message ids can be different on
different machines that are setup with different line ending handling,
or if the developer moves a template from inline to external or vice versa.
The goal is always to normalize line endings, whether inline or external.
But this would be a breaking change since it would change i18n message ids
that have been previously computed. Therefore this commit aligns the ivy
template parsing to have the same "buggy" behavior for external templates.
There is now a compiler option `i18nNormalizeLineEndingsInICUs`, which
if set to `true` will ensure the correct non-buggy behavior. For the time
being this option defaults to `false` to ensure backward compatibility while
allowing opt-in to the desired behavior. This option's default will be
flipped in a future breaking change release.
Further, when this option is set to `false`, any ICU expression tokens,
which have not been normalized, are added to the `ParseResult` from the
`HtmlParser.parse()` method. In the future, this collection of tokens could
be used to diagnose and encourage developers to migrate their i18n message
ids. See FW-2106.
Closes #36725
PR Close #36741
											 
										 
										
											2020-04-26 18:15:43 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        it ( 'should normalize line endings within CDATA' ,  ( )  = >  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          const  parsed  =  parser . parse ( '<![CDATA[ line 1 \r\n line 2 ]]>' ,  'TestComp' ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( humanizeDom ( parsed ) ) . toEqual ( [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Text ,  ' line 1 \n line 2 ' ,  0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( parsed . errors ) . toEqual ( [ ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-08-25 15:36:02 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								      } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-09-11 13:35:46 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								      describe ( 'elements' ,  ( )  = >  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        it ( 'should parse root level elements' ,  ( )  = >  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          expect ( humanizeDom ( parser . parse ( '<div></div>' ,  'TestComp' ) ) ) . toEqual ( [ 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-21 13:56:58 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            [ html . Element ,  'div' ,  0 ] 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-09-11 13:35:46 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        it ( 'should parse elements inside of regular elements' ,  ( )  = >  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          expect ( humanizeDom ( parser . parse ( '<div><span></span></div>' ,  'TestComp' ) ) ) . toEqual ( [ 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-21 13:56:58 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            [ html . Element ,  'div' ,  0 ] ,  [ html . Element ,  'span' ,  1 ] 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-09-11 13:35:46 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-01-09 13:16:46 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        it ( 'should parse elements inside  <ng-template> elements' ,  ( )  = >  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( humanizeDom ( parser . parse ( '<ng-template><span></span></ng-template>' ,  'TestComp' ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              . toEqual ( [ [ html . Element ,  'ng-template' ,  0 ] ,  [ html . Element ,  'span' ,  1 ] ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-11-10 15:56:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        it ( 'should support void elements' ,  ( )  = >  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( humanizeDom ( parser . parse ( '<link rel="author license" href="/about">' ,  'TestComp' ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              . toEqual ( [ 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-21 13:56:58 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                [ html . Element ,  'link' ,  0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                [ html . Attribute ,  'rel' ,  'author license' ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                [ html . Attribute ,  'href' ,  '/about' ] , 
							 
						 
					
						
							
								
									
										
										
										
											2015-11-10 15:56:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								              ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-12-07 18:06:03 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        it ( 'should not error on void elements from HTML5 spec' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								           ( )  = >  {   // http://www.w3.org/TR/html-markup/syntax.html#syntax-elements without:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								             // <base> - it can be present in head only
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								             // <meta> - it can be present in head only
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								             // <command> - obsolete
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								             // <keygen> - obsolete
 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-08 10:14:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								             [ '<map><area></map>' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              '<div><br></div>' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              '<colgroup><col></colgroup>' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              '<div><embed></div>' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              '<div><hr></div>' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              '<div><img></div>' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              '<div><input></div>' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              '<object><param>/<object>' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              '<audio><source></audio>' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              '<audio><track></audio>' , 
							 
						 
					
						
							
								
									
										
										
										
											2015-12-07 18:06:03 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								              '<p><wbr></p>' , 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-08 10:14:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								             ] . forEach ( ( html )  = >  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								               expect ( parser . parse ( html ,  'TestComp' ) . errors ) . toEqual ( [ ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								             } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-12-07 18:06:03 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								           } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-12-01 13:01:05 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        it ( 'should close void elements on text nodes' ,  ( )  = >  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          expect ( humanizeDom ( parser . parse ( '<p>before<br>after</p>' ,  'TestComp' ) ) ) . toEqual ( [ 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-21 13:56:58 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            [ html . Element ,  'p' ,  0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Text ,  'before' ,  1 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Element ,  'br' ,  1 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Text ,  'after' ,  1 ] , 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-12-01 13:01:05 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-11-10 15:56:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        it ( 'should support optional end tags' ,  ( )  = >  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          expect ( humanizeDom ( parser . parse ( '<div><p>1<p>2</div>' ,  'TestComp' ) ) ) . toEqual ( [ 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-21 13:56:58 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            [ html . Element ,  'div' ,  0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Element ,  'p' ,  1 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Text ,  '1' ,  2 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Element ,  'p' ,  1 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Text ,  '2' ,  2 ] , 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-11-10 15:56:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        it ( 'should support nested elements' ,  ( )  = >  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( humanizeDom ( parser . parse ( '<ul><li><ul><li></li></ul></li></ul>' ,  'TestComp' ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              . toEqual ( [ 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-21 13:56:58 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                [ html . Element ,  'ul' ,  0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                [ html . Element ,  'li' ,  1 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                [ html . Element ,  'ul' ,  2 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                [ html . Element ,  'li' ,  3 ] , 
							 
						 
					
						
							
								
									
										
										
										
											2015-11-10 15:56:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								              ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-03-11 14:26:20 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        / * * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								         *  Certain  elements  ( like  < tr >  or  < col > )  require  parent  elements  of  a  certain  type  ( ex .  < tr > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								         *  can  only  be  inside  < tbody >  /  < thead > ) .  The  Angular  HTML  parser  doesn ' t  validate  those 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								         *  HTML  compliancy  rules  as  "problematic"  elements  can  be  projected  -  in  such  case  HTML  ( as 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								         *  written  in  an  Angular  template )  might  be  "invalid"  ( spec - wise )  but  the  resulting  DOM  will 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								         *  still  be  correct . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								         * / 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        it ( 'should not wraps elements in a required parent' ,  ( )  = >  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( humanizeDom ( parser . parse ( '<div><tr></tr></div>' ,  'TestComp' ) ) ) . toEqual ( [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Element ,  'div' ,  0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Element ,  'tr' ,  1 ] , 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-15 09:45:19 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-05-15 16:27:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        it ( 'should support explicit namespace' ,  ( )  = >  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          expect ( humanizeDom ( parser . parse ( '<myns:div></myns:div>' ,  'TestComp' ) ) ) . toEqual ( [ 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-21 13:56:58 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            [ html . Element ,  ':myns:div' ,  0 ] 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-11-10 15:56:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-05-15 16:27:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        it ( 'should support implicit namespace' ,  ( )  = >  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          expect ( humanizeDom ( parser . parse ( '<svg></svg>' ,  'TestComp' ) ) ) . toEqual ( [ 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-21 13:56:58 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            [ html . Element ,  ':svg:svg' ,  0 ] 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-11-10 15:56:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        it ( 'should propagate the namespace' ,  ( )  = >  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          expect ( humanizeDom ( parser . parse ( '<myns:div><p></p></myns:div>' ,  'TestComp' ) ) ) . toEqual ( [ 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-21 13:56:58 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            [ html . Element ,  ':myns:div' ,  0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Element ,  ':myns:p' ,  1 ] , 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-11-10 15:56:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-11-23 16:02:19 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        it ( 'should match closing tags case sensitive' ,  ( )  = >  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-11-12 14:08:58 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          const  errors  =  parser . parse ( '<DiV><P></p></dIv>' ,  'TestComp' ) . errors ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-11-23 16:02:19 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          expect ( errors . length ) . toEqual ( 2 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          expect ( humanizeErrors ( errors ) ) . toEqual ( [ 
							 
						 
					
						
							
								
									
										
										
										
											2017-03-11 00:05:17 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              'p' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              'Unexpected closing tag "p". It may happen when the tag has already been closed by another tag. For more info see https://www.w3.org/TR/html5/syntax.html#closing-elements-that-have-implied-end-tags' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              '0:8' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              'dIv' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              'Unexpected closing tag "dIv". It may happen when the tag has already been closed by another tag. For more info see https://www.w3.org/TR/html5/syntax.html#closing-elements-that-have-implied-end-tags' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              '0:12' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            ] , 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-09-11 13:35:46 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-12-03 16:10:20 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        it ( 'should support self closing void elements' ,  ( )  = >  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          expect ( humanizeDom ( parser . parse ( '<input />' ,  'TestComp' ) ) ) . toEqual ( [ 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-21 13:56:58 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            [ html . Element ,  'input' ,  0 ] 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-12-03 16:10:20 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        it ( 'should support self closing foreign elements' ,  ( )  = >  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          expect ( humanizeDom ( parser . parse ( '<math />' ,  'TestComp' ) ) ) . toEqual ( [ 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-21 13:56:58 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            [ html . Element ,  ':math:math' ,  0 ] 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-12-03 16:10:20 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 00:15:18 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        it ( 'should ignore LF immediately after textarea, pre and listing' ,  ( )  = >  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( humanizeDom ( parser . parse ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                     '<p>\n</p><textarea>\n</textarea><pre>\n\n</pre><listing>\n\n</listing>' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                     'TestComp' ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              . toEqual ( [ 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-21 13:56:58 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                [ html . Element ,  'p' ,  0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                [ html . Text ,  '\n' ,  1 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                [ html . Element ,  'textarea' ,  0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                [ html . Element ,  'pre' ,  0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                [ html . Text ,  '\n' ,  1 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                [ html . Element ,  'listing' ,  0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                [ html . Text ,  '\n' ,  1 ] , 
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 00:15:18 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								              ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												fix(compiler): normalize line endings in ICU expansions (#36741)
The html parser already normalizes line endings (converting `\r\n` to `\n`)
for most text in templates but it was missing the expressions of ICU expansions.
In ViewEngine backticked literal strings, used to define inline templates,
were already normalized by the TypeScript parser.
In Ivy we are parsing the raw text of the source file directly so the line
endings need to be manually normalized.
This change ensures that inline templates have the line endings of ICU
expression normalized correctly, which matches the ViewEngine.
In ViewEngine external templates, defined in HTML files, the behavior was
different, since TypeScript was not normalizing the line endings.
Specifically, ICU expansion "expressions" are not being normalized.
This is a problem because it means that i18n message ids can be different on
different machines that are setup with different line ending handling,
or if the developer moves a template from inline to external or vice versa.
The goal is always to normalize line endings, whether inline or external.
But this would be a breaking change since it would change i18n message ids
that have been previously computed. Therefore this commit aligns the ivy
template parsing to have the same "buggy" behavior for external templates.
There is now a compiler option `i18nNormalizeLineEndingsInICUs`, which
if set to `true` will ensure the correct non-buggy behavior. For the time
being this option defaults to `false` to ensure backward compatibility while
allowing opt-in to the desired behavior. This option's default will be
flipped in a future breaking change release.
Further, when this option is set to `false`, any ICU expression tokens,
which have not been normalized, are added to the `ParseResult` from the
`HtmlParser.parse()` method. In the future, this collection of tokens could
be used to diagnose and encourage developers to migrate their i18n message
ids. See FW-2106.
Closes #36725
PR Close #36741
											 
										 
										
											2020-04-26 18:15:43 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        it ( 'should normalize line endings in text' ,  ( )  = >  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          let  parsed : ParseTreeResult ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          parsed  =  parser . parse ( '<title> line 1 \r\n line 2 </title>' ,  'TestComp' ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( humanizeDom ( parsed ) ) . toEqual ( [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Element ,  'title' ,  0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Text ,  ' line 1 \n line 2 ' ,  1 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( parsed . errors ) . toEqual ( [ ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          parsed  =  parser . parse ( '<script> line 1 \r\n line 2 </script>' ,  'TestComp' ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( humanizeDom ( parsed ) ) . toEqual ( [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Element ,  'script' ,  0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Text ,  ' line 1 \n line 2 ' ,  1 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( parsed . errors ) . toEqual ( [ ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          parsed  =  parser . parse ( '<div> line 1 \r\n line 2 </div>' ,  'TestComp' ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( humanizeDom ( parsed ) ) . toEqual ( [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Element ,  'div' ,  0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Text ,  ' line 1 \n line 2 ' ,  1 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( parsed . errors ) . toEqual ( [ ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          parsed  =  parser . parse ( '<span> line 1 \r\n line 2 </span>' ,  'TestComp' ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( humanizeDom ( parsed ) ) . toEqual ( [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Element ,  'span' ,  0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Text ,  ' line 1 \n line 2 ' ,  1 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( parsed . errors ) . toEqual ( [ ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-08-25 15:36:02 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								      } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-09-11 13:35:46 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								      describe ( 'attributes' ,  ( )  = >  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-11-10 15:56:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        it ( 'should parse attributes on regular elements case sensitive' ,  ( )  = >  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          expect ( humanizeDom ( parser . parse ( '<div kEy="v" key2=v2></div>' ,  'TestComp' ) ) ) . toEqual ( [ 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-21 13:56:58 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            [ html . Element ,  'div' ,  0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Attribute ,  'kEy' ,  'v' ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Attribute ,  'key2' ,  'v2' ] , 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-09-11 13:35:46 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												fix(compiler): normalize line endings in ICU expansions (#36741)
The html parser already normalizes line endings (converting `\r\n` to `\n`)
for most text in templates but it was missing the expressions of ICU expansions.
In ViewEngine backticked literal strings, used to define inline templates,
were already normalized by the TypeScript parser.
In Ivy we are parsing the raw text of the source file directly so the line
endings need to be manually normalized.
This change ensures that inline templates have the line endings of ICU
expression normalized correctly, which matches the ViewEngine.
In ViewEngine external templates, defined in HTML files, the behavior was
different, since TypeScript was not normalizing the line endings.
Specifically, ICU expansion "expressions" are not being normalized.
This is a problem because it means that i18n message ids can be different on
different machines that are setup with different line ending handling,
or if the developer moves a template from inline to external or vice versa.
The goal is always to normalize line endings, whether inline or external.
But this would be a breaking change since it would change i18n message ids
that have been previously computed. Therefore this commit aligns the ivy
template parsing to have the same "buggy" behavior for external templates.
There is now a compiler option `i18nNormalizeLineEndingsInICUs`, which
if set to `true` will ensure the correct non-buggy behavior. For the time
being this option defaults to `false` to ensure backward compatibility while
allowing opt-in to the desired behavior. This option's default will be
flipped in a future breaking change release.
Further, when this option is set to `false`, any ICU expression tokens,
which have not been normalized, are added to the `ParseResult` from the
`HtmlParser.parse()` method. In the future, this collection of tokens could
be used to diagnose and encourage developers to migrate their i18n message
ids. See FW-2106.
Closes #36725
PR Close #36741
											 
										 
										
											2020-04-26 18:15:43 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        it ( 'should normalize line endings within attribute values' ,  ( )  = >  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          const  result  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              parser . parse ( '<div key="  \r\n line 1 \r\n   line 2  "></div>' ,  'TestComp' ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( humanizeDom ( result ) ) . toEqual ( [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Element ,  'div' ,  0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Attribute ,  'key' ,  '  \n line 1 \n   line 2  ' ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( result . errors ) . toEqual ( [ ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-10-07 09:34:21 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        it ( 'should parse attributes without values' ,  ( )  = >  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          expect ( humanizeDom ( parser . parse ( '<div k></div>' ,  'TestComp' ) ) ) . toEqual ( [ 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-21 13:56:58 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            [ html . Element ,  'div' ,  0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Attribute ,  'k' ,  '' ] , 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-10-07 09:34:21 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-11-06 11:31:03 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        it ( 'should parse attributes on svg elements case sensitive' ,  ( )  = >  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          expect ( humanizeDom ( parser . parse ( '<svg viewBox="0"></svg>' ,  'TestComp' ) ) ) . toEqual ( [ 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-21 13:56:58 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            [ html . Element ,  ':svg:svg' ,  0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Attribute ,  'viewBox' ,  '0' ] , 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-10-14 18:04:38 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-01-09 13:16:46 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        it ( 'should parse attributes on <ng-template> elements' ,  ( )  = >  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( humanizeDom ( parser . parse ( '<ng-template k="v"></ng-template>' ,  'TestComp' ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              . toEqual ( [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                [ html . Element ,  'ng-template' ,  0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                [ html . Attribute ,  'k' ,  'v' ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-09-11 13:35:46 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-08-25 15:36:02 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-04-12 11:46:39 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        it ( 'should support namespace' ,  ( )  = >  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          expect ( humanizeDom ( parser . parse ( '<svg:use xlink:href="Port" />' ,  'TestComp' ) ) ) . toEqual ( [ 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-21 13:56:58 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            [ html . Element ,  ':svg:use' ,  0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Attribute ,  ':xlink:href' ,  'Port' ] , 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-11-10 15:56:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      describe ( 'comments' ,  ( )  = >  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-03-06 20:21:20 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        it ( 'should preserve comments' ,  ( )  = >  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          expect ( humanizeDom ( parser . parse ( '<!-- comment --><div></div>' ,  'TestComp' ) ) ) . toEqual ( [ 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-21 13:56:58 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            [ html . Comment ,  'comment' ,  0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Element ,  'div' ,  0 ] , 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-11-10 15:56:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												fix(compiler): normalize line endings in ICU expansions (#36741)
The html parser already normalizes line endings (converting `\r\n` to `\n`)
for most text in templates but it was missing the expressions of ICU expansions.
In ViewEngine backticked literal strings, used to define inline templates,
were already normalized by the TypeScript parser.
In Ivy we are parsing the raw text of the source file directly so the line
endings need to be manually normalized.
This change ensures that inline templates have the line endings of ICU
expression normalized correctly, which matches the ViewEngine.
In ViewEngine external templates, defined in HTML files, the behavior was
different, since TypeScript was not normalizing the line endings.
Specifically, ICU expansion "expressions" are not being normalized.
This is a problem because it means that i18n message ids can be different on
different machines that are setup with different line ending handling,
or if the developer moves a template from inline to external or vice versa.
The goal is always to normalize line endings, whether inline or external.
But this would be a breaking change since it would change i18n message ids
that have been previously computed. Therefore this commit aligns the ivy
template parsing to have the same "buggy" behavior for external templates.
There is now a compiler option `i18nNormalizeLineEndingsInICUs`, which
if set to `true` will ensure the correct non-buggy behavior. For the time
being this option defaults to `false` to ensure backward compatibility while
allowing opt-in to the desired behavior. This option's default will be
flipped in a future breaking change release.
Further, when this option is set to `false`, any ICU expression tokens,
which have not been normalized, are added to the `ParseResult` from the
`HtmlParser.parse()` method. In the future, this collection of tokens could
be used to diagnose and encourage developers to migrate their i18n message
ids. See FW-2106.
Closes #36725
PR Close #36741
											 
										 
										
											2020-04-26 18:15:43 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        it ( 'should normalize line endings within comments' ,  ( )  = >  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( humanizeDom ( parser . parse ( '<!-- line 1 \r\n line 2 -->' ,  'TestComp' ) ) ) . toEqual ( [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Comment ,  'line 1 \n line 2' ,  0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-11-10 15:56:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								      } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								      describe ( 'expansion forms' ,  ( )  = >  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        it ( 'should parse out expansion forms' ,  ( )  = >  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-11-12 14:08:58 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          const  parsed  =  parser . parse ( 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								              ` <div>before{messages.length, plural, =0 {You have <b>no</b> messages} =1 {One {{message}}}}after</div> ` , 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-08 22:10:19 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								              'TestComp' ,  { tokenizeExpansionForms : true } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-04-12 11:46:39 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-06-09 14:53:03 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          expect ( humanizeDom ( parsed ) ) . toEqual ( [ 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-21 13:56:58 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            [ html . Element ,  'div' ,  0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Text ,  'before' ,  1 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Expansion ,  'messages.length' ,  'plural' ,  1 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . ExpansionCase ,  '=0' ,  2 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . ExpansionCase ,  '=1' ,  2 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Text ,  'after' ,  1 ] , 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-09 14:53:03 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-11-12 14:08:58 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          const  cases  =  ( < any > parsed . rootNodes [ 0 ] ) . children [ 1 ] . cases ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-04-12 11:46:39 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-07-21 13:56:58 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          expect ( humanizeDom ( new  ParseTreeResult ( cases [ 0 ] . expression ,  [ ] ) ) ) . toEqual ( [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Text ,  'You have ' ,  0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Element ,  'b' ,  0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Text ,  'no' ,  1 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Text ,  ' messages' ,  0 ] , 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-04-12 11:46:39 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-04-08 10:14:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          expect ( humanizeDom ( new  ParseTreeResult ( cases [ 1 ] . expression ,  [ ] ) ) ) . toEqual ( [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Text ,  'One {{message}}' ,  0 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-04-12 11:46:39 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												fix(compiler): normalize line endings in ICU expansions (#36741)
The html parser already normalizes line endings (converting `\r\n` to `\n`)
for most text in templates but it was missing the expressions of ICU expansions.
In ViewEngine backticked literal strings, used to define inline templates,
were already normalized by the TypeScript parser.
In Ivy we are parsing the raw text of the source file directly so the line
endings need to be manually normalized.
This change ensures that inline templates have the line endings of ICU
expression normalized correctly, which matches the ViewEngine.
In ViewEngine external templates, defined in HTML files, the behavior was
different, since TypeScript was not normalizing the line endings.
Specifically, ICU expansion "expressions" are not being normalized.
This is a problem because it means that i18n message ids can be different on
different machines that are setup with different line ending handling,
or if the developer moves a template from inline to external or vice versa.
The goal is always to normalize line endings, whether inline or external.
But this would be a breaking change since it would change i18n message ids
that have been previously computed. Therefore this commit aligns the ivy
template parsing to have the same "buggy" behavior for external templates.
There is now a compiler option `i18nNormalizeLineEndingsInICUs`, which
if set to `true` will ensure the correct non-buggy behavior. For the time
being this option defaults to `false` to ensure backward compatibility while
allowing opt-in to the desired behavior. This option's default will be
flipped in a future breaking change release.
Further, when this option is set to `false`, any ICU expression tokens,
which have not been normalized, are added to the `ParseResult` from the
`HtmlParser.parse()` method. In the future, this collection of tokens could
be used to diagnose and encourage developers to migrate their i18n message
ids. See FW-2106.
Closes #36725
PR Close #36741
											 
										 
										
											2020-04-26 18:15:43 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        it ( 'should normalize line-endings in expansion forms in inline templates' ,  ( )  = >  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          const  parsed  =  parser . parse ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              ` <div> \ r \ n `  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                  `   { \ r \ n `  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                  `     messages.length, \ r \ n `  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                  `     plural, \ r \ n `  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                  `     =0 {You have  \ r \ nno \ r \ n messages} \ r \ n `  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                  `     =1 {One {{message}}}} \ r \ n `  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                  ` </div> ` , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              'TestComp' ,  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                tokenizeExpansionForms : true , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                escapedString : true , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( humanizeDom ( parsed ) ) . toEqual ( [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Element ,  'div' ,  0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Text ,  '\n  ' ,  1 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Expansion ,  '\n    messages.length' ,  'plural' ,  1 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . ExpansionCase ,  '=0' ,  2 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . ExpansionCase ,  '=1' ,  2 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Text ,  '\n' ,  1 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          const  cases  =  ( < any > parsed . rootNodes [ 0 ] ) . children [ 1 ] . cases ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( humanizeDom ( new  ParseTreeResult ( cases [ 0 ] . expression ,  [ ] ) ) ) . toEqual ( [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Text ,  'You have \nno\n messages' ,  0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( humanizeDom ( new  ParseTreeResult ( cases [ 1 ] . expression ,  [ ] ) ) ) . toEqual ( [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Text ,  'One {{message}}' ,  0 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( parsed . errors ) . toEqual ( [ ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        it ( 'should normalize line-endings in expansion forms in external templates if `i18nNormalizeLineEndingsInICUs` is true' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								           ( )  = >  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								             const  parsed  =  parser . parse ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                 ` <div> \ r \ n `  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                     `   { \ r \ n `  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                     `     messages.length, \ r \ n `  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                     `     plural, \ r \ n `  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                     `     =0 {You have  \ r \ nno \ r \ n messages} \ r \ n `  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                     `     =1 {One {{message}}}} \ r \ n `  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                     ` </div> ` , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                 'TestComp' ,  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                   tokenizeExpansionForms : true , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                   escapedString : false , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                   i18nNormalizeLineEndingsInICUs : true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                 } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								             expect ( humanizeDom ( parsed ) ) . toEqual ( [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								               [ html . Element ,  'div' ,  0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								               [ html . Text ,  '\n  ' ,  1 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								               [ html . Expansion ,  '\n    messages.length' ,  'plural' ,  1 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								               [ html . ExpansionCase ,  '=0' ,  2 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								               [ html . ExpansionCase ,  '=1' ,  2 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								               [ html . Text ,  '\n' ,  1 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								             ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								             const  cases  =  ( < any > parsed . rootNodes [ 0 ] ) . children [ 1 ] . cases ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								             expect ( humanizeDom ( new  ParseTreeResult ( cases [ 0 ] . expression ,  [ ] ) ) ) . toEqual ( [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								               [ html . Text ,  'You have \nno\n messages' ,  0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								             ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								             expect ( humanizeDom ( new  ParseTreeResult ( cases [ 1 ] . expression ,  [ ] ) ) ) . toEqual ( [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								               [ html . Text ,  'One {{message}}' ,  0 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								             ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								             expect ( parsed . errors ) . toEqual ( [ ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								           } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        it ( 'should not normalize line-endings in ICU expressions in external templates when `i18nNormalizeLineEndingsInICUs` is not set' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								           ( )  = >  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								             const  parsed  =  parser . parse ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                 ` <div> \ r \ n `  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                     `   { \ r \ n `  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                     `     messages.length, \ r \ n `  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                     `     plural, \ r \ n `  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                     `     =0 {You have  \ r \ nno \ r \ n messages} \ r \ n `  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                     `     =1 {One {{message}}}} \ r \ n `  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                     ` </div> ` , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                 'TestComp' ,  { tokenizeExpansionForms : true ,  escapedString : false } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								             expect ( humanizeDom ( parsed ) ) . toEqual ( [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								               [ html . Element ,  'div' ,  0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								               [ html . Text ,  '\n  ' ,  1 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								               [ html . Expansion ,  '\r\n    messages.length' ,  'plural' ,  1 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								               [ html . ExpansionCase ,  '=0' ,  2 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								               [ html . ExpansionCase ,  '=1' ,  2 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								               [ html . Text ,  '\n' ,  1 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								             ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								             const  cases  =  ( < any > parsed . rootNodes [ 0 ] ) . children [ 1 ] . cases ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								             expect ( humanizeDom ( new  ParseTreeResult ( cases [ 0 ] . expression ,  [ ] ) ) ) . toEqual ( [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								               [ html . Text ,  'You have \nno\n messages' ,  0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								             ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								             expect ( humanizeDom ( new  ParseTreeResult ( cases [ 1 ] . expression ,  [ ] ) ) ) . toEqual ( [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								               [ html . Text ,  'One {{message}}' ,  0 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								             ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								             expect ( parsed . errors ) . toEqual ( [ ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								           } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-12-16 15:33:16 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        it ( 'should parse out expansion forms' ,  ( )  = >  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-08 22:10:19 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          const  parsed  =  parser . parse ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              ` <div><span>{a, plural, =0 {b}}</span></div> ` ,  'TestComp' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              { tokenizeExpansionForms : true } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-16 15:33:16 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( humanizeDom ( parsed ) ) . toEqual ( [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Element ,  'div' ,  0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Element ,  'span' ,  1 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Expansion ,  'a' ,  'plural' ,  2 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . ExpansionCase ,  '=0' ,  3 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        it ( 'should parse out nested expansion forms' ,  ( )  = >  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-11-12 14:08:58 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          const  parsed  =  parser . parse ( 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-08 22:10:19 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								              ` {messages.length, plural, =0 { {p.gender, select, male {m}} }} ` ,  'TestComp' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              { tokenizeExpansionForms : true } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-09 14:53:03 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          expect ( humanizeDom ( parsed ) ) . toEqual ( [ 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-21 13:56:58 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            [ html . Expansion ,  'messages.length' ,  'plural' ,  0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . ExpansionCase ,  '=0' ,  1 ] , 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-09 14:53:03 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-04-13 16:01:25 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-11-12 14:08:58 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          const  firstCase  =  ( < any > parsed . rootNodes [ 0 ] ) . cases [ 0 ] ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-04-13 16:01:25 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-07-21 13:56:58 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          expect ( humanizeDom ( new  ParseTreeResult ( firstCase . expression ,  [ ] ) ) ) . toEqual ( [ 
							 
						 
					
						
							
								
									
										
										
										
											2016-11-04 15:10:19 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            [ html . Expansion ,  'p.gender' ,  'select' ,  0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . ExpansionCase ,  'male' ,  1 ] , 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-21 13:56:58 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            [ html . Text ,  ' ' ,  0 ] , 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-09 14:53:03 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-04-13 16:01:25 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												fix(compiler): normalize line endings in ICU expansions (#36741)
The html parser already normalizes line endings (converting `\r\n` to `\n`)
for most text in templates but it was missing the expressions of ICU expansions.
In ViewEngine backticked literal strings, used to define inline templates,
were already normalized by the TypeScript parser.
In Ivy we are parsing the raw text of the source file directly so the line
endings need to be manually normalized.
This change ensures that inline templates have the line endings of ICU
expression normalized correctly, which matches the ViewEngine.
In ViewEngine external templates, defined in HTML files, the behavior was
different, since TypeScript was not normalizing the line endings.
Specifically, ICU expansion "expressions" are not being normalized.
This is a problem because it means that i18n message ids can be different on
different machines that are setup with different line ending handling,
or if the developer moves a template from inline to external or vice versa.
The goal is always to normalize line endings, whether inline or external.
But this would be a breaking change since it would change i18n message ids
that have been previously computed. Therefore this commit aligns the ivy
template parsing to have the same "buggy" behavior for external templates.
There is now a compiler option `i18nNormalizeLineEndingsInICUs`, which
if set to `true` will ensure the correct non-buggy behavior. For the time
being this option defaults to `false` to ensure backward compatibility while
allowing opt-in to the desired behavior. This option's default will be
flipped in a future breaking change release.
Further, when this option is set to `false`, any ICU expression tokens,
which have not been normalized, are added to the `ParseResult` from the
`HtmlParser.parse()` method. In the future, this collection of tokens could
be used to diagnose and encourage developers to migrate their i18n message
ids. See FW-2106.
Closes #36725
PR Close #36741
											 
										 
										
											2020-04-26 18:15:43 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        it ( 'should normalize line endings in nested expansion forms for inline templates' ,  ( )  = >  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          const  parsed  =  parser . parse ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              ` { \ r \ n `  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                  `   messages.length, plural, \ r \ n `  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                  `   =0 { zero  \ r \ n `  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                  `        { \ r \ n `  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                  `          p.gender, select, \ r \ n `  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                  `          male {m} \ r \ n `  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                  `        } \ r \ n `  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                  `      } \ r \ n `  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                  ` } ` , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              'TestComp' ,  { tokenizeExpansionForms : true ,  escapedString : true } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( humanizeDom ( parsed ) ) . toEqual ( [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Expansion ,  '\n  messages.length' ,  'plural' ,  0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . ExpansionCase ,  '=0' ,  1 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          const  expansion  =  parsed . rootNodes [ 0 ]  as  html . Expansion ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( humanizeDom ( new  ParseTreeResult ( expansion . cases [ 0 ] . expression ,  [ ] ) ) ) . toEqual ( [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Text ,  'zero \n       ' ,  0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Expansion ,  '\n         p.gender' ,  'select' ,  0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . ExpansionCase ,  'male' ,  1 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Text ,  '\n     ' ,  0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( parsed . errors ) . toEqual ( [ ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        it ( 'should not normalize line endings in nested expansion forms for external templates, when `i18nNormalizeLineEndingsInICUs` is not set' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								           ( )  = >  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								             const  parsed  =  parser . parse ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                 ` { \ r \ n `  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                     `   messages.length, plural, \ r \ n `  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                     `   =0 { zero  \ r \ n `  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                     `        { \ r \ n `  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                     `          p.gender, select, \ r \ n `  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                     `          male {m} \ r \ n `  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                     `        } \ r \ n `  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                     `      } \ r \ n `  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                     ` } ` , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                 'TestComp' ,  { tokenizeExpansionForms : true } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								             expect ( humanizeDom ( parsed ) ) . toEqual ( [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								               [ html . Expansion ,  '\r\n  messages.length' ,  'plural' ,  0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								               [ html . ExpansionCase ,  '=0' ,  1 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								             ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								             const  expansion  =  parsed . rootNodes [ 0 ]  as  html . Expansion ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								             expect ( humanizeDom ( new  ParseTreeResult ( expansion . cases [ 0 ] . expression ,  [ ] ) ) ) . toEqual ( [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								               [ html . Text ,  'zero \n       ' ,  0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								               [ html . Expansion ,  '\r\n         p.gender' ,  'select' ,  0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								               [ html . ExpansionCase ,  'male' ,  1 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								               [ html . Text ,  '\n     ' ,  0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								             ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								             expect ( parsed . errors ) . toEqual ( [ ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								           } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        it ( 'should error when expansion form is not closed' ,  ( )  = >  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-08 22:10:19 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          const  p  =  parser . parse ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              ` {messages.length, plural, =0 {one} ` ,  'TestComp' ,  { tokenizeExpansionForms : true } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          expect ( humanizeErrors ( p . errors ) ) . toEqual ( [ 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-21 13:56:58 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            [ null ,  'Invalid ICU message. Missing \'}\'.' ,  '0:34' ] 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-04-12 11:46:39 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-07-13 13:55:15 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        it ( 'should support ICU expressions with cases that contain numbers' ,  ( )  = >  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-08 22:10:19 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          const  p  =  parser . parse ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              ` {sex, select, male {m} female {f} 0 {other}} ` ,  'TestComp' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              { tokenizeExpansionForms : true } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-07-13 13:55:15 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          expect ( p . errors . length ) . toEqual ( 0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-03-18 07:39:48 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        it ( ` should support ICU expressions with cases that contain any character except '}' ` , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								           ( )  = >  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								             const  p  =  parser . parse ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                 ` {a, select, b {foo} % bar {% bar}} ` ,  'TestComp' ,  { tokenizeExpansionForms : true } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								             expect ( p . errors . length ) . toEqual ( 0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								           } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        it ( 'should error when expansion case is not properly closed' ,  ( )  = >  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          const  p  =  parser . parse ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              ` {a, select, b {foo} % { bar {% bar}} ` ,  'TestComp' ,  { tokenizeExpansionForms : true } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( humanizeErrors ( p . errors ) ) . toEqual ( [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              6 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              'Unexpected character "EOF" (Do you have an unescaped "{" in your template? Use "{{ \'{\' }}") to escape it.)' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              '0:36' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ null ,  'Invalid ICU message. Missing \'}\'.' ,  '0:22' ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        it ( 'should error when expansion case is not closed' ,  ( )  = >  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-08 22:10:19 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          const  p  =  parser . parse ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              ` {messages.length, plural, =0 {one ` ,  'TestComp' ,  { tokenizeExpansionForms : true } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          expect ( humanizeErrors ( p . errors ) ) . toEqual ( [ 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-21 13:56:58 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            [ null ,  'Invalid ICU message. Missing \'}\'.' ,  '0:29' ] 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-04-12 11:46:39 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        it ( 'should error when invalid html in the case' ,  ( )  = >  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-08 22:10:19 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          const  p  =  parser . parse ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              ` {messages.length, plural, =0 {<b/>} ` ,  'TestComp' ,  { tokenizeExpansionForms : true } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          expect ( humanizeErrors ( p . errors ) ) . toEqual ( [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ 'b' ,  'Only void and foreign elements can be self closed "b"' ,  '0:30' ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-04-12 11:46:39 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-11-10 15:56:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								      describe ( 'source spans' ,  ( )  = >  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        it ( 'should store the location' ,  ( )  = >  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( humanizeDomSourceSpans ( parser . parse ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                     '<div [prop]="v1" (e)="do()" attr="v2" noValue>\na\n</div>' ,  'TestComp' ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              . toEqual ( [ 
							 
						 
					
						
							
								
									
										
											 
										
											
												fix(compiler): properly associate source spans for implicitly closed elements (#38126)
HTML is very lenient when it comes to closing elements, so Angular's parser has
rules that specify which elements are implicitly closed when closing a tag.
The parser keeps track of the nesting of tag names using a stack and parsing
a closing tag will pop as many elements off the stack as possible, provided
that the elements can be implicitly closed.
For example, consider the following templates:
- `<div><br></div>`, the `<br>` is implicitly closed when parsing `</div>`,
  because `<br>` is a void element.
- `<div><p></div>`, the `<p>` is implicitly closed when parsing `</div>`,
  as `<p>` is allowed to be closed by the closing of its parent element.
- `<ul><li>A <li>B</ul>`, the first `<li>` is implicitly closed when parsing
  the second `<li>`, whereas the second `<li>` would be implicitly closed when
  parsing the `</ul>`.
In all the cases above the parsed structure would be correct, however the source
span of the closing `</div>` would incorrectly be assigned to the element that
is implicitly closed. The problem was that closing an element would associate
the source span with the element at the top of the stack, however this may not
be the element that is actually being closed if some elements would be
implicitly closed.
This commit fixes the issue by assigning the end source span with the element
on the stack that is actually being closed. Any implicitly closed elements that
are popped off the stack will not be assigned an end source span, as the
implicit closing implies that no ending element is present.
Note that there is a difference between self-closed elements such as `<input/>`
and implicitly closed elements such as `<input>`. The former does have an end
source span (identical to its start source span) whereas the latter does not.
Fixes #36118
Resolves FW-2004
PR Close #38126
											 
										 
										
											2020-07-18 00:05:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                  html . Element ,  'div' ,  0 ,  '<div [prop]="v1" (e)="do()" attr="v2" noValue>' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                  '<div [prop]="v1" (e)="do()" attr="v2" noValue>' ,  '</div>' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                ] , 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-21 13:56:58 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                [ html . Attribute ,  '[prop]' ,  'v1' ,  '[prop]="v1"' ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                [ html . Attribute ,  '(e)' ,  'do()' ,  '(e)="do()"' ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                [ html . Attribute ,  'attr' ,  'v2' ,  'attr="v2"' ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                [ html . Attribute ,  'noValue' ,  '' ,  'noValue' ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                [ html . Text ,  '\na\n' ,  1 ,  '\na\n' ] , 
							 
						 
					
						
							
								
									
										
										
										
											2015-11-10 15:56:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								              ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-03-23 13:43:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        it ( 'should set the start and end source spans' ,  ( )  = >  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-11-12 14:08:58 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          const  node  =  < html.Element > parser . parse ( '<div>a</div>' ,  'TestComp' ) . rootNodes [ 0 ] ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-03-23 13:43:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-04-08 10:14:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          expect ( node . startSourceSpan ! . start . offset ) . toEqual ( 0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( node . startSourceSpan ! . end . offset ) . toEqual ( 5 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-03-23 13:43:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-04-08 10:14:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          expect ( node . endSourceSpan ! . start . offset ) . toEqual ( 6 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( node . endSourceSpan ! . end . offset ) . toEqual ( 12 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-03-23 13:43:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-21 13:56:58 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												fix(compiler): properly associate source spans for implicitly closed elements (#38126)
HTML is very lenient when it comes to closing elements, so Angular's parser has
rules that specify which elements are implicitly closed when closing a tag.
The parser keeps track of the nesting of tag names using a stack and parsing
a closing tag will pop as many elements off the stack as possible, provided
that the elements can be implicitly closed.
For example, consider the following templates:
- `<div><br></div>`, the `<br>` is implicitly closed when parsing `</div>`,
  because `<br>` is a void element.
- `<div><p></div>`, the `<p>` is implicitly closed when parsing `</div>`,
  as `<p>` is allowed to be closed by the closing of its parent element.
- `<ul><li>A <li>B</ul>`, the first `<li>` is implicitly closed when parsing
  the second `<li>`, whereas the second `<li>` would be implicitly closed when
  parsing the `</ul>`.
In all the cases above the parsed structure would be correct, however the source
span of the closing `</div>` would incorrectly be assigned to the element that
is implicitly closed. The problem was that closing an element would associate
the source span with the element at the top of the stack, however this may not
be the element that is actually being closed if some elements would be
implicitly closed.
This commit fixes the issue by assigning the end source span with the element
on the stack that is actually being closed. Any implicitly closed elements that
are popped off the stack will not be assigned an end source span, as the
implicit closing implies that no ending element is present.
Note that there is a difference between self-closed elements such as `<input/>`
and implicitly closed elements such as `<input>`. The former does have an end
source span (identical to its start source span) whereas the latter does not.
Fixes #36118
Resolves FW-2004
PR Close #38126
											 
										 
										
											2020-07-18 00:05:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        it ( 'should not set the end source span for void elements' ,  ( )  = >  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( humanizeDomSourceSpans ( parser . parse ( '<div><br></div>' ,  'TestComp' ) ) ) . toEqual ( [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Element ,  'div' ,  0 ,  '<div>' ,  '<div>' ,  '</div>' ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Element ,  'br' ,  1 ,  '<br>' ,  '<br>' ,  null ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        it ( 'should not set the end source span for multiple void elements' ,  ( )  = >  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( humanizeDomSourceSpans ( parser . parse ( '<div><br><hr></div>' ,  'TestComp' ) ) ) . toEqual ( [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Element ,  'div' ,  0 ,  '<div>' ,  '<div>' ,  '</div>' ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Element ,  'br' ,  1 ,  '<br>' ,  '<br>' ,  null ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Element ,  'hr' ,  1 ,  '<hr>' ,  '<hr>' ,  null ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        it ( 'should not set the end source span for standalone void elements' ,  ( )  = >  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( humanizeDomSourceSpans ( parser . parse ( '<br>' ,  'TestComp' ) ) ) . toEqual ( [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Element ,  'br' ,  0 ,  '<br>' ,  '<br>' ,  null ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        it ( 'should set the end source span for standalone self-closing elements' ,  ( )  = >  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( humanizeDomSourceSpans ( parser . parse ( '<br/>' ,  'TestComp' ) ) ) . toEqual ( [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Element ,  'br' ,  0 ,  '<br/>' ,  '<br/>' ,  '<br/>' ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        it ( 'should set the end source span for self-closing elements' ,  ( )  = >  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( humanizeDomSourceSpans ( parser . parse ( '<div><br/></div>' ,  'TestComp' ) ) ) . toEqual ( [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Element ,  'div' ,  0 ,  '<div>' ,  '<div>' ,  '</div>' ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Element ,  'br' ,  1 ,  '<br/>' ,  '<br/>' ,  '<br/>' ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        it ( 'should not set the end source span for elements that are implicitly closed' ,  ( )  = >  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( humanizeDomSourceSpans ( parser . parse ( '<div><p></div>' ,  'TestComp' ) ) ) . toEqual ( [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Element ,  'div' ,  0 ,  '<div>' ,  '<div>' ,  '</div>' ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ html . Element ,  'p' ,  1 ,  '<p>' ,  '<p>' ,  null ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( humanizeDomSourceSpans ( parser . parse ( '<div><li>A<li>B</div>' ,  'TestComp' ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              . toEqual ( [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                [ html . Element ,  'div' ,  0 ,  '<div>' ,  '<div>' ,  '</div>' ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                [ html . Element ,  'li' ,  1 ,  '<li>' ,  '<li>' ,  null ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                [ html . Text ,  'A' ,  2 ,  'A' ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                [ html . Element ,  'li' ,  1 ,  '<li>' ,  '<li>' ,  null ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                [ html . Text ,  'B' ,  2 ,  'B' ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-07-21 13:56:58 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        it ( 'should support expansion form' ,  ( )  = >  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-08 22:10:19 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          expect ( humanizeDomSourceSpans ( parser . parse ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                     '<div>{count, plural, =0 {msg}}</div>' ,  'TestComp' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                     { tokenizeExpansionForms : true } ) ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-21 13:56:58 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								              . toEqual ( [ 
							 
						 
					
						
							
								
									
										
											 
										
											
												fix(compiler): properly associate source spans for implicitly closed elements (#38126)
HTML is very lenient when it comes to closing elements, so Angular's parser has
rules that specify which elements are implicitly closed when closing a tag.
The parser keeps track of the nesting of tag names using a stack and parsing
a closing tag will pop as many elements off the stack as possible, provided
that the elements can be implicitly closed.
For example, consider the following templates:
- `<div><br></div>`, the `<br>` is implicitly closed when parsing `</div>`,
  because `<br>` is a void element.
- `<div><p></div>`, the `<p>` is implicitly closed when parsing `</div>`,
  as `<p>` is allowed to be closed by the closing of its parent element.
- `<ul><li>A <li>B</ul>`, the first `<li>` is implicitly closed when parsing
  the second `<li>`, whereas the second `<li>` would be implicitly closed when
  parsing the `</ul>`.
In all the cases above the parsed structure would be correct, however the source
span of the closing `</div>` would incorrectly be assigned to the element that
is implicitly closed. The problem was that closing an element would associate
the source span with the element at the top of the stack, however this may not
be the element that is actually being closed if some elements would be
implicitly closed.
This commit fixes the issue by assigning the end source span with the element
on the stack that is actually being closed. Any implicitly closed elements that
are popped off the stack will not be assigned an end source span, as the
implicit closing implies that no ending element is present.
Note that there is a difference between self-closed elements such as `<input/>`
and implicitly closed elements such as `<input>`. The former does have an end
source span (identical to its start source span) whereas the latter does not.
Fixes #36118
Resolves FW-2004
PR Close #38126
											 
										 
										
											2020-07-18 00:05:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                [ html . Element ,  'div' ,  0 ,  '<div>' ,  '<div>' ,  '</div>' ] , 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-21 13:56:58 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                [ html . Expansion ,  'count' ,  'plural' ,  1 ,  '{count, plural, =0 {msg}}' ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                [ html . ExpansionCase ,  '=0' ,  2 ,  '=0 {msg}' ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-07 13:53:29 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        it ( 'should not report a value span for an attribute without a value' ,  ( )  = >  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          const  ast  =  parser . parse ( '<div bar></div>' ,  'TestComp' ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( ( ast . rootNodes [ 0 ]  as  html . Element ) . attrs [ 0 ] . valueSpan ) . toBeUndefined ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-07-07 16:55:17 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        it ( 'should report a value span for an attribute with a value' ,  ( )  = >  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-07 13:53:29 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          const  ast  =  parser . parse ( '<div bar="12"></div>' ,  'TestComp' ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          const  attr  =  ( ast . rootNodes [ 0 ]  as  html . Element ) . attrs [ 0 ] ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-08 10:14:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          expect ( attr . valueSpan ! . start . offset ) . toEqual ( 10 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( attr . valueSpan ! . end . offset ) . toEqual ( 12 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-08 22:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        it ( 'should report a value span for an unquoted attribute value' ,  ( )  = >  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          const  ast  =  parser . parse ( '<div bar=12></div>' ,  'TestComp' ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          const  attr  =  ( ast . rootNodes [ 0 ]  as  html . Element ) . attrs [ 0 ] ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-08 10:14:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          expect ( attr . valueSpan ! . start . offset ) . toEqual ( 9 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( attr . valueSpan ! . end . offset ) . toEqual ( 11 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-07 13:53:29 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-11-10 15:56:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								      } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-10 09:13:50 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								      describe ( 'visitor' ,  ( )  = >  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        it ( 'should visit text nodes' ,  ( )  = >  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          const  result  =  humanizeDom ( parser . parse ( 'text' ,  'TestComp' ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( result ) . toEqual ( [ [ html . Text ,  'text' ,  0 ] ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        it ( 'should visit element nodes' ,  ( )  = >  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          const  result  =  humanizeDom ( parser . parse ( '<div></div>' ,  'TestComp' ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( result ) . toEqual ( [ [ html . Element ,  'div' ,  0 ] ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        it ( 'should visit attribute nodes' ,  ( )  = >  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          const  result  =  humanizeDom ( parser . parse ( '<div id="foo"></div>' ,  'TestComp' ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( result ) . toContain ( [ html . Attribute ,  'id' ,  'foo' ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        it ( 'should visit all nodes' ,  ( )  = >  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          const  result  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              parser . parse ( '<div id="foo"><span id="bar">a</span><span>b</span></div>' ,  'TestComp' ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          const  accumulator : html.Node [ ]  =  [ ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          const  visitor  =  new  class  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-08 10:14:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            visit ( node : html.Node ,  context : any )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              accumulator . push ( node ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-10 09:13:50 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            visitElement ( element : html.Element ,  context : any ) :  any  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              html . visitAll ( this ,  element . attrs ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              html . visitAll ( this ,  element . children ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            visitAttribute ( attribute : html.Attribute ,  context : any ) :  any  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            visitText ( text : html.Text ,  context : any ) :  any  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            visitComment ( comment : html.Comment ,  context : any ) :  any  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            visitExpansion ( expansion : html.Expansion ,  context : any ) :  any  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              html . visitAll ( this ,  expansion . cases ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            visitExpansionCase ( expansionCase : html.ExpansionCase ,  context : any ) :  any  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          html . visitAll ( visitor ,  result . rootNodes ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( accumulator . map ( n  = >  n . constructor ) ) . toEqual ( [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            html . Element ,  html . Attribute ,  html . Element ,  html . Attribute ,  html . Text ,  html . Element , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            html . Text 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        it ( 'should skip typed visit if visit() returns a truthy value' ,  ( )  = >  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          const  visitor  =  new  class  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-08 10:14:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            visit ( node : html.Node ,  context : any )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              return  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            visitElement ( element : html.Element ,  context : any ) :  any  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              throw  Error ( 'Unexpected' ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-10 09:13:50 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            visitAttribute ( attribute : html.Attribute ,  context : any ) :  any  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              throw  Error ( 'Unexpected' ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-08 10:14:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            visitText ( text : html.Text ,  context : any ) :  any  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              throw  Error ( 'Unexpected' ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            visitComment ( comment : html.Comment ,  context : any ) :  any  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              throw  Error ( 'Unexpected' ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-10 09:13:50 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            visitExpansion ( expansion : html.Expansion ,  context : any ) :  any  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              throw  Error ( 'Unexpected' ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            visitExpansionCase ( expansionCase : html.ExpansionCase ,  context : any ) :  any  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              throw  Error ( 'Unexpected' ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          const  result  =  parser . parse ( '<div id="foo"></div><div id="bar"></div>' ,  'TestComp' ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          const  traversal  =  html . visitAll ( visitor ,  result . rootNodes ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          expect ( traversal ) . toEqual ( [ true ,  true ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-11-10 15:56:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								      describe ( 'errors' ,  ( )  = >  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        it ( 'should report unexpected closing tags' ,  ( )  = >  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-11-12 14:08:58 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          const  errors  =  parser . parse ( '<div></p></div>' ,  'TestComp' ) . errors ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-11-10 15:56:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          expect ( errors . length ) . toEqual ( 1 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-03-11 00:05:17 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          expect ( humanizeErrors ( errors ) ) . toEqual ( [ [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'p' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'Unexpected closing tag "p". It may happen when the tag has already been closed by another tag. For more info see https://www.w3.org/TR/html5/syntax.html#closing-elements-that-have-implied-end-tags' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            '0:5' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          ] ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-11-10 15:56:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-06-03 19:49:17 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        it ( 'should report subsequent open tags without proper close tag' ,  ( )  = >  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-11-12 14:08:58 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          const  errors  =  parser . parse ( '<div</div>' ,  'TestComp' ) . errors ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-03 19:49:17 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          expect ( errors . length ) . toEqual ( 1 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-03-11 00:05:17 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          expect ( humanizeErrors ( errors ) ) . toEqual ( [ [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'div' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'Unexpected closing tag "div". It may happen when the tag has already been closed by another tag. For more info see https://www.w3.org/TR/html5/syntax.html#closing-elements-that-have-implied-end-tags' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            '0:4' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          ] ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-03 19:49:17 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-12-03 15:53:44 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        it ( 'should report closing tag for void elements' ,  ( )  = >  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-11-12 14:08:58 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          const  errors  =  parser . parse ( '<input></input>' ,  'TestComp' ) . errors ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-12-02 10:11:01 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          expect ( errors . length ) . toEqual ( 1 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          expect ( humanizeErrors ( errors ) ) . toEqual ( [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ 'input' ,  'Void elements do not have end tags "input"' ,  '0:7' ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-12-02 10:11:01 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-12-03 16:10:20 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        it ( 'should report self closing html element' ,  ( )  = >  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-11-12 14:08:58 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          const  errors  =  parser . parse ( '<p />' ,  'TestComp' ) . errors ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-12-03 16:10:20 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          expect ( errors . length ) . toEqual ( 1 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          expect ( humanizeErrors ( errors ) ) . toEqual ( [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ 'p' ,  'Only void and foreign elements can be self closed "p"' ,  '0:0' ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-12-03 16:10:20 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        it ( 'should report self closing custom element' ,  ( )  = >  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-11-12 14:08:58 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          const  errors  =  parser . parse ( '<my-cmp />' ,  'TestComp' ) . errors ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-12-03 16:10:20 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          expect ( errors . length ) . toEqual ( 1 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          expect ( humanizeErrors ( errors ) ) . toEqual ( [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            [ 'my-cmp' ,  'Only void and foreign elements can be self closed "my-cmp"' ,  '0:0' ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-12-03 16:10:20 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-11-10 15:56:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        it ( 'should also report lexer errors' ,  ( )  = >  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-11-12 14:08:58 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          const  errors  =  parser . parse ( '<!-err--><div></p></div>' ,  'TestComp' ) . errors ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-11-10 15:56:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          expect ( errors . length ) . toEqual ( 2 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          expect ( humanizeErrors ( errors ) ) . toEqual ( [ 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-21 13:56:58 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            [ TokenType . COMMENT_START ,  'Unexpected character "e"' ,  '0:3' ] , 
							 
						 
					
						
							
								
									
										
										
										
											2017-03-11 00:05:17 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              'p' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              'Unexpected closing tag "p". It may happen when the tag has already been closed by another tag. For more info see https://www.w3.org/TR/html5/syntax.html#closing-elements-that-have-implied-end-tags' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              '0:14' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            ] 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 16:38:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-11-10 15:56:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-08-25 15:36:02 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								      } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-03-23 13:43:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								export  function  humanizeErrors ( errors : ParseError [ ] ) :  any [ ]  {  
						 
					
						
							
								
									
										
										
										
											2016-06-22 17:25:42 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								  return  errors . map ( e  = >  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-21 13:56:58 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( e  instanceof  TreeError )  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-11-10 15:56:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								      // Parser errors
 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-22 17:25:42 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								      return  [ < any > e . elementName ,  e . msg ,  humanizeLineColumn ( e . span . start ) ] ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-11-10 15:56:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // Tokenizer errors
 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-22 17:25:42 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    return  [ ( < any > e ) . tokenType ,  e . msg ,  humanizeLineColumn ( e . span . start ) ] ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-11-10 15:56:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								  } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-04-28 17:50:03 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}