11import  {  assert  }  from  'vitest' ; 
22
3- /** @param  {Element } node */ 
4- function  clean_children ( node )  { 
3+ /** 
4+  * @param  {Element } node 
5+  * @param  {{ preserveComments: boolean } } opts 
6+  */ 
7+ function  clean_children ( node ,  opts )  { 
58	let  previous  =  null ; 
9+ 	let  has_element_children  =  false ; 
10+ 	let  template  = 
11+ 		node . nodeName  ===  'TEMPLATE'  ? /** @type  {HTMLTemplateElement } */  ( node )  : undefined ; 
12+ 
13+ 	if  ( template )  { 
14+ 		const  div  =  document . createElement ( 'div' ) ; 
15+ 		div . append ( template . content ) ; 
16+ 		node  =  div ; 
17+ 	} 
618
719	// sort attributes 
820	const  attributes  =  Array . from ( node . attributes ) . sort ( ( a ,  b )  =>  { 
@@ -14,6 +26,11 @@ function clean_children(node) {
1426	} ) ; 
1527
1628	attributes . forEach ( ( attr )  =>  { 
29+ 		// Strip out the special onload/onerror hydration events from the test output 
30+ 		if  ( ( attr . name  ===  'onload'  ||  attr . name  ===  'onerror' )  &&  attr . value  ===  'this.__e=event' )  { 
31+ 			return ; 
32+ 		} 
33+ 
1734		node . setAttribute ( attr . name ,  attr . value ) ; 
1835	} ) ; 
1936
@@ -27,24 +44,43 @@ function clean_children(node) {
2744				node . tagName  !==  'tspan' 
2845			)  { 
2946				node . removeChild ( child ) ; 
47+ 				continue ; 
3048			} 
3149
32- 			text . data  =  text . data . replace ( / [   \t \n \r \f ] + / g,  '\n ' ) ; 
50+ 			text . data  =  text . data . replace ( / [ ^ \S ] + / g,  '  ' ) ; 
3351
3452			if  ( previous  &&  previous . nodeType  ===  3 )  { 
3553				const  prev  =  /** @type  {Text } */  ( previous ) ; 
3654
3755				prev . data  +=  text . data ; 
38- 				prev . data  =  prev . data . replace ( / [   \t \n \r \f ] + / g,  '\n' ) ; 
39- 
4056				node . removeChild ( text ) ; 
57+ 
4158				text  =  prev ; 
59+ 				text . data  =  text . data . replace ( / [ ^ \S ] + / g,  ' ' ) ; 
60+ 
61+ 				continue ; 
4262			} 
43- 		}  else  if  ( child . nodeType  ===  8 )  { 
63+ 		} 
64+ 
65+ 		if  ( child . nodeType  ===  8  &&  ! opts . preserveComments )  { 
4466			// comment 
45- 			// do nothing 
46- 		}  else  { 
47- 			clean_children ( /** @type  {Element } */  ( child ) ) ; 
67+ 			child . remove ( ) ; 
68+ 			continue ; 
69+ 		} 
70+ 
71+ 		// add newlines for better readability and potentially recurse into children 
72+ 		if  ( child . nodeType  ===  1  ||  child . nodeType  ===  8 )  { 
73+ 			if  ( previous ?. nodeType  ===  3 )  { 
74+ 				const  prev  =  /** @type  {Text } */  ( previous ) ; 
75+ 				prev . data  =  prev . data . replace ( / ^ [ ^ \S ] + $ / ,  '\n' ) ; 
76+ 			}  else  if  ( previous ?. nodeType  ===  1  ||  previous ?. nodeType  ===  8 )  { 
77+ 				node . insertBefore ( document . createTextNode ( '\n' ) ,  child ) ; 
78+ 			} 
79+ 
80+ 			if  ( child . nodeType  ===  1 )  { 
81+ 				has_element_children  =  true ; 
82+ 				clean_children ( /** @type  {Element } */  ( child ) ,  opts ) ; 
83+ 			} 
4884		} 
4985
5086		previous  =  child ; 
@@ -53,37 +89,36 @@ function clean_children(node) {
5389	// collapse whitespace 
5490	if  ( node . firstChild  &&  node . firstChild . nodeType  ===  3 )  { 
5591		const  text  =  /** @type  {Text } */  ( node . firstChild ) ; 
56- 		text . data  =  text . data . replace ( / ^ [   \t \n \r \f ] + / ,  '' ) ; 
57- 		if  ( ! text . data . length )  node . removeChild ( text ) ; 
92+ 		text . data  =  text . data . trimStart ( ) ; 
5893	} 
5994
6095	if  ( node . lastChild  &&  node . lastChild . nodeType  ===  3 )  { 
6196		const  text  =  /** @type  {Text } */  ( node . lastChild ) ; 
62- 		text . data  =  text . data . replace ( / [   \t \n \r \f ] + $ / ,  '' ) ; 
63- 		if  ( ! text . data . length )  node . removeChild ( text ) ; 
97+ 		text . data  =  text . data . trimEnd ( ) ; 
98+ 	} 
99+ 
100+ 	// indent code for better readability 
101+ 	if  ( has_element_children  &&  node . parentNode )  { 
102+ 		node . innerHTML  =  `\n\  ${ node . innerHTML . replace ( / \n / g,  '\n  ' ) }  ; 
103+ 	} 
104+ 
105+ 	if  ( template )  { 
106+ 		template . innerHTML  =  node . innerHTML ; 
64107	} 
65108} 
66109
67110/** 
68111 * @param  {Window } window 
69112 * @param  {string } html 
70-  * @param  {{ removeDataSvelte?: boolean,  preserveComments?: boolean } } param2  
113+  * @param  {{ preserveComments?: boolean } } opts  
71114 */ 
72- export  function  normalize_html ( 
73- 	window , 
74- 	html , 
75- 	{  removeDataSvelte =  false ,  preserveComments =  false  } 
76- )  { 
115+ export  function  normalize_html ( window ,  html ,  {  preserveComments =  false  }  =  { } )  { 
77116	try  { 
78117		const  node  =  window . document . createElement ( 'div' ) ; 
79- 		node . innerHTML  =  html 
80- 			. replace ( / ( < ! ( - - ) ? .* ?\2> ) / g,  preserveComments  ? '$1'  : '' ) 
81- 			. replace ( / ( d a t a - s v e l t e - h = " [ ^ " ] + " ) / g,  removeDataSvelte  ? ''  : '$1' ) 
82- 			. replace ( / > [   \t \n \r \f ] + < / g,  '><' ) 
83- 			// Strip out the special onload/onerror hydration events from the test output 
84- 			. replace ( / \s ? o n e r r o r = " t h i s ._ _ e = e v e n t " | \s ? o n l o a d = " t h i s ._ _ e = e v e n t " / g,  '' ) 
85- 			. trim ( ) ; 
86- 		clean_children ( node ) ; 
118+ 
119+ 		node . innerHTML  =  html . trim ( ) ; 
120+ 		clean_children ( node ,  {  preserveComments } ) ; 
121+ 
87122		return  node . innerHTML ; 
88123	}  catch  ( err )  { 
89124		throw  new  Error ( `Failed to normalize HTML:\n${ html } ${ err }  ) ; 
@@ -99,67 +134,52 @@ export function normalize_new_line(html) {
99134} 
100135
101136/** 
102-  * @param  {{ removeDataSvelte?: boolean } } options 
137+  * @param  {string } actual 
138+  * @param  {string } expected 
139+  * @param  {string } [message] 
103140 */ 
104- export  function  setup_html_equal ( options  =  { } )  { 
105- 	/** 
106- 	 * @param  {string } actual 
107- 	 * @param  {string } expected 
108- 	 * @param  {string } [message] 
109- 	 */ 
110- 	const  assert_html_equal  =  ( actual ,  expected ,  message )  =>  { 
111- 		try  { 
112- 			assert . deepEqual ( 
113- 				normalize_html ( window ,  actual ,  options ) , 
114- 				normalize_html ( window ,  expected ,  options ) , 
115- 				message 
116- 			) ; 
117- 		}  catch  ( e )  { 
118- 			if  ( Error . captureStackTrace ) 
119- 				Error . captureStackTrace ( /** @type  {Error } */  ( e ) ,  assert_html_equal ) ; 
120- 			throw  e ; 
121- 		} 
122- 	} ; 
123- 
124- 	/** 
125- 	 * 
126- 	 * @param  {string } actual 
127- 	 * @param  {string } expected 
128- 	 * @param  {{ preserveComments?: boolean, withoutNormalizeHtml?: boolean } } param2 
129- 	 * @param  {string } [message] 
130- 	 */ 
131- 	const  assert_html_equal_with_options  =  ( 
132- 		actual , 
133- 		expected , 
134- 		{  preserveComments,  withoutNormalizeHtml } , 
135- 		message 
136- 	)  =>  { 
137- 		try  { 
138- 			assert . deepEqual ( 
139- 				withoutNormalizeHtml 
140- 					? normalize_new_line ( actual . trim ( ) ) 
141- 							. replace ( / ( \s d a t a - s v e l t e - h = " [ ^ " ] + " ) / g,  options . removeDataSvelte  ? ''  : '$1' ) 
142- 							. replace ( / ( < ! ( - - ) ? .* ?\2> ) / g,  preserveComments  !==  false  ? '$1'  : '' ) 
143- 					: normalize_html ( window ,  actual . trim ( ) ,  {  ...options ,  preserveComments } ) , 
144- 				withoutNormalizeHtml 
145- 					? normalize_new_line ( expected . trim ( ) ) 
146- 							. replace ( / ( \s d a t a - s v e l t e - h = " [ ^ " ] + " ) / g,  options . removeDataSvelte  ? ''  : '$1' ) 
147- 							. replace ( / ( < ! ( - - ) ? .* ?\2> ) / g,  preserveComments  !==  false  ? '$1'  : '' ) 
148- 					: normalize_html ( window ,  expected . trim ( ) ,  {  ...options ,  preserveComments } ) , 
149- 				message 
150- 			) ; 
151- 		}  catch  ( e )  { 
152- 			if  ( Error . captureStackTrace ) 
153- 				Error . captureStackTrace ( /** @type  {Error } */  ( e ) ,  assert_html_equal_with_options ) ; 
154- 			throw  e ; 
155- 		} 
156- 	} ; 
157- 
158- 	return  { 
159- 		assert_html_equal, 
160- 		assert_html_equal_with_options
161- 	} ; 
162- } 
141+ export  const  assert_html_equal  =  ( actual ,  expected ,  message )  =>  { 
142+ 	try  { 
143+ 		assert . deepEqual ( normalize_html ( window ,  actual ) ,  normalize_html ( window ,  expected ) ,  message ) ; 
144+ 	}  catch  ( e )  { 
145+ 		if  ( Error . captureStackTrace ) 
146+ 			Error . captureStackTrace ( /** @type  {Error } */  ( e ) ,  assert_html_equal ) ; 
147+ 		throw  e ; 
148+ 	} 
149+ } ; 
163150
164- // Common case without options 
165- export  const  {  assert_html_equal,  assert_html_equal_with_options }  =  setup_html_equal ( ) ; 
151+ /** 
152+  * 
153+  * @param  {string } actual 
154+  * @param  {string } expected 
155+  * @param  {{ preserveComments?: boolean, withoutNormalizeHtml?: boolean } } param2 
156+  * @param  {string } [message] 
157+  */ 
158+ export  const  assert_html_equal_with_options  =  ( 
159+ 	actual , 
160+ 	expected , 
161+ 	{  preserveComments,  withoutNormalizeHtml } , 
162+ 	message 
163+ )  =>  { 
164+ 	try  { 
165+ 		assert . deepEqual ( 
166+ 			withoutNormalizeHtml 
167+ 				? normalize_new_line ( actual . trim ( ) ) . replace ( 
168+ 						/ ( < ! ( - - ) ? .* ?\2> ) / g, 
169+ 						preserveComments  !==  false  ? '$1'  : '' 
170+ 					) 
171+ 				: normalize_html ( window ,  actual . trim ( ) ,  {  preserveComments } ) , 
172+ 			withoutNormalizeHtml 
173+ 				? normalize_new_line ( expected . trim ( ) ) . replace ( 
174+ 						/ ( < ! ( - - ) ? .* ?\2> ) / g, 
175+ 						preserveComments  !==  false  ? '$1'  : '' 
176+ 					) 
177+ 				: normalize_html ( window ,  expected . trim ( ) ,  {  preserveComments } ) , 
178+ 			message 
179+ 		) ; 
180+ 	}  catch  ( e )  { 
181+ 		if  ( Error . captureStackTrace ) 
182+ 			Error . captureStackTrace ( /** @type  {Error } */  ( e ) ,  assert_html_equal_with_options ) ; 
183+ 		throw  e ; 
184+ 	} 
185+ } ; 
0 commit comments