handle block element
This commit is contained in:
@@ -53,7 +53,8 @@ function buildNode(n: serializedNodeWithId, doc: Document): Node | null {
|
|||||||
node = doc.createElement(tagName);
|
node = doc.createElement(tagName);
|
||||||
}
|
}
|
||||||
for (const name in n.attributes) {
|
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];
|
let value = n.attributes[name];
|
||||||
value = typeof value === 'boolean' ? '' : value;
|
value = typeof value === 'boolean' ? '' : value;
|
||||||
const isTextarea = tagName === 'textarea' && name === 'value';
|
const isTextarea = tagName === 'textarea' && name === 'value';
|
||||||
@@ -74,6 +75,15 @@ function buildNode(n: serializedNodeWithId, doc: Document): Node | null {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
// skip invalid attribute
|
// 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;
|
return node;
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ function isSVGElement(el: Element): boolean {
|
|||||||
return el.tagName === 'svg' || el instanceof SVGElement;
|
return el.tagName === 'svg' || el instanceof SVGElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const BLOCK_CLASS = 'rr-block';
|
||||||
function serializeNode(n: Node, doc: Document): serializedNode | false {
|
function serializeNode(n: Node, doc: Document): serializedNode | false {
|
||||||
switch (n.nodeType) {
|
switch (n.nodeType) {
|
||||||
case n.DOCUMENT_NODE:
|
case n.DOCUMENT_NODE:
|
||||||
@@ -93,6 +94,7 @@ function serializeNode(n: Node, doc: Document): serializedNode | false {
|
|||||||
systemId: (n as DocumentType).systemId,
|
systemId: (n as DocumentType).systemId,
|
||||||
};
|
};
|
||||||
case n.ELEMENT_NODE:
|
case n.ELEMENT_NODE:
|
||||||
|
const needBlock = (n as HTMLElement).classList.contains(BLOCK_CLASS);
|
||||||
const tagName = (n as HTMLElement).tagName.toLowerCase();
|
const tagName = (n as HTMLElement).tagName.toLowerCase();
|
||||||
let attributes: attributes = {};
|
let attributes: attributes = {};
|
||||||
for (const { name, value } of Array.from((n as HTMLElement).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;
|
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 {
|
return {
|
||||||
type: NodeType.Element,
|
type: NodeType.Element,
|
||||||
tagName,
|
tagName,
|
||||||
attributes,
|
attributes,
|
||||||
childNodes: [],
|
childNodes: [],
|
||||||
isSVG: isSVGElement(n as Element) || undefined,
|
isSVG: isSVGElement(n as Element) || undefined,
|
||||||
|
needBlock,
|
||||||
};
|
};
|
||||||
case n.TEXT_NODE:
|
case n.TEXT_NODE:
|
||||||
// The parent node may not be a html element which has a tagName attribute.
|
// 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;
|
(n as INode).__sn = serializedNode;
|
||||||
map[serializedNode.id] = n as INode;
|
map[serializedNode.id] = n as INode;
|
||||||
|
let recordChild = !skipChild;
|
||||||
|
if (serializedNode.type === NodeType.Element) {
|
||||||
|
recordChild = recordChild && !serializedNode.needBlock;
|
||||||
|
}
|
||||||
if (
|
if (
|
||||||
(serializedNode.type === NodeType.Document ||
|
(serializedNode.type === NodeType.Document ||
|
||||||
serializedNode.type === NodeType.Element) &&
|
serializedNode.type === NodeType.Element) &&
|
||||||
!skipChild
|
recordChild
|
||||||
) {
|
) {
|
||||||
for (const childN of Array.from(n.childNodes)) {
|
for (const childN of Array.from(n.childNodes)) {
|
||||||
const serializedChildNode = serializeNodeWithId(childN, doc, map);
|
const serializedChildNode = serializeNodeWithId(childN, doc, map);
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ export type elementNode = {
|
|||||||
attributes: attributes;
|
attributes: attributes;
|
||||||
childNodes: serializedNodeWithId[];
|
childNodes: serializedNodeWithId[];
|
||||||
isSVG?: true;
|
isSVG?: true;
|
||||||
|
needBlock?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type textNode = {
|
export type textNode = {
|
||||||
|
|||||||
@@ -48,6 +48,31 @@ exports[`[html file]: basic.html 1`] = `
|
|||||||
</head><body></body></html>"
|
</head><body></body></html>"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`[html file]: block-element.html 1`] = `
|
||||||
|
"<!DOCTYPE html><html xmlns=\\"http://www.w3.org/1999/xhtml\\" lang=\\"en\\"><head>
|
||||||
|
<meta charset=\\"UTF-8\\" />
|
||||||
|
<meta name=\\"viewport\\" content=\\"width=device-width, initial-scale=1.0\\" />
|
||||||
|
<meta http-equiv=\\"X-UA-Compatible\\" content=\\"ie=edge\\" />
|
||||||
|
<title>Document</title>
|
||||||
|
<style>
|
||||||
|
.big {
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
}
|
||||||
|
.small {
|
||||||
|
width: 50px;
|
||||||
|
height: 100px;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head> <body>
|
||||||
|
<div class=\\"rr-block big\\" style=\\"width: 50px; height: 50px;\\"></div>
|
||||||
|
<div>record 2</div>
|
||||||
|
<div class=\\"rr-block small\\" style=\\"width: 50px; height: 100px;\\"></div>
|
||||||
|
<div class=\\"rr-block\\" style=\\"height: 200px; width: 100px\\"></div>
|
||||||
|
</body></html>"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`[html file]: cors-style-sheet.html 1`] = `
|
exports[`[html file]: cors-style-sheet.html 1`] = `
|
||||||
"<!DOCTYPE html><html xmlns=\\"http://www.w3.org/1999/xhtml\\" lang=\\"en\\"><head>
|
"<!DOCTYPE html><html xmlns=\\"http://www.w3.org/1999/xhtml\\" lang=\\"en\\"><head>
|
||||||
<meta charset=\\"UTF-8\\" />
|
<meta charset=\\"UTF-8\\" />
|
||||||
|
|||||||
27
test/html/block-element.html
Normal file
27
test/html/block-element.html
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
|
||||||
|
<title>Document</title>
|
||||||
|
<style>
|
||||||
|
.big {
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
}
|
||||||
|
.small {
|
||||||
|
width: 50px;
|
||||||
|
height: 100px;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class="rr-block big">block 1</div>
|
||||||
|
<div>record 2</div>
|
||||||
|
<div class="rr-block small">block 3</div>
|
||||||
|
<div class="rr-block" style="height: 200px; width: 100px">block 3</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user