@@ -62,7 +62,7 @@ export function addHoverClass(cssText: string): string {
62
62
if ( ! ast . stylesheet ) {
63
63
return cssText ;
64
64
}
65
- ast . stylesheet . rules . forEach ( rule => {
65
+ ast . stylesheet . rules . forEach ( ( rule ) => {
66
66
if ( 'selectors' in rule ) {
67
67
( rule . selectors || [ ] ) . forEach ( ( selector : string ) => {
68
68
if ( HOVER_SELECTOR . test ( selector ) ) {
@@ -102,7 +102,8 @@ function buildNode(
102
102
continue ;
103
103
}
104
104
let value = n . attributes [ name ] ;
105
- value = typeof value === 'boolean' || typeof value === 'number' ? '' : value ;
105
+ value =
106
+ typeof value === 'boolean' || typeof value === 'number' ? '' : value ;
106
107
// attribute names start with rr_ are internal attributes added by rrweb
107
108
if ( ! name . startsWith ( 'rr_' ) ) {
108
109
const isTextarea = tagName === 'textarea' && name === 'value' ;
@@ -128,7 +129,11 @@ function buildNode(
128
129
try {
129
130
if ( n . isSVG && name === 'xlink:href' ) {
130
131
node . setAttributeNS ( 'http://www.w3.org/1999/xlink' , name , value ) ;
131
- } else if ( name == 'onload' || name == 'onclick' || name . substring ( 0 , 7 ) == 'onmouse' ) {
132
+ } else if (
133
+ name === 'onload' ||
134
+ name === 'onclick' ||
135
+ name . substring ( 0 , 7 ) === 'onmouse'
136
+ ) {
132
137
// Rename some of the more common atttributes from https://www.w3schools.com/tags/ref_eventattributes.asp
133
138
// as setting them triggers a console.error (which shows up despite the try/catch)
134
139
// Assumption: these attributes are not used to css
@@ -220,40 +225,55 @@ export function buildNodeWithSN(
220
225
return node as INode ;
221
226
}
222
227
223
- function sideEffects ( idNodeMap : idNodeMap ) {
224
- for ( let id in idNodeMap ) {
225
- const node = idNodeMap [ id ] ;
226
- const n = node . __sn ;
227
- if ( n . type !== NodeType . Element ) {
228
+ function visit ( idNodeMap : idNodeMap , onVisit : ( node : INode ) => void ) {
229
+ function walk ( node : INode ) {
230
+ onVisit ( node ) ;
231
+ }
232
+
233
+ for ( const key in idNodeMap ) {
234
+ if ( idNodeMap [ key ] ) {
235
+ walk ( idNodeMap [ key ] ) ;
236
+ }
237
+ }
238
+ }
239
+
240
+ function handleScroll ( node : INode ) {
241
+ const n = node . __sn ;
242
+ if ( n . type !== NodeType . Element ) {
243
+ return ;
244
+ }
245
+ const el = ( node as Node ) as HTMLElement ;
246
+ for ( const name in n . attributes ) {
247
+ if ( ! ( n . attributes . hasOwnProperty ( name ) && name . startsWith ( 'rr_' ) ) ) {
228
248
continue ;
229
249
}
230
- const el = node as Node as HTMLElement ;
231
- for ( const name in n . attributes ) {
232
- if ( ! ( n . attributes . hasOwnProperty ( name ) && name . startsWith ( 'rr_' ) ) ) {
233
- continue ;
234
- }
235
- const value = n . attributes [ name ] ;
236
- if ( name === 'rr_scrollLeft' ) {
237
- el . scrollLeft = value as number ;
238
- }
239
- if ( name === 'rr_scrollTop' ) {
240
- el . scrollTop = value as number ;
241
- }
250
+ const value = n . attributes [ name ] ;
251
+ if ( name === 'rr_scrollLeft' ) {
252
+ el . scrollLeft = value as number ;
253
+ }
254
+ if ( name === 'rr_scrollTop' ) {
255
+ el . scrollTop = value as number ;
242
256
}
243
257
}
244
258
}
245
259
246
260
function rebuild (
247
261
n : serializedNodeWithId ,
248
262
doc : Document ,
263
+ onVisit ?: ( node : INode ) => unknown ,
249
264
/**
250
265
* This is not a public API yet, just for POC
251
266
*/
252
267
HACK_CSS : boolean = true ,
253
268
) : [ Node | null , idNodeMap ] {
254
269
const idNodeMap : idNodeMap = { } ;
255
270
const node = buildNodeWithSN ( n , doc , idNodeMap , false , HACK_CSS ) ;
256
- sideEffects ( idNodeMap ) ;
271
+ visit ( idNodeMap , ( visitedNode ) => {
272
+ if ( onVisit ) {
273
+ onVisit ( visitedNode ) ;
274
+ }
275
+ handleScroll ( visitedNode ) ;
276
+ } ) ;
257
277
return [ node , idNodeMap ] ;
258
278
}
259
279
0 commit comments