Add options to mask texts (#540)
* feat: add options to mask texts * feat: add the default mask function * refactor: rename options to identify the difference between mask text and mask input * test: add tests about masking * doc: add options about masking * chore: bump up rrweb-snapshot version
This commit is contained in:
10
guide.md
10
guide.md
@@ -142,10 +142,13 @@ The parameter of `rrweb.record` accepts the following options.
|
|||||||
| checkoutEveryNms | - | take a full snapshot after every N ms<br />refer to the [checkout](#checkout) chapter |
|
| checkoutEveryNms | - | take a full snapshot after every N ms<br />refer to the [checkout](#checkout) chapter |
|
||||||
| blockClass | 'rr-block' | Use a string or RegExp to configure which elements should be blocked, refer to the [privacy](#privacy) chapter |
|
| blockClass | 'rr-block' | Use a string or RegExp to configure which elements should be blocked, refer to the [privacy](#privacy) chapter |
|
||||||
| ignoreClass | 'rr-ignore' | Use a string or RegExp to configure which elements should be ignored, refer to the [privacy](#privacy) chapter |
|
| ignoreClass | 'rr-ignore' | Use a string or RegExp to configure which elements should be ignored, refer to the [privacy](#privacy) chapter |
|
||||||
| blockSelector | null | Use a string or RegExp to configure which selector should be blocked, refer to the [privacy](#privacy) chapter |
|
| maskTextClass | 'rr-mask' | Use a string or RegExp to configure which elements should be masked, refer to the [privacy](#privacy) chapter |
|
||||||
|
| blockSelector | null | Use a string to configure which selector should be blocked, refer to the [privacy](#privacy) chapter |
|
||||||
|
| maskTextSelector | null | Use a string to configure which selector should be masked, refer to the [privacy](#privacy) chapter |
|
||||||
| maskAllInputs | false | mask all input content as \* |
|
| maskAllInputs | false | mask all input content as \* |
|
||||||
| maskInputOptions | {} | mask some kinds of input \*<br />refer to the [list](https://github.com/rrweb-io/rrweb-snapshot/blob/6728d12b3cddd96951c86d948578f99ada5749ff/src/types.ts#L72) |
|
| maskInputOptions | {} | mask some kinds of input \*<br />refer to the [list](https://github.com/rrweb-io/rrweb-snapshot/blob/6728d12b3cddd96951c86d948578f99ada5749ff/src/types.ts#L72) |
|
||||||
| maskInputFn | - | customize mask input content recording logic |
|
| maskInputFn | - | customize mask input content recording logic |
|
||||||
|
| maskTextFn | - | customize mask text content recording logic |
|
||||||
| slimDOMOptions | {} | remove unnecessary parts of the DOM <br />refer to the [list](https://github.com/rrweb-io/rrweb-snapshot/blob/6728d12b3cddd96951c86d948578f99ada5749ff/src/types.ts#L91) |
|
| slimDOMOptions | {} | remove unnecessary parts of the DOM <br />refer to the [list](https://github.com/rrweb-io/rrweb-snapshot/blob/6728d12b3cddd96951c86d948578f99ada5749ff/src/types.ts#L91) |
|
||||||
| inlineStylesheet | true | whether to inline the stylesheet in the events |
|
| inlineStylesheet | true | whether to inline the stylesheet in the events |
|
||||||
| hooks | {} | hooks for events<br />refer to the [list](https://github.com/rrweb-io/rrweb/blob/9488deb6d54a5f04350c063d942da5e96ab74075/src/types.ts#L207) |
|
| hooks | {} | hooks for events<br />refer to the [list](https://github.com/rrweb-io/rrweb/blob/9488deb6d54a5f04350c063d942da5e96ab74075/src/types.ts#L207) |
|
||||||
@@ -163,6 +166,7 @@ You may find some contents on the webpage which are not willing to be recorded,
|
|||||||
- An element with the class name `.rr-ignore` will not record its input events.
|
- An element with the class name `.rr-ignore` will not record its input events.
|
||||||
- `input[type="password"]` will be ignored as default.
|
- `input[type="password"]` will be ignored as default.
|
||||||
- Mask options to mask the content in input elements.
|
- Mask options to mask the content in input elements.
|
||||||
|
- A text of elements with the class name `.rr-mask` and its children will be masked.
|
||||||
|
|
||||||
#### Checkout
|
#### Checkout
|
||||||
|
|
||||||
|
|||||||
@@ -66,6 +66,6 @@
|
|||||||
"@xstate/fsm": "^1.4.0",
|
"@xstate/fsm": "^1.4.0",
|
||||||
"fflate": "^0.4.4",
|
"fflate": "^0.4.4",
|
||||||
"mitt": "^1.1.3",
|
"mitt": "^1.1.3",
|
||||||
"rrweb-snapshot": "^1.1.1"
|
"rrweb-snapshot": "^1.1.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,11 +43,14 @@ function record<T = eventWithTime>(
|
|||||||
blockClass = 'rr-block',
|
blockClass = 'rr-block',
|
||||||
blockSelector = null,
|
blockSelector = null,
|
||||||
ignoreClass = 'rr-ignore',
|
ignoreClass = 'rr-ignore',
|
||||||
|
maskTextClass = 'rr-mask',
|
||||||
|
maskTextSelector = null,
|
||||||
inlineStylesheet = true,
|
inlineStylesheet = true,
|
||||||
maskAllInputs,
|
maskAllInputs,
|
||||||
maskInputOptions: _maskInputOptions,
|
maskInputOptions: _maskInputOptions,
|
||||||
slimDOMOptions: _slimDOMOptions,
|
slimDOMOptions: _slimDOMOptions,
|
||||||
maskInputFn,
|
maskInputFn,
|
||||||
|
maskTextFn,
|
||||||
hooks,
|
hooks,
|
||||||
packFn,
|
packFn,
|
||||||
sampling = {},
|
sampling = {},
|
||||||
@@ -203,8 +206,11 @@ function record<T = eventWithTime>(
|
|||||||
bypassOptions: {
|
bypassOptions: {
|
||||||
blockClass,
|
blockClass,
|
||||||
blockSelector,
|
blockSelector,
|
||||||
|
maskTextClass,
|
||||||
|
maskTextSelector,
|
||||||
inlineStylesheet,
|
inlineStylesheet,
|
||||||
maskInputOptions,
|
maskInputOptions,
|
||||||
|
maskTextFn,
|
||||||
recordCanvas,
|
recordCanvas,
|
||||||
slimDOMOptions,
|
slimDOMOptions,
|
||||||
iframeManager,
|
iframeManager,
|
||||||
@@ -228,8 +234,11 @@ function record<T = eventWithTime>(
|
|||||||
const [node, idNodeMap] = snapshot(document, {
|
const [node, idNodeMap] = snapshot(document, {
|
||||||
blockClass,
|
blockClass,
|
||||||
blockSelector,
|
blockSelector,
|
||||||
|
maskTextClass,
|
||||||
|
maskTextSelector,
|
||||||
inlineStylesheet,
|
inlineStylesheet,
|
||||||
maskAllInputs: maskInputOptions,
|
maskAllInputs: maskInputOptions,
|
||||||
|
maskTextFn,
|
||||||
slimDOM: slimDOMOptions,
|
slimDOM: slimDOMOptions,
|
||||||
recordCanvas,
|
recordCanvas,
|
||||||
onSerialize: (n) => {
|
onSerialize: (n) => {
|
||||||
@@ -396,6 +405,8 @@ function record<T = eventWithTime>(
|
|||||||
),
|
),
|
||||||
blockClass,
|
blockClass,
|
||||||
ignoreClass,
|
ignoreClass,
|
||||||
|
maskTextClass,
|
||||||
|
maskTextSelector,
|
||||||
maskInputOptions,
|
maskInputOptions,
|
||||||
inlineStylesheet,
|
inlineStylesheet,
|
||||||
sampling,
|
sampling,
|
||||||
@@ -403,6 +414,7 @@ function record<T = eventWithTime>(
|
|||||||
collectFonts,
|
collectFonts,
|
||||||
doc,
|
doc,
|
||||||
maskInputFn,
|
maskInputFn,
|
||||||
|
maskTextFn,
|
||||||
logOptions,
|
logOptions,
|
||||||
blockSelector,
|
blockSelector,
|
||||||
slimDOMOptions,
|
slimDOMOptions,
|
||||||
|
|||||||
@@ -6,15 +6,18 @@ import {
|
|||||||
SlimDOMOptions,
|
SlimDOMOptions,
|
||||||
IGNORED_NODE,
|
IGNORED_NODE,
|
||||||
isShadowRoot,
|
isShadowRoot,
|
||||||
|
needMaskingText,
|
||||||
} from 'rrweb-snapshot';
|
} from 'rrweb-snapshot';
|
||||||
import {
|
import {
|
||||||
mutationRecord,
|
mutationRecord,
|
||||||
blockClass,
|
blockClass,
|
||||||
|
maskTextClass,
|
||||||
mutationCallBack,
|
mutationCallBack,
|
||||||
textCursor,
|
textCursor,
|
||||||
attributeCursor,
|
attributeCursor,
|
||||||
removedNodeMutation,
|
removedNodeMutation,
|
||||||
addedNodeMutation,
|
addedNodeMutation,
|
||||||
|
MaskTextFn,
|
||||||
} from '../types';
|
} from '../types';
|
||||||
import {
|
import {
|
||||||
mirror,
|
mirror,
|
||||||
@@ -159,8 +162,11 @@ export default class MutationBuffer {
|
|||||||
private emissionCallback: mutationCallBack;
|
private emissionCallback: mutationCallBack;
|
||||||
private blockClass: blockClass;
|
private blockClass: blockClass;
|
||||||
private blockSelector: string | null;
|
private blockSelector: string | null;
|
||||||
|
private maskTextClass: maskTextClass;
|
||||||
|
private maskTextSelector: string | null;
|
||||||
private inlineStylesheet: boolean;
|
private inlineStylesheet: boolean;
|
||||||
private maskInputOptions: MaskInputOptions;
|
private maskInputOptions: MaskInputOptions;
|
||||||
|
private maskTextFn: MaskTextFn | undefined;
|
||||||
private recordCanvas: boolean;
|
private recordCanvas: boolean;
|
||||||
private slimDOMOptions: SlimDOMOptions;
|
private slimDOMOptions: SlimDOMOptions;
|
||||||
private doc: Document;
|
private doc: Document;
|
||||||
@@ -172,8 +178,11 @@ export default class MutationBuffer {
|
|||||||
cb: mutationCallBack,
|
cb: mutationCallBack,
|
||||||
blockClass: blockClass,
|
blockClass: blockClass,
|
||||||
blockSelector: string | null,
|
blockSelector: string | null,
|
||||||
|
maskTextClass: maskTextClass,
|
||||||
|
maskTextSelector: string | null,
|
||||||
inlineStylesheet: boolean,
|
inlineStylesheet: boolean,
|
||||||
maskInputOptions: MaskInputOptions,
|
maskInputOptions: MaskInputOptions,
|
||||||
|
maskTextFn: MaskTextFn | undefined,
|
||||||
recordCanvas: boolean,
|
recordCanvas: boolean,
|
||||||
slimDOMOptions: SlimDOMOptions,
|
slimDOMOptions: SlimDOMOptions,
|
||||||
doc: Document,
|
doc: Document,
|
||||||
@@ -182,8 +191,11 @@ export default class MutationBuffer {
|
|||||||
) {
|
) {
|
||||||
this.blockClass = blockClass;
|
this.blockClass = blockClass;
|
||||||
this.blockSelector = blockSelector;
|
this.blockSelector = blockSelector;
|
||||||
|
this.maskTextClass = maskTextClass;
|
||||||
|
this.maskTextSelector = maskTextSelector;
|
||||||
this.inlineStylesheet = inlineStylesheet;
|
this.inlineStylesheet = inlineStylesheet;
|
||||||
this.maskInputOptions = maskInputOptions;
|
this.maskInputOptions = maskInputOptions;
|
||||||
|
this.maskTextFn = maskTextFn;
|
||||||
this.recordCanvas = recordCanvas;
|
this.recordCanvas = recordCanvas;
|
||||||
this.slimDOMOptions = slimDOMOptions;
|
this.slimDOMOptions = slimDOMOptions;
|
||||||
this.emissionCallback = cb;
|
this.emissionCallback = cb;
|
||||||
@@ -266,9 +278,12 @@ export default class MutationBuffer {
|
|||||||
map: mirror.map,
|
map: mirror.map,
|
||||||
blockClass: this.blockClass,
|
blockClass: this.blockClass,
|
||||||
blockSelector: this.blockSelector,
|
blockSelector: this.blockSelector,
|
||||||
|
maskTextClass: this.maskTextClass,
|
||||||
|
maskTextSelector: this.maskTextSelector,
|
||||||
skipChild: true,
|
skipChild: true,
|
||||||
inlineStylesheet: this.inlineStylesheet,
|
inlineStylesheet: this.inlineStylesheet,
|
||||||
maskInputOptions: this.maskInputOptions,
|
maskInputOptions: this.maskInputOptions,
|
||||||
|
maskTextFn: this.maskTextFn,
|
||||||
slimDOMOptions: this.slimDOMOptions,
|
slimDOMOptions: this.slimDOMOptions,
|
||||||
recordCanvas: this.recordCanvas,
|
recordCanvas: this.recordCanvas,
|
||||||
onSerialize: (currentN) => {
|
onSerialize: (currentN) => {
|
||||||
@@ -409,7 +424,16 @@ export default class MutationBuffer {
|
|||||||
const value = m.target.textContent;
|
const value = m.target.textContent;
|
||||||
if (!isBlocked(m.target, this.blockClass) && value !== m.oldValue) {
|
if (!isBlocked(m.target, this.blockClass) && value !== m.oldValue) {
|
||||||
this.texts.push({
|
this.texts.push({
|
||||||
value,
|
value:
|
||||||
|
needMaskingText(
|
||||||
|
m.target,
|
||||||
|
this.maskTextClass,
|
||||||
|
this.maskTextSelector,
|
||||||
|
) && value
|
||||||
|
? this.maskTextFn
|
||||||
|
? this.maskTextFn(value)
|
||||||
|
: value.replace(/[\S]/g, '*')
|
||||||
|
: value,
|
||||||
node: m.target,
|
node: m.target,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import {
|
|||||||
inputCallback,
|
inputCallback,
|
||||||
hookResetter,
|
hookResetter,
|
||||||
blockClass,
|
blockClass,
|
||||||
|
maskTextClass,
|
||||||
IncrementalSource,
|
IncrementalSource,
|
||||||
hooksParam,
|
hooksParam,
|
||||||
Arguments,
|
Arguments,
|
||||||
@@ -36,6 +37,7 @@ import {
|
|||||||
fontCallback,
|
fontCallback,
|
||||||
fontParam,
|
fontParam,
|
||||||
MaskInputFn,
|
MaskInputFn,
|
||||||
|
MaskTextFn,
|
||||||
logCallback,
|
logCallback,
|
||||||
LogRecordOptions,
|
LogRecordOptions,
|
||||||
Logger,
|
Logger,
|
||||||
@@ -62,8 +64,11 @@ export function initMutationObserver(
|
|||||||
doc: Document,
|
doc: Document,
|
||||||
blockClass: blockClass,
|
blockClass: blockClass,
|
||||||
blockSelector: string | null,
|
blockSelector: string | null,
|
||||||
|
maskTextClass: maskTextClass,
|
||||||
|
maskTextSelector: string | null,
|
||||||
inlineStylesheet: boolean,
|
inlineStylesheet: boolean,
|
||||||
maskInputOptions: MaskInputOptions,
|
maskInputOptions: MaskInputOptions,
|
||||||
|
maskTextFn: MaskTextFn | undefined,
|
||||||
recordCanvas: boolean,
|
recordCanvas: boolean,
|
||||||
slimDOMOptions: SlimDOMOptions,
|
slimDOMOptions: SlimDOMOptions,
|
||||||
iframeManager: IframeManager,
|
iframeManager: IframeManager,
|
||||||
@@ -77,8 +82,11 @@ export function initMutationObserver(
|
|||||||
cb,
|
cb,
|
||||||
blockClass,
|
blockClass,
|
||||||
blockSelector,
|
blockSelector,
|
||||||
|
maskTextClass,
|
||||||
|
maskTextSelector,
|
||||||
inlineStylesheet,
|
inlineStylesheet,
|
||||||
maskInputOptions,
|
maskInputOptions,
|
||||||
|
maskTextFn,
|
||||||
recordCanvas,
|
recordCanvas,
|
||||||
slimDOMOptions,
|
slimDOMOptions,
|
||||||
doc,
|
doc,
|
||||||
@@ -777,8 +785,11 @@ export function initObservers(
|
|||||||
o.doc,
|
o.doc,
|
||||||
o.blockClass,
|
o.blockClass,
|
||||||
o.blockSelector,
|
o.blockSelector,
|
||||||
|
o.maskTextClass,
|
||||||
|
o.maskTextSelector,
|
||||||
o.inlineStylesheet,
|
o.inlineStylesheet,
|
||||||
o.maskInputOptions,
|
o.maskInputOptions,
|
||||||
|
o.maskTextFn,
|
||||||
o.recordCanvas,
|
o.recordCanvas,
|
||||||
o.slimDOMOptions,
|
o.slimDOMOptions,
|
||||||
o.iframeManager,
|
o.iframeManager,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { mutationCallBack, blockClass } from '../types';
|
import { mutationCallBack, blockClass, maskTextClass, MaskTextFn } from '../types';
|
||||||
import { MaskInputOptions, SlimDOMOptions } from 'rrweb-snapshot';
|
import { MaskInputOptions, SlimDOMOptions } from 'rrweb-snapshot';
|
||||||
import { IframeManager } from './iframe-manager';
|
import { IframeManager } from './iframe-manager';
|
||||||
import { initMutationObserver } from './observer';
|
import { initMutationObserver } from './observer';
|
||||||
@@ -6,8 +6,11 @@ import { initMutationObserver } from './observer';
|
|||||||
type BypassOptions = {
|
type BypassOptions = {
|
||||||
blockClass: blockClass;
|
blockClass: blockClass;
|
||||||
blockSelector: string | null;
|
blockSelector: string | null;
|
||||||
|
maskTextClass: maskTextClass;
|
||||||
|
maskTextSelector: string | null;
|
||||||
inlineStylesheet: boolean;
|
inlineStylesheet: boolean;
|
||||||
maskInputOptions: MaskInputOptions;
|
maskInputOptions: MaskInputOptions;
|
||||||
|
maskTextFn: MaskTextFn | undefined;
|
||||||
recordCanvas: boolean;
|
recordCanvas: boolean;
|
||||||
slimDOMOptions: SlimDOMOptions;
|
slimDOMOptions: SlimDOMOptions;
|
||||||
iframeManager: IframeManager;
|
iframeManager: IframeManager;
|
||||||
@@ -31,8 +34,11 @@ export class ShadowDomManager {
|
|||||||
doc,
|
doc,
|
||||||
this.bypassOptions.blockClass,
|
this.bypassOptions.blockClass,
|
||||||
this.bypassOptions.blockSelector,
|
this.bypassOptions.blockSelector,
|
||||||
|
this.bypassOptions.maskTextClass,
|
||||||
|
this.bypassOptions.maskTextSelector,
|
||||||
this.bypassOptions.inlineStylesheet,
|
this.bypassOptions.inlineStylesheet,
|
||||||
this.bypassOptions.maskInputOptions,
|
this.bypassOptions.maskInputOptions,
|
||||||
|
this.bypassOptions.maskTextFn,
|
||||||
this.bypassOptions.recordCanvas,
|
this.bypassOptions.recordCanvas,
|
||||||
this.bypassOptions.slimDOMOptions,
|
this.bypassOptions.slimDOMOptions,
|
||||||
this.bypassOptions.iframeManager,
|
this.bypassOptions.iframeManager,
|
||||||
|
|||||||
10
src/types.ts
10
src/types.ts
@@ -163,6 +163,8 @@ export type eventWithTime = event & {
|
|||||||
|
|
||||||
export type blockClass = string | RegExp;
|
export type blockClass = string | RegExp;
|
||||||
|
|
||||||
|
export type maskTextClass = string | RegExp;
|
||||||
|
|
||||||
export type SamplingStrategy = Partial<{
|
export type SamplingStrategy = Partial<{
|
||||||
/**
|
/**
|
||||||
* false means not to record mouse/touch move events
|
* false means not to record mouse/touch move events
|
||||||
@@ -196,9 +198,12 @@ export type recordOptions<T> = {
|
|||||||
blockClass?: blockClass;
|
blockClass?: blockClass;
|
||||||
blockSelector?: string;
|
blockSelector?: string;
|
||||||
ignoreClass?: string;
|
ignoreClass?: string;
|
||||||
|
maskTextClass?: maskTextClass;
|
||||||
|
maskTextSelector?: string;
|
||||||
maskAllInputs?: boolean;
|
maskAllInputs?: boolean;
|
||||||
maskInputOptions?: MaskInputOptions;
|
maskInputOptions?: MaskInputOptions;
|
||||||
maskInputFn?: MaskInputFn;
|
maskInputFn?: MaskInputFn;
|
||||||
|
maskTextFn?: MaskTextFn;
|
||||||
slimDOMOptions?: SlimDOMOptions | 'all' | true;
|
slimDOMOptions?: SlimDOMOptions | 'all' | true;
|
||||||
inlineStylesheet?: boolean;
|
inlineStylesheet?: boolean;
|
||||||
hooks?: hooksParam;
|
hooks?: hooksParam;
|
||||||
@@ -222,8 +227,11 @@ export type observerParam = {
|
|||||||
blockClass: blockClass;
|
blockClass: blockClass;
|
||||||
blockSelector: string | null;
|
blockSelector: string | null;
|
||||||
ignoreClass: string;
|
ignoreClass: string;
|
||||||
|
maskTextClass: maskTextClass;
|
||||||
|
maskTextSelector: string | null;
|
||||||
maskInputOptions: MaskInputOptions;
|
maskInputOptions: MaskInputOptions;
|
||||||
maskInputFn?: MaskInputFn;
|
maskInputFn?: MaskInputFn;
|
||||||
|
maskTextFn?: MaskTextFn;
|
||||||
inlineStylesheet: boolean;
|
inlineStylesheet: boolean;
|
||||||
styleSheetRuleCb: styleSheetRuleCallback;
|
styleSheetRuleCb: styleSheetRuleCallback;
|
||||||
canvasMutationCb: canvasMutationCallback;
|
canvasMutationCb: canvasMutationCallback;
|
||||||
@@ -583,6 +591,8 @@ export enum ReplayerEvents {
|
|||||||
|
|
||||||
export type MaskInputFn = (text: string) => string;
|
export type MaskInputFn = (text: string) => string;
|
||||||
|
|
||||||
|
export type MaskTextFn = (text: string) => string;
|
||||||
|
|
||||||
// store the state that would be changed during the process(unmount from dom and mount again)
|
// store the state that would be changed during the process(unmount from dom and mount again)
|
||||||
export type ElementState = {
|
export type ElementState = {
|
||||||
// [scrollLeft,scrollTop]
|
// [scrollLeft,scrollTop]
|
||||||
|
|||||||
@@ -4111,6 +4111,746 @@ exports[`mask 1`] = `
|
|||||||
]"
|
]"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`mask-character-data 1`] = `
|
||||||
|
"[
|
||||||
|
{
|
||||||
|
\\"type\\": 0,
|
||||||
|
\\"data\\": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 1,
|
||||||
|
\\"data\\": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 4,
|
||||||
|
\\"data\\": {
|
||||||
|
\\"href\\": \\"about:blank\\",
|
||||||
|
\\"width\\": 1920,
|
||||||
|
\\"height\\": 1080
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"data\\": {
|
||||||
|
\\"node\\": {
|
||||||
|
\\"type\\": 0,
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"html\\",
|
||||||
|
\\"attributes\\": {},
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"head\\",
|
||||||
|
\\"attributes\\": {},
|
||||||
|
\\"childNodes\\": [],
|
||||||
|
\\"id\\": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"body\\",
|
||||||
|
\\"attributes\\": {},
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"p\\",
|
||||||
|
\\"attributes\\": {},
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"mutation observer\\",
|
||||||
|
\\"id\\": 7
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"ul\\",
|
||||||
|
\\"attributes\\": {},
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"li\\",
|
||||||
|
\\"attributes\\": {},
|
||||||
|
\\"childNodes\\": [],
|
||||||
|
\\"id\\": 11
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 12
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 9
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n\\\\n \\",
|
||||||
|
\\"id\\": 13
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"script\\",
|
||||||
|
\\"attributes\\": {},
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"SCRIPT_PLACEHOLDER\\",
|
||||||
|
\\"id\\": 15
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 14
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\\\n \\",
|
||||||
|
\\"id\\": 16
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 4
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 2
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 1
|
||||||
|
},
|
||||||
|
\\"initialOffset\\": {
|
||||||
|
\\"left\\": 0,
|
||||||
|
\\"top\\": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"data\\": {
|
||||||
|
\\"source\\": 0,
|
||||||
|
\\"texts\\": [],
|
||||||
|
\\"attributes\\": [
|
||||||
|
{
|
||||||
|
\\"id\\": 6,
|
||||||
|
\\"attributes\\": {
|
||||||
|
\\"class\\": \\"rr-mask\\"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"removes\\": [
|
||||||
|
{
|
||||||
|
\\"parentId\\": 6,
|
||||||
|
\\"id\\": 7
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"adds\\": [
|
||||||
|
{
|
||||||
|
\\"parentId\\": 9,
|
||||||
|
\\"nextId\\": null,
|
||||||
|
\\"node\\": {
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"li\\",
|
||||||
|
\\"attributes\\": {
|
||||||
|
\\"class\\": \\"rr-mask\\"
|
||||||
|
},
|
||||||
|
\\"childNodes\\": [],
|
||||||
|
\\"id\\": 17
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"parentId\\": 17,
|
||||||
|
\\"nextId\\": null,
|
||||||
|
\\"node\\": {
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"*** **** ****\\",
|
||||||
|
\\"id\\": 18
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"parentId\\": 6,
|
||||||
|
\\"nextId\\": null,
|
||||||
|
\\"node\\": {
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"*******\\",
|
||||||
|
\\"id\\": 19
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`mask-text 1`] = `
|
||||||
|
"[
|
||||||
|
{
|
||||||
|
\\"type\\": 0,
|
||||||
|
\\"data\\": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 1,
|
||||||
|
\\"data\\": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 4,
|
||||||
|
\\"data\\": {
|
||||||
|
\\"href\\": \\"about:blank\\",
|
||||||
|
\\"width\\": 1920,
|
||||||
|
\\"height\\": 1080
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"data\\": {
|
||||||
|
\\"node\\": {
|
||||||
|
\\"type\\": 0,
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 1,
|
||||||
|
\\"name\\": \\"html\\",
|
||||||
|
\\"publicId\\": \\"\\",
|
||||||
|
\\"systemId\\": \\"\\",
|
||||||
|
\\"id\\": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"html\\",
|
||||||
|
\\"attributes\\": {
|
||||||
|
\\"lang\\": \\"en\\"
|
||||||
|
},
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"head\\",
|
||||||
|
\\"attributes\\": {},
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"meta\\",
|
||||||
|
\\"attributes\\": {
|
||||||
|
\\"charset\\": \\"UTF-8\\"
|
||||||
|
},
|
||||||
|
\\"childNodes\\": [],
|
||||||
|
\\"id\\": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 7
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"meta\\",
|
||||||
|
\\"attributes\\": {
|
||||||
|
\\"name\\": \\"viewport\\",
|
||||||
|
\\"content\\": \\"width=device-width, initial-scale=1.0\\"
|
||||||
|
},
|
||||||
|
\\"childNodes\\": [],
|
||||||
|
\\"id\\": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 9
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"meta\\",
|
||||||
|
\\"attributes\\": {
|
||||||
|
\\"http-equiv\\": \\"X-UA-Compatible\\",
|
||||||
|
\\"content\\": \\"ie=edge\\"
|
||||||
|
},
|
||||||
|
\\"childNodes\\": [],
|
||||||
|
\\"id\\": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 11
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"title\\",
|
||||||
|
\\"attributes\\": {},
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"Mask text\\",
|
||||||
|
\\"id\\": 13
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 12
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 14
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 15
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"body\\",
|
||||||
|
\\"attributes\\": {},
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 17
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"p\\",
|
||||||
|
\\"attributes\\": {
|
||||||
|
\\"class\\": \\"rr-mask\\"
|
||||||
|
},
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"*****\\",
|
||||||
|
\\"id\\": 19
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 18
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 20
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"div\\",
|
||||||
|
\\"attributes\\": {
|
||||||
|
\\"class\\": \\"rr-mask\\"
|
||||||
|
},
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 22
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"span\\",
|
||||||
|
\\"attributes\\": {},
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"*****\\",
|
||||||
|
\\"id\\": 24
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 23
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 25
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 21
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 26
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"div\\",
|
||||||
|
\\"attributes\\": {
|
||||||
|
\\"data-masking\\": \\"true\\"
|
||||||
|
},
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 28
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"div\\",
|
||||||
|
\\"attributes\\": {},
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 30
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"div\\",
|
||||||
|
\\"attributes\\": {},
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"*****\\",
|
||||||
|
\\"id\\": 32
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 31
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 33
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 29
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 34
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 27
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\\\n \\",
|
||||||
|
\\"id\\": 35
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"script\\",
|
||||||
|
\\"attributes\\": {},
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"SCRIPT_PLACEHOLDER\\",
|
||||||
|
\\"id\\": 37
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 36
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\\\n \\\\n\\\\n\\",
|
||||||
|
\\"id\\": 38
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 16
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 3
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 1
|
||||||
|
},
|
||||||
|
\\"initialOffset\\": {
|
||||||
|
\\"left\\": 0,
|
||||||
|
\\"top\\": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`mask-text-fn 1`] = `
|
||||||
|
"[
|
||||||
|
{
|
||||||
|
\\"type\\": 0,
|
||||||
|
\\"data\\": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 1,
|
||||||
|
\\"data\\": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 4,
|
||||||
|
\\"data\\": {
|
||||||
|
\\"href\\": \\"about:blank\\",
|
||||||
|
\\"width\\": 1920,
|
||||||
|
\\"height\\": 1080
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"data\\": {
|
||||||
|
\\"node\\": {
|
||||||
|
\\"type\\": 0,
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 1,
|
||||||
|
\\"name\\": \\"html\\",
|
||||||
|
\\"publicId\\": \\"\\",
|
||||||
|
\\"systemId\\": \\"\\",
|
||||||
|
\\"id\\": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"html\\",
|
||||||
|
\\"attributes\\": {
|
||||||
|
\\"lang\\": \\"en\\"
|
||||||
|
},
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"head\\",
|
||||||
|
\\"attributes\\": {},
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"meta\\",
|
||||||
|
\\"attributes\\": {
|
||||||
|
\\"charset\\": \\"UTF-8\\"
|
||||||
|
},
|
||||||
|
\\"childNodes\\": [],
|
||||||
|
\\"id\\": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 7
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"meta\\",
|
||||||
|
\\"attributes\\": {
|
||||||
|
\\"name\\": \\"viewport\\",
|
||||||
|
\\"content\\": \\"width=device-width, initial-scale=1.0\\"
|
||||||
|
},
|
||||||
|
\\"childNodes\\": [],
|
||||||
|
\\"id\\": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 9
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"meta\\",
|
||||||
|
\\"attributes\\": {
|
||||||
|
\\"http-equiv\\": \\"X-UA-Compatible\\",
|
||||||
|
\\"content\\": \\"ie=edge\\"
|
||||||
|
},
|
||||||
|
\\"childNodes\\": [],
|
||||||
|
\\"id\\": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 11
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"title\\",
|
||||||
|
\\"attributes\\": {},
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"Mask text\\",
|
||||||
|
\\"id\\": 13
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 12
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 14
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 15
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"body\\",
|
||||||
|
\\"attributes\\": {},
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 17
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"p\\",
|
||||||
|
\\"attributes\\": {
|
||||||
|
\\"class\\": \\"rr-mask\\"
|
||||||
|
},
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"****1\\",
|
||||||
|
\\"id\\": 19
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 18
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 20
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"div\\",
|
||||||
|
\\"attributes\\": {
|
||||||
|
\\"class\\": \\"rr-mask\\"
|
||||||
|
},
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 22
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"span\\",
|
||||||
|
\\"attributes\\": {},
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"****2\\",
|
||||||
|
\\"id\\": 24
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 23
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 25
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 21
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 26
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"div\\",
|
||||||
|
\\"attributes\\": {
|
||||||
|
\\"data-masking\\": \\"true\\"
|
||||||
|
},
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 28
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"div\\",
|
||||||
|
\\"attributes\\": {},
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 30
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"div\\",
|
||||||
|
\\"attributes\\": {},
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"****3\\",
|
||||||
|
\\"id\\": 32
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 31
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 33
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 29
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\",
|
||||||
|
\\"id\\": 34
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 27
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\\\n \\",
|
||||||
|
\\"id\\": 35
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 2,
|
||||||
|
\\"tagName\\": \\"script\\",
|
||||||
|
\\"attributes\\": {},
|
||||||
|
\\"childNodes\\": [
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"SCRIPT_PLACEHOLDER\\",
|
||||||
|
\\"id\\": 37
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 36
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\\"type\\": 3,
|
||||||
|
\\"textContent\\": \\"\\\\n \\\\n \\\\n\\\\n\\",
|
||||||
|
\\"id\\": 38
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 16
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 3
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\\"id\\": 1
|
||||||
|
},
|
||||||
|
\\"initialOffset\\": {
|
||||||
|
\\"left\\": 0,
|
||||||
|
\\"top\\": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`maskInputOptions 1`] = `
|
exports[`maskInputOptions 1`] = `
|
||||||
"[
|
"[
|
||||||
{
|
{
|
||||||
|
|||||||
20
test/html/mask-text.html
Normal file
20
test/html/mask-text.html
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<!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>Mask text</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p class="rr-mask">mask1</p>
|
||||||
|
<div class="rr-mask">
|
||||||
|
<span>mask2</span>
|
||||||
|
</div>
|
||||||
|
<div data-masking="true">
|
||||||
|
<div>
|
||||||
|
<div>mask3</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -72,8 +72,10 @@ describe('record integration tests', function (this: ISuite) {
|
|||||||
emit: event => {
|
emit: event => {
|
||||||
window.snapshots.push(event);
|
window.snapshots.push(event);
|
||||||
},
|
},
|
||||||
|
maskTextSelector: ${JSON.stringify(options.maskTextSelector)},
|
||||||
maskAllInputs: ${options.maskAllInputs},
|
maskAllInputs: ${options.maskAllInputs},
|
||||||
maskInputOptions: ${JSON.stringify(options.maskAllInputs)},
|
maskInputOptions: ${JSON.stringify(options.maskAllInputs)},
|
||||||
|
maskTextFn: ${options.maskTextFn},
|
||||||
recordCanvas: ${options.recordCanvas},
|
recordCanvas: ${options.recordCanvas},
|
||||||
recordLog: ${options.recordLog},
|
recordLog: ${options.recordLog},
|
||||||
});
|
});
|
||||||
@@ -456,4 +458,52 @@ describe('record integration tests', function (this: ISuite) {
|
|||||||
const snapshots = await page.evaluate('window.snapshots');
|
const snapshots = await page.evaluate('window.snapshots');
|
||||||
assertSnapshot(snapshots, __filename, 'shadow-dom');
|
assertSnapshot(snapshots, __filename, 'shadow-dom');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should mask texts', async () => {
|
||||||
|
const page: puppeteer.Page = await this.browser.newPage();
|
||||||
|
await page.goto('about:blank');
|
||||||
|
await page.setContent(
|
||||||
|
getHtml.call(this, 'mask-text.html', {
|
||||||
|
maskTextSelector: '[data-masking="true"]',
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
const snapshots = await page.evaluate('window.snapshots');
|
||||||
|
assertSnapshot(snapshots, __filename, 'mask-text');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should mask texts using maskTextFn', async () => {
|
||||||
|
const page: puppeteer.Page = await this.browser.newPage();
|
||||||
|
await page.goto('about:blank');
|
||||||
|
await page.setContent(
|
||||||
|
getHtml.call(this, 'mask-text.html', {
|
||||||
|
maskTextSelector: '[data-masking="true"]',
|
||||||
|
maskTextFn: (t: string) => t.replace(/[a-z]/g, '*'),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
const snapshots = await page.evaluate('window.snapshots');
|
||||||
|
assertSnapshot(snapshots, __filename, 'mask-text-fn');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can mask character data mutations', async () => {
|
||||||
|
const page: puppeteer.Page = await this.browser.newPage();
|
||||||
|
await page.goto('about:blank');
|
||||||
|
await page.setContent(getHtml.call(this, 'mutation-observer.html'));
|
||||||
|
|
||||||
|
await page.evaluate(() => {
|
||||||
|
const li = document.createElement('li');
|
||||||
|
const ul = document.querySelector('ul') as HTMLUListElement;
|
||||||
|
const p = document.querySelector('p') as HTMLParagraphElement;
|
||||||
|
[li, p].forEach((element) => {
|
||||||
|
element.className = 'rr-mask';
|
||||||
|
});
|
||||||
|
ul.appendChild(li);
|
||||||
|
li.innerText = 'new list item';
|
||||||
|
p.innerText = 'mutated';
|
||||||
|
});
|
||||||
|
|
||||||
|
const snapshots = await page.evaluate('window.snapshots');
|
||||||
|
assertSnapshot(snapshots, __filename, 'mask-character-data');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
8
typings/types.d.ts
vendored
8
typings/types.d.ts
vendored
@@ -3,6 +3,7 @@ import { serializedNodeWithId, idNodeMap, INode, MaskInputOptions, SlimDOMOption
|
|||||||
import { PackFn, UnpackFn } from './packer/base';
|
import { PackFn, UnpackFn } from './packer/base';
|
||||||
import { FontFaceDescriptors } from 'css-font-loading-module';
|
import { FontFaceDescriptors } from 'css-font-loading-module';
|
||||||
import { IframeManager } from './record/iframe-manager';
|
import { IframeManager } from './record/iframe-manager';
|
||||||
|
import { MaskTextFn } from '../src/types';
|
||||||
export declare enum EventType {
|
export declare enum EventType {
|
||||||
DomContentLoaded = 0,
|
DomContentLoaded = 0,
|
||||||
Load = 1,
|
Load = 1,
|
||||||
@@ -109,6 +110,7 @@ export declare type eventWithTime = event & {
|
|||||||
delay?: number;
|
delay?: number;
|
||||||
};
|
};
|
||||||
export declare type blockClass = string | RegExp;
|
export declare type blockClass = string | RegExp;
|
||||||
|
export declare type maskTextClass = string | RegExp;
|
||||||
export declare type SamplingStrategy = Partial<{
|
export declare type SamplingStrategy = Partial<{
|
||||||
mousemove: boolean | number;
|
mousemove: boolean | number;
|
||||||
mousemoveCallback: number;
|
mousemoveCallback: number;
|
||||||
@@ -123,9 +125,12 @@ export declare type recordOptions<T> = {
|
|||||||
blockClass?: blockClass;
|
blockClass?: blockClass;
|
||||||
blockSelector?: string;
|
blockSelector?: string;
|
||||||
ignoreClass?: string;
|
ignoreClass?: string;
|
||||||
|
maskTextClass?: maskTextClass;
|
||||||
|
maskTextSelector?: string | null;
|
||||||
maskAllInputs?: boolean;
|
maskAllInputs?: boolean;
|
||||||
maskInputOptions?: MaskInputOptions;
|
maskInputOptions?: MaskInputOptions;
|
||||||
maskInputFn?: MaskInputFn;
|
maskInputFn?: MaskInputFn;
|
||||||
|
maskTextFn?: MaskTextFn;
|
||||||
slimDOMOptions?: SlimDOMOptions | 'all' | true;
|
slimDOMOptions?: SlimDOMOptions | 'all' | true;
|
||||||
inlineStylesheet?: boolean;
|
inlineStylesheet?: boolean;
|
||||||
hooks?: hooksParam;
|
hooks?: hooksParam;
|
||||||
@@ -146,9 +151,12 @@ export declare type observerParam = {
|
|||||||
mediaInteractionCb: mediaInteractionCallback;
|
mediaInteractionCb: mediaInteractionCallback;
|
||||||
blockClass: blockClass;
|
blockClass: blockClass;
|
||||||
blockSelector: string | null;
|
blockSelector: string | null;
|
||||||
|
maskTextClass: maskTextClass;
|
||||||
|
maskTextSelector: string | null;
|
||||||
ignoreClass: string;
|
ignoreClass: string;
|
||||||
maskInputOptions: MaskInputOptions;
|
maskInputOptions: MaskInputOptions;
|
||||||
maskInputFn?: MaskInputFn;
|
maskInputFn?: MaskInputFn;
|
||||||
|
maskTextFn?: MaskTextFn;
|
||||||
inlineStylesheet: boolean;
|
inlineStylesheet: boolean;
|
||||||
styleSheetRuleCb: styleSheetRuleCallback;
|
styleSheetRuleCb: styleSheetRuleCallback;
|
||||||
canvasMutationCb: canvasMutationCallback;
|
canvasMutationCb: canvasMutationCallback;
|
||||||
|
|||||||
@@ -2767,10 +2767,10 @@ rollup@^2.3.3:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
fsevents "~2.1.2"
|
fsevents "~2.1.2"
|
||||||
|
|
||||||
rrweb-snapshot@^1.1.1:
|
rrweb-snapshot@^1.1.2:
|
||||||
version "1.1.1"
|
version "1.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/rrweb-snapshot/-/rrweb-snapshot-1.1.1.tgz#71da8792f43b8bd7017851edcd02e3d7c7cfef9f"
|
resolved "https://registry.yarnpkg.com/rrweb-snapshot/-/rrweb-snapshot-1.1.2.tgz#e9a5ce11f2dba8ff58e22f7f0b96954ef9133be2"
|
||||||
integrity sha512-xRX7s2/MA/Ifnul4ImAquD1w/Nkz6WOACm3xdKDdQrCD/xKdgcu1yWoJ8eSIXyfVSuIt4VfrhxJdeHyhC1gmGQ==
|
integrity sha512-J/BCClbk1fs9ilU9Bn8J/vUdumUllvNsmC1rVSz7rxqVzo+MthpI83gll1S3rBQVcxmQcLGmJWpkyO7M2rGyTw==
|
||||||
|
|
||||||
run-async@^2.2.0:
|
run-async@^2.2.0:
|
||||||
version "2.4.1"
|
version "2.4.1"
|
||||||
|
|||||||
Reference in New Issue
Block a user