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 ' ) } \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 } \nCause: ${ 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