77 idNodeMap ,
88 MaskInputOptions ,
99 SlimDOMOptions ,
10+ MaskTextFn ,
1011} from './types' ;
1112import { isElement , isShadowRoot } from './utils' ;
1213
@@ -206,6 +207,40 @@ export function _isBlockedElement(
206207 return false ;
207208}
208209
210+ export function needMaskingText (
211+ node : Node | null ,
212+ maskTextClass : string | RegExp ,
213+ maskTextSelector : string | null ,
214+ ) : boolean {
215+ if ( ! node ) {
216+ return false ;
217+ }
218+ if ( node . nodeType === node . ELEMENT_NODE ) {
219+ if ( typeof maskTextClass === 'string' ) {
220+ if ( ( node as HTMLElement ) . classList . contains ( maskTextClass ) ) {
221+ return true ;
222+ }
223+ } else {
224+ ( node as HTMLElement ) . classList . forEach ( ( className ) => {
225+ if ( maskTextClass . test ( className ) ) {
226+ return true ;
227+ }
228+ } ) ;
229+ }
230+ if ( maskTextSelector ) {
231+ if ( ( node as HTMLElement ) . matches ( maskTextSelector ) ) {
232+ return true ;
233+ }
234+ }
235+ return needMaskingText ( node . parentNode , maskTextClass , maskTextSelector ) ;
236+ }
237+ if ( node . nodeType === node . TEXT_NODE ) {
238+ // check parent node since text node do not have class name
239+ return needMaskingText ( node . parentNode , maskTextClass , maskTextSelector ) ;
240+ }
241+ return needMaskingText ( node . parentNode , maskTextClass , maskTextSelector ) ;
242+ }
243+
209244// https://stackoverflow.com/a/36155560
210245function onceIframeLoaded (
211246 iframeEl : HTMLIFrameElement ,
@@ -259,17 +294,23 @@ function serializeNode(
259294 doc : Document ;
260295 blockClass : string | RegExp ;
261296 blockSelector : string | null ;
297+ maskTextClass : string | RegExp ;
298+ maskTextSelector : string | null ;
262299 inlineStylesheet : boolean ;
263300 maskInputOptions : MaskInputOptions ;
301+ maskTextFn : MaskTextFn | undefined ;
264302 recordCanvas : boolean ;
265303 } ,
266304) : serializedNode | false {
267305 const {
268306 doc,
269307 blockClass,
270308 blockSelector,
309+ maskTextClass,
310+ maskTextSelector,
271311 inlineStylesheet,
272312 maskInputOptions = { } ,
313+ maskTextFn,
273314 recordCanvas,
274315 } = options ;
275316 // Only record root id when document object is not the base document
@@ -412,12 +453,23 @@ function serializeNode(
412453 n . parentNode && ( n . parentNode as HTMLElement ) . tagName ;
413454 let textContent = ( n as Text ) . textContent ;
414455 const isStyle = parentTagName === 'STYLE' ? true : undefined ;
456+ const isScript = parentTagName === 'SCRIPT' ? true : undefined ;
415457 if ( isStyle && textContent ) {
416458 textContent = absoluteToStylesheet ( textContent , getHref ( ) ) ;
417459 }
418- if ( parentTagName === 'SCRIPT' ) {
460+ if ( isScript ) {
419461 textContent = 'SCRIPT_PLACEHOLDER' ;
420462 }
463+ if (
464+ ! isStyle &&
465+ ! isScript &&
466+ needMaskingText ( n , maskTextClass , maskTextSelector ) &&
467+ textContent
468+ ) {
469+ textContent = maskTextFn
470+ ? maskTextFn ( textContent )
471+ : textContent . replace ( / [ \S ] / g, '*' ) ;
472+ }
421473 return {
422474 type : NodeType . Text ,
423475 textContent : textContent || '' ,
@@ -540,9 +592,12 @@ export function serializeNodeWithId(
540592 map : idNodeMap ;
541593 blockClass : string | RegExp ;
542594 blockSelector : string | null ;
595+ maskTextClass : string | RegExp ;
596+ maskTextSelector : string | null ;
543597 skipChild : boolean ;
544598 inlineStylesheet : boolean ;
545599 maskInputOptions ?: MaskInputOptions ;
600+ maskTextFn : MaskTextFn | undefined ;
546601 slimDOMOptions : SlimDOMOptions ;
547602 recordCanvas ?: boolean ;
548603 preserveWhiteSpace ?: boolean ;
@@ -556,9 +611,12 @@ export function serializeNodeWithId(
556611 map,
557612 blockClass,
558613 blockSelector,
614+ maskTextClass,
615+ maskTextSelector,
559616 skipChild = false ,
560617 inlineStylesheet = true ,
561618 maskInputOptions = { } ,
619+ maskTextFn,
562620 slimDOMOptions,
563621 recordCanvas = false ,
564622 onSerialize,
@@ -570,8 +628,11 @@ export function serializeNodeWithId(
570628 doc,
571629 blockClass,
572630 blockSelector,
631+ maskTextClass,
632+ maskTextSelector,
573633 inlineStylesheet,
574634 maskInputOptions,
635+ maskTextFn,
575636 recordCanvas,
576637 } ) ;
577638 if ( ! _serializedNode ) {
@@ -628,9 +689,12 @@ export function serializeNodeWithId(
628689 map,
629690 blockClass,
630691 blockSelector,
692+ maskTextClass,
693+ maskTextSelector,
631694 skipChild,
632695 inlineStylesheet,
633696 maskInputOptions,
697+ maskTextFn,
634698 slimDOMOptions,
635699 recordCanvas,
636700 preserveWhiteSpace,
@@ -675,9 +739,12 @@ export function serializeNodeWithId(
675739 map,
676740 blockClass,
677741 blockSelector,
742+ maskTextClass,
743+ maskTextSelector,
678744 skipChild : false ,
679745 inlineStylesheet,
680746 maskInputOptions,
747+ maskTextFn,
681748 slimDOMOptions,
682749 recordCanvas,
683750 preserveWhiteSpace,
@@ -702,11 +769,14 @@ function snapshot(
702769 n : Document ,
703770 options ?: {
704771 blockClass ?: string | RegExp ;
772+ blockSelector ?: string | null ;
773+ maskTextClass ?: string | RegExp ;
774+ maskTextSelector ?: string | null ;
705775 inlineStylesheet ?: boolean ;
706776 maskAllInputs ?: boolean | MaskInputOptions ;
777+ maskTextFn ?: MaskTextFn ;
707778 slimDOM ?: boolean | SlimDOMOptions ;
708779 recordCanvas ?: boolean ;
709- blockSelector ?: string | null ;
710780 preserveWhiteSpace ?: boolean ;
711781 onSerialize ?: ( n : INode ) => unknown ;
712782 onIframeLoad ?: ( iframeINode : INode , node : serializedNodeWithId ) => unknown ;
@@ -715,10 +785,13 @@ function snapshot(
715785) : [ serializedNodeWithId | null , idNodeMap ] {
716786 const {
717787 blockClass = 'rr-block' ,
788+ blockSelector = null ,
789+ maskTextClass = 'rr-mask' ,
790+ maskTextSelector = null ,
718791 inlineStylesheet = true ,
719792 recordCanvas = false ,
720- blockSelector = null ,
721793 maskAllInputs = false ,
794+ maskTextFn,
722795 slimDOM = false ,
723796 preserveWhiteSpace,
724797 onSerialize,
@@ -772,9 +845,12 @@ function snapshot(
772845 map : idNodeMap ,
773846 blockClass,
774847 blockSelector,
848+ maskTextClass,
849+ maskTextSelector,
775850 skipChild : false ,
776851 inlineStylesheet,
777852 maskInputOptions,
853+ maskTextFn,
778854 slimDOMOptions,
779855 recordCanvas,
780856 preserveWhiteSpace,
0 commit comments