Skip to content

Commit

Permalink
apply text mask settings to inputs rrweb-io#1096
Browse files Browse the repository at this point in the history
  • Loading branch information
mdellanoce committed Jan 17, 2023
1 parent a4f52c5 commit eae89e8
Show file tree
Hide file tree
Showing 8 changed files with 740 additions and 3 deletions.
24 changes: 24 additions & 0 deletions packages/rrweb-snapshot/src/snapshot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,11 @@ function serializeNode(
keepIframeSrcFn,
newlyAddedElement,
rootId,
maskAllText,
maskTextClass,
unmaskTextClass,
maskTextSelector,
unmaskTextSelector,
});
case n.TEXT_NODE:
return serializeTextNode(n as Text, {
Expand Down Expand Up @@ -683,6 +688,11 @@ function serializeElementNode(
*/
newlyAddedElement?: boolean;
rootId: number | undefined;
maskAllText: boolean;
maskTextClass: string | RegExp;
unmaskTextClass: string | RegExp;
maskTextSelector: string | null;
unmaskTextSelector: string | null;
},
): serializedNode | false {
const {
Expand All @@ -698,6 +708,11 @@ function serializeElementNode(
keepIframeSrcFn,
newlyAddedElement = false,
rootId,
maskAllText,
maskTextClass,
unmaskTextClass,
maskTextSelector,
unmaskTextSelector,
} = options;
const needBlock = _isBlockedElement(n, blockClass, blockSelector);
const tagName = getValidTagName(n);
Expand Down Expand Up @@ -752,12 +767,21 @@ function serializeElementNode(
attributes.type !== 'button' &&
value
) {
const forceMask = needMaskingText(
n,
maskTextClass,
maskTextSelector,
unmaskTextClass,
unmaskTextSelector,
maskAllText,
);
attributes.value = maskInputValue({
type: attributes.type,
tagName,
value,
maskInputOptions,
maskInputFn,
forceMask,
});
} else if (checked) {
attributes.checked = checked;
Expand Down
5 changes: 4 additions & 1 deletion packages/rrweb-snapshot/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,17 +153,20 @@ export function maskInputValue({
type,
value,
maskInputFn,
forceMask,
}: {
maskInputOptions: MaskInputOptions;
tagName: string;
type: string | number | boolean | null;
value: string | null;
maskInputFn?: MaskInputFn;
forceMask?: boolean;
}): string {
let text = value || '';
if (
maskInputOptions[tagName.toLowerCase() as keyof MaskInputOptions] ||
maskInputOptions[type as keyof MaskInputOptions]
maskInputOptions[type as keyof MaskInputOptions] ||
forceMask
) {
if (maskInputFn) {
text = maskInputFn(text);
Expand Down
1 change: 1 addition & 0 deletions packages/rrweb/src/record/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,7 @@ function record<T = eventWithTime>(
unmaskTextSelector,
inlineStylesheet,
maskAllInputs: maskInputOptions,
maskInputFn,
maskTextFn,
slimDOM: slimDOMOptions,
dataURLOptions,
Expand Down
9 changes: 9 additions & 0 deletions packages/rrweb/src/record/mutation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -511,12 +511,21 @@ export default class MutationBuffer {
const target = m.target as HTMLElement;
let value = (m.target as HTMLElement).getAttribute(m.attributeName!);
if (m.attributeName === 'value') {
const forceMask = needMaskingText(
m.target,
this.maskTextClass,
this.maskTextSelector,
this.unmaskTextClass,
this.unmaskTextSelector,
this.maskAllText,
);
value = maskInputValue({
maskInputOptions: this.maskInputOptions,
tagName: (m.target as HTMLElement).tagName,
type: (m.target as HTMLElement).getAttribute('type'),
value,
maskInputFn: this.maskInputFn,
forceMask,
});
}
if (
Expand Down
24 changes: 22 additions & 2 deletions packages/rrweb/src/record/observer.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { MaskInputOptions, maskInputValue, Mirror } from 'rrweb-snapshot';
import {
MaskInputOptions,
maskInputValue,
Mirror,
needMaskingText,
} from 'rrweb-snapshot';
import type { FontFaceSet } from 'css-font-loading-module';
import {
throttle,
Expand Down Expand Up @@ -339,6 +344,11 @@ function initInputObserver({
maskInputFn,
sampling,
userTriggeredOnInput,
maskAllText,
maskTextClass,
unmaskTextClass,
maskTextSelector,
unmaskTextSelector,
}: observerParam): listenerHandler {
function eventHandler(event: Event) {
let target = getEventTarget(event);
Expand All @@ -363,20 +373,30 @@ function initInputObserver({
}
let text = (target as HTMLInputElement).value;
let isChecked = false;
const forceMask = needMaskingText(
target as Node,
maskTextClass,
maskTextSelector,
unmaskTextClass,
unmaskTextSelector,
maskAllText,
);
if (type === 'radio' || type === 'checkbox') {
isChecked = (target as HTMLInputElement).checked;
} else if (
maskInputOptions[
(target as Element).tagName.toLowerCase() as keyof MaskInputOptions
] ||
maskInputOptions[type as keyof MaskInputOptions]
maskInputOptions[type as keyof MaskInputOptions] ||
forceMask
) {
text = maskInputValue({
maskInputOptions,
tagName: (target as HTMLElement).tagName,
type,
value: text,
maskInputFn,
forceMask,
});
}
cbWithDedup(
Expand Down
Loading

0 comments on commit eae89e8

Please sign in to comment.