Skip to content

Commit e54218b

Browse files
committed
provide a general visit function to modify rebuilt id node map
1 parent ae476d2 commit e54218b

File tree

1 file changed

+41
-21
lines changed

1 file changed

+41
-21
lines changed

src/rebuild.ts

Lines changed: 41 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export function addHoverClass(cssText: string): string {
6262
if (!ast.stylesheet) {
6363
return cssText;
6464
}
65-
ast.stylesheet.rules.forEach(rule => {
65+
ast.stylesheet.rules.forEach((rule) => {
6666
if ('selectors' in rule) {
6767
(rule.selectors || []).forEach((selector: string) => {
6868
if (HOVER_SELECTOR.test(selector)) {
@@ -102,7 +102,8 @@ function buildNode(
102102
continue;
103103
}
104104
let value = n.attributes[name];
105-
value = typeof value === 'boolean' || typeof value === 'number' ? '' : value;
105+
value =
106+
typeof value === 'boolean' || typeof value === 'number' ? '' : value;
106107
// attribute names start with rr_ are internal attributes added by rrweb
107108
if (!name.startsWith('rr_')) {
108109
const isTextarea = tagName === 'textarea' && name === 'value';
@@ -128,7 +129,11 @@ function buildNode(
128129
try {
129130
if (n.isSVG && name === 'xlink:href') {
130131
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+
) {
132137
// Rename some of the more common atttributes from https://www.w3schools.com/tags/ref_eventattributes.asp
133138
// as setting them triggers a console.error (which shows up despite the try/catch)
134139
// Assumption: these attributes are not used to css
@@ -220,40 +225,55 @@ export function buildNodeWithSN(
220225
return node as INode;
221226
}
222227

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_'))) {
228248
continue;
229249
}
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;
242256
}
243257
}
244258
}
245259

246260
function rebuild(
247261
n: serializedNodeWithId,
248262
doc: Document,
263+
onVisit?: (node: INode) => unknown,
249264
/**
250265
* This is not a public API yet, just for POC
251266
*/
252267
HACK_CSS: boolean = true,
253268
): [Node | null, idNodeMap] {
254269
const idNodeMap: idNodeMap = {};
255270
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+
});
257277
return [node, idNodeMap];
258278
}
259279

0 commit comments

Comments
 (0)