From 2d1d3596b80a904edd860b19e436f5b8665f1502 Mon Sep 17 00:00:00 2001 From: Yanzhen Yu Date: Wed, 1 Apr 2026 12:00:00 +0800 Subject: [PATCH] handle block element --- src/rebuild.ts | 12 +++++++++++- src/snapshot.ts | 14 ++++++++++++- src/types.ts | 1 + test/__snapshots__/integration.ts.snap | 25 ++++++++++++++++++++++++ test/html/block-element.html | 27 ++++++++++++++++++++++++++ 5 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 test/html/block-element.html diff --git a/src/rebuild.ts b/src/rebuild.ts index 2256c40e..563e7867 100644 --- a/src/rebuild.ts +++ b/src/rebuild.ts @@ -53,7 +53,8 @@ function buildNode(n: serializedNodeWithId, doc: Document): Node | null { node = doc.createElement(tagName); } for (const name in n.attributes) { - if (n.attributes.hasOwnProperty(name)) { + // attribute names start with rr_ are internal attributes added by rrweb + if (n.attributes.hasOwnProperty(name) && !name.startsWith('rr_')) { let value = n.attributes[name]; value = typeof value === 'boolean' ? '' : value; const isTextarea = tagName === 'textarea' && name === 'value'; @@ -74,6 +75,15 @@ function buildNode(n: serializedNodeWithId, doc: Document): Node | null { } catch (error) { // skip invalid attribute } + } else { + // handle internal attributes + if (n.attributes.rr_width) { + (node as HTMLElement).style.width = n.attributes.rr_width as string; + } + if (n.attributes.rr_height) { + (node as HTMLElement).style.height = n.attributes + .rr_height as string; + } } } return node; diff --git a/src/snapshot.ts b/src/snapshot.ts index 4b4708d8..1edd5acc 100644 --- a/src/snapshot.ts +++ b/src/snapshot.ts @@ -78,6 +78,7 @@ function isSVGElement(el: Element): boolean { return el.tagName === 'svg' || el instanceof SVGElement; } +const BLOCK_CLASS = 'rr-block'; function serializeNode(n: Node, doc: Document): serializedNode | false { switch (n.nodeType) { case n.DOCUMENT_NODE: @@ -93,6 +94,7 @@ function serializeNode(n: Node, doc: Document): serializedNode | false { systemId: (n as DocumentType).systemId, }; case n.ELEMENT_NODE: + const needBlock = (n as HTMLElement).classList.contains(BLOCK_CLASS); const tagName = (n as HTMLElement).tagName.toLowerCase(); let attributes: attributes = {}; for (const { name, value } of Array.from((n as HTMLElement).attributes)) { @@ -138,12 +140,18 @@ function serializeNode(n: Node, doc: Document): serializedNode | false { attributes.selected = (n as HTMLOptionElement).selected; } } + if (needBlock) { + const { width, height } = (n as HTMLElement).getBoundingClientRect(); + attributes.rr_width = `${width}px`; + attributes.rr_height = `${height}px`; + } return { type: NodeType.Element, tagName, attributes, childNodes: [], isSVG: isSVGElement(n as Element) || undefined, + needBlock, }; case n.TEXT_NODE: // The parent node may not be a html element which has a tagName attribute. @@ -195,10 +203,14 @@ export function serializeNodeWithId( }); (n as INode).__sn = serializedNode; map[serializedNode.id] = n as INode; + let recordChild = !skipChild; + if (serializedNode.type === NodeType.Element) { + recordChild = recordChild && !serializedNode.needBlock; + } if ( (serializedNode.type === NodeType.Document || serializedNode.type === NodeType.Element) && - !skipChild + recordChild ) { for (const childN of Array.from(n.childNodes)) { const serializedChildNode = serializeNodeWithId(childN, doc, map); diff --git a/src/types.ts b/src/types.ts index 21fa2de3..2bdbd74c 100644 --- a/src/types.ts +++ b/src/types.ts @@ -28,6 +28,7 @@ export type elementNode = { attributes: attributes; childNodes: serializedNodeWithId[]; isSVG?: true; + needBlock?: boolean; }; export type textNode = { diff --git a/test/__snapshots__/integration.ts.snap b/test/__snapshots__/integration.ts.snap index 68cc0b97..7d0575fc 100644 --- a/test/__snapshots__/integration.ts.snap +++ b/test/__snapshots__/integration.ts.snap @@ -48,6 +48,31 @@ exports[`[html file]: basic.html 1`] = ` " `; +exports[`[html file]: block-element.html 1`] = ` +" + + + + Document + + +
+
record 2
+
+
+ " +`; + exports[`[html file]: cors-style-sheet.html 1`] = ` " diff --git a/test/html/block-element.html b/test/html/block-element.html new file mode 100644 index 00000000..f9671d2a --- /dev/null +++ b/test/html/block-element.html @@ -0,0 +1,27 @@ + + + + + + + Document + + + + +
block 1
+
record 2
+
block 3
+
block 3
+ +