return id node map when snapshot

This commit is contained in:
Yanzhen Yu
2026-04-01 12:00:00 +08:00
parent ac5293f162
commit cfc8798b53
4 changed files with 37 additions and 10 deletions

4
index.d.ts vendored
View File

@@ -1,5 +1,5 @@
import { serializedNodeWithId } from './src/types';
import { serializedNodeWithId, idNodeMap } from './src/types';
export * from './src/types';
export function snapshot(n: Document): serializedNodeWithId | null;
export function snapshot(n: Document): [serializedNodeWithId | null, idNodeMap];
export function rebuild(n: serializedNodeWithId): Node | null;

View File

@@ -3,6 +3,8 @@ import {
serializedNodeWithId,
NodeType,
attributes,
INode,
idNodeMap,
} from './types';
let _id = 1;
@@ -115,22 +117,38 @@ function serializeNode(n: Node, doc: Document): serializedNode | false {
}
}
function _snapshot(n: Node, doc: Document): serializedNodeWithId | null {
function serializeNodeWithId(
n: Node,
doc: Document,
): serializedNodeWithId | null {
const _serializedNode = serializeNode(n, doc);
if (!_serializedNode) {
// TODO: dev only
console.warn(n, 'not serialized');
return null;
}
const serializedNode: serializedNodeWithId = Object.assign(_serializedNode, {
return Object.assign(_serializedNode, {
id: genId(),
});
}
function _snapshot(
n: Node,
doc: Document,
map: idNodeMap,
): serializedNodeWithId | null {
const serializedNode = serializeNodeWithId(n, doc);
if (!serializedNode) {
return null;
}
(n as INode).__sn = serializedNode;
map[serializedNode.id] = n as INode;
if (
serializedNode.type === NodeType.Document ||
serializedNode.type === NodeType.Element
) {
for (const childN of Array.from(n.childNodes)) {
const serializedChildNode = _snapshot(childN, doc);
const serializedChildNode = _snapshot(childN, doc, map);
if (serializedChildNode) {
serializedNode.childNodes.push(serializedChildNode);
}
@@ -139,9 +157,10 @@ function _snapshot(n: Node, doc: Document): serializedNodeWithId | null {
return serializedNode;
}
function snapshot(n: Document): serializedNodeWithId | null {
function snapshot(n: Document): [serializedNodeWithId | null, idNodeMap] {
resetId();
return _snapshot(n, n);
const idNodeMap: idNodeMap = {};
return [_snapshot(n, n, idNodeMap), idNodeMap];
}
export default snapshot;

View File

@@ -57,3 +57,11 @@ export type serializedNodeWithId = serializedNode & { id: number };
export type tagMap = {
[key: string]: string;
};
export interface INode extends Node {
__sn: serializedNodeWithId;
}
export type idNodeMap = {
[key: number]: INode;
};

View File

@@ -38,9 +38,9 @@ const server = () =>
'.css': 'text/css',
};
const s = http.createServer((req, res) => {
const parsedUrl = url.parse(req.url);
const parsedUrl = url.parse(req.url!);
const sanitizePath = path
.normalize(parsedUrl.pathname)
.normalize(parsedUrl.pathname!)
.replace(/^(\.\.[\/\\])+/, '');
let pathname = path.join(__dirname, sanitizePath);
try {
@@ -98,7 +98,7 @@ describe('integration tests', () => {
});
const rebuildHtml = (await page.evaluate(`${this.code}
const x = new XMLSerializer();
const snap = rrweb.snapshot(document);
const [snap] = rrweb.snapshot(document);
x.serializeToString(rrweb.rebuild(snap));
`)).replace(/\n\n/g, '');
await page.goto(`http://localhost:3030/html`);