pick #286, export slim DOM options
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { snapshot, MaskInputOptions } from 'rrweb-snapshot';
|
||||
import { snapshot, MaskInputOptions, SlimDOMOptions } from 'rrweb-snapshot';
|
||||
import { initObservers, mutationBuffer } from './observer';
|
||||
import {
|
||||
mirror,
|
||||
@@ -38,6 +38,7 @@ function record<T = eventWithTime>(
|
||||
inlineStylesheet = true,
|
||||
maskAllInputs,
|
||||
maskInputOptions: _maskInputOptions,
|
||||
slimDOMOptions: _slimDOMOptions,
|
||||
maskInputFn,
|
||||
hooks,
|
||||
packFn,
|
||||
@@ -78,6 +79,26 @@ function record<T = eventWithTime>(
|
||||
? _maskInputOptions
|
||||
: {};
|
||||
|
||||
const slimDOMOptions: SlimDOMOptions =
|
||||
_slimDOMOptions === true || _slimDOMOptions === 'all'
|
||||
? {
|
||||
script: true,
|
||||
comment: true,
|
||||
headFavicon: true,
|
||||
headWhitespace: true,
|
||||
headMetaSocial: true,
|
||||
headMetaRobots: true,
|
||||
headMetaHttpEquiv: true,
|
||||
headMetaVerification: true,
|
||||
// the following are off for slimDOMOptions === true,
|
||||
// as they destroy some (hidden) info:
|
||||
headMetaAuthorship: _slimDOMOptions === 'all',
|
||||
headMetaDescKeywords: _slimDOMOptions === 'all',
|
||||
}
|
||||
: _slimDOMOptions === false
|
||||
? {}
|
||||
: _slimDOMOptions;
|
||||
|
||||
polyfill();
|
||||
|
||||
let lastFullSnapshotEvent: eventWithTime;
|
||||
@@ -134,6 +155,7 @@ function record<T = eventWithTime>(
|
||||
blockSelector,
|
||||
inlineStylesheet,
|
||||
maskAllInputs: maskInputOptions,
|
||||
slimDOM: slimDOMOptions,
|
||||
recordCanvas,
|
||||
});
|
||||
|
||||
@@ -299,6 +321,7 @@ function record<T = eventWithTime>(
|
||||
sampling,
|
||||
recordCanvas,
|
||||
collectFonts,
|
||||
slimDOMOptions,
|
||||
},
|
||||
hooks,
|
||||
),
|
||||
|
||||
@@ -3,6 +3,8 @@ import {
|
||||
serializeNodeWithId,
|
||||
transformAttribute,
|
||||
MaskInputOptions,
|
||||
SlimDOMOptions,
|
||||
IGNORED_NODE,
|
||||
} from 'rrweb-snapshot';
|
||||
import {
|
||||
mutationRecord,
|
||||
@@ -13,7 +15,7 @@ import {
|
||||
removedNodeMutation,
|
||||
addedNodeMutation,
|
||||
} from '../types';
|
||||
import { mirror, isBlocked, isAncestorRemoved } from '../utils';
|
||||
import { mirror, isBlocked, isAncestorRemoved, isIgnored } from '../utils';
|
||||
|
||||
type DoubleLinkedListNode = {
|
||||
previous: DoubleLinkedListNode | null;
|
||||
@@ -145,6 +147,7 @@ export default class MutationBuffer {
|
||||
private inlineStylesheet: boolean;
|
||||
private maskInputOptions: MaskInputOptions;
|
||||
private recordCanvas: boolean;
|
||||
private slimDOMOptions: SlimDOMOptions;
|
||||
|
||||
public init(
|
||||
cb: mutationCallBack,
|
||||
@@ -153,12 +156,14 @@ export default class MutationBuffer {
|
||||
inlineStylesheet: boolean,
|
||||
maskInputOptions: MaskInputOptions,
|
||||
recordCanvas: boolean,
|
||||
slimDOMOptions: SlimDOMOptions,
|
||||
) {
|
||||
this.blockClass = blockClass;
|
||||
this.blockSelector = blockSelector;
|
||||
this.inlineStylesheet = inlineStylesheet;
|
||||
this.maskInputOptions = maskInputOptions;
|
||||
this.recordCanvas = recordCanvas;
|
||||
this.slimDOMOptions = slimDOMOptions;
|
||||
this.emissionCallback = cb;
|
||||
}
|
||||
|
||||
@@ -193,8 +198,12 @@ export default class MutationBuffer {
|
||||
*/
|
||||
const addList = new DoubleLinkedList();
|
||||
const getNextId = (n: Node): number | null => {
|
||||
let nextId =
|
||||
n.nextSibling && mirror.getId((n.nextSibling as unknown) as INode);
|
||||
let ns: Node | null = n;
|
||||
let nextId: number | null = IGNORED_NODE; // slimDOM: ignored
|
||||
while (nextId === IGNORED_NODE) {
|
||||
ns = ns && ns.nextSibling;
|
||||
nextId = ns && mirror.getId((ns as unknown) as INode);
|
||||
}
|
||||
if (nextId === -1 && isBlocked(n.nextSibling, this.blockClass)) {
|
||||
nextId = null;
|
||||
}
|
||||
@@ -209,21 +218,24 @@ export default class MutationBuffer {
|
||||
if (parentId === -1 || nextId === -1) {
|
||||
return addList.addNode(n);
|
||||
}
|
||||
adds.push({
|
||||
parentId,
|
||||
nextId,
|
||||
node: serializeNodeWithId(n, {
|
||||
doc: document,
|
||||
map: mirror.map,
|
||||
blockClass: this.blockClass,
|
||||
blockSelector: this.blockSelector,
|
||||
skipChild: true,
|
||||
inlineStylesheet: this.inlineStylesheet,
|
||||
maskInputOptions: this.maskInputOptions,
|
||||
slimDOMOptions: {},
|
||||
recordCanvas: this.recordCanvas,
|
||||
})!,
|
||||
let sn = serializeNodeWithId(n, {
|
||||
doc: document,
|
||||
map: mirror.map,
|
||||
blockClass: this.blockClass,
|
||||
blockSelector: this.blockSelector,
|
||||
skipChild: true,
|
||||
inlineStylesheet: this.inlineStylesheet,
|
||||
maskInputOptions: this.maskInputOptions,
|
||||
slimDOMOptions: this.slimDOMOptions,
|
||||
recordCanvas: this.recordCanvas,
|
||||
});
|
||||
if (sn) {
|
||||
adds.push({
|
||||
parentId,
|
||||
nextId,
|
||||
node: sn,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
while (this.mapRemoves.length) {
|
||||
@@ -332,6 +344,9 @@ export default class MutationBuffer {
|
||||
};
|
||||
|
||||
private processMutation = (m: mutationRecord) => {
|
||||
if (isIgnored(m.target)) {
|
||||
return;
|
||||
}
|
||||
switch (m.type) {
|
||||
case 'characterData': {
|
||||
const value = m.target.textContent;
|
||||
@@ -373,7 +388,8 @@ export default class MutationBuffer {
|
||||
const parentId = mirror.getId(m.target as INode);
|
||||
if (
|
||||
isBlocked(n, this.blockClass) ||
|
||||
isBlocked(m.target, this.blockClass)
|
||||
isBlocked(m.target, this.blockClass) ||
|
||||
isIgnored(n)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
@@ -421,6 +437,9 @@ export default class MutationBuffer {
|
||||
return;
|
||||
}
|
||||
if (isINode(n)) {
|
||||
if (isIgnored(n)) {
|
||||
return;
|
||||
}
|
||||
this.movedSet.add(n);
|
||||
let targetId: number | null = null;
|
||||
if (target && isINode(target)) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { INode, MaskInputOptions } from 'rrweb-snapshot';
|
||||
import { INode, MaskInputOptions, SlimDOMOptions } from 'rrweb-snapshot';
|
||||
import { FontFaceDescriptors, FontFaceSet } from 'css-font-loading-module';
|
||||
import {
|
||||
mirror,
|
||||
@@ -48,6 +48,7 @@ function initMutationObserver(
|
||||
inlineStylesheet: boolean,
|
||||
maskInputOptions: MaskInputOptions,
|
||||
recordCanvas: boolean,
|
||||
slimDOMOptions: SlimDOMOptions,
|
||||
): MutationObserver {
|
||||
// see mutation.ts for details
|
||||
mutationBuffer.init(
|
||||
@@ -57,6 +58,7 @@ function initMutationObserver(
|
||||
inlineStylesheet,
|
||||
maskInputOptions,
|
||||
recordCanvas,
|
||||
slimDOMOptions,
|
||||
);
|
||||
const observer = new MutationObserver(
|
||||
mutationBuffer.processMutations.bind(mutationBuffer),
|
||||
@@ -584,6 +586,7 @@ export function initObservers(
|
||||
o.inlineStylesheet,
|
||||
o.maskInputOptions,
|
||||
o.recordCanvas,
|
||||
o.slimDOMOptions,
|
||||
);
|
||||
const mousemoveHandler = initMoveObserver(o.mousemoveCb, o.sampling);
|
||||
const mouseInteractionHandler = initMouseInteractionObserver(
|
||||
|
||||
@@ -3,6 +3,7 @@ import {
|
||||
idNodeMap,
|
||||
INode,
|
||||
MaskInputOptions,
|
||||
SlimDOMOptions,
|
||||
} from 'rrweb-snapshot';
|
||||
import { PackFn, UnpackFn } from './packer/base';
|
||||
import { FontFaceDescriptors } from 'css-font-loading-module';
|
||||
@@ -176,6 +177,7 @@ export type recordOptions<T> = {
|
||||
maskAllInputs?: boolean;
|
||||
maskInputOptions?: MaskInputOptions;
|
||||
maskInputFn?: MaskInputFn;
|
||||
slimDOMOptions?: SlimDOMOptions;
|
||||
inlineStylesheet?: boolean;
|
||||
hooks?: hooksParam;
|
||||
packFn?: PackFn;
|
||||
@@ -206,6 +208,7 @@ export type observerParam = {
|
||||
sampling: SamplingStrategy;
|
||||
recordCanvas: boolean;
|
||||
collectFonts: boolean;
|
||||
slimDOMOptions: SlimDOMOptions;
|
||||
};
|
||||
|
||||
export type hooksParam = {
|
||||
|
||||
11
src/utils.ts
11
src/utils.ts
@@ -15,7 +15,7 @@ import {
|
||||
scrollData,
|
||||
inputData,
|
||||
} from './types';
|
||||
import { INode } from 'rrweb-snapshot';
|
||||
import { INode, IGNORED_NODE } from 'rrweb-snapshot';
|
||||
|
||||
export function on(
|
||||
type: string,
|
||||
@@ -197,6 +197,15 @@ export function isBlocked(node: Node | null, blockClass: blockClass): boolean {
|
||||
return isBlocked(node.parentNode, blockClass);
|
||||
}
|
||||
|
||||
export function isIgnored(n: Node | INode): boolean {
|
||||
if ('__sn' in n) {
|
||||
return (n as INode).__sn.id === IGNORED_NODE;
|
||||
}
|
||||
// The main part of the slimDOM check happens in
|
||||
// rrweb-snapshot::serializeNodeWithId
|
||||
return false;
|
||||
}
|
||||
|
||||
export function isAncestorRemoved(target: INode): boolean {
|
||||
const id = mirror.getId(target);
|
||||
if (!mirror.has(id)) {
|
||||
|
||||
Reference in New Issue
Block a user