Skip to content

Commit e4593ff

Browse files
committed
part of rrweb #80, support configure mask input types
1 parent 63c3bd7 commit e4593ff

File tree

2 files changed

+56
-18
lines changed

2 files changed

+56
-18
lines changed

src/snapshot.ts

Lines changed: 40 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@ import {
55
attributes,
66
INode,
77
idNodeMap,
8+
MaskInputOptions,
89
} from './types';
910

1011
let _id = 1;
11-
const symbolAndNumberRegex = RegExp('[^a-z1-6\-]');
12+
const symbolAndNumberRegex = RegExp('[^a-z1-6-]');
1213

1314
function genId(): number {
1415
return _id++;
@@ -32,9 +33,9 @@ function getCssRulesString(s: CSSStyleSheet): string | null {
3233
const rules = s.rules || s.cssRules;
3334
return rules
3435
? Array.from(rules).reduce(
35-
(prev, cur) => prev + getCssRuleString(cur),
36-
'',
37-
)
36+
(prev, cur) => prev + getCssRuleString(cur),
37+
'',
38+
)
3839
: null;
3940
} catch (error) {
4041
return null;
@@ -54,10 +55,7 @@ function isCSSImportRule(rule: CSSRule): rule is CSSImportRule {
5455
function extractOrigin(url: string): string {
5556
let origin;
5657
if (url.indexOf('//') > -1) {
57-
origin = url
58-
.split('/')
59-
.slice(0, 3)
60-
.join('/');
58+
origin = url.split('/').slice(0, 3).join('/');
6159
} else {
6260
origin = url.split('/')[0];
6361
}
@@ -114,7 +112,7 @@ function getAbsoluteSrcsetString(doc: Document, attributeValue: string) {
114112
// srcset attributes is defined as such:
115113
// srcset = "url size,url1 size1"
116114
const resultingSrcsetString = srcsetValues
117-
.map(srcItem => {
115+
.map((srcItem) => {
118116
// removing all but middle spaces
119117
const trimmedSrcItem = srcItem.trimLeft().trimRight();
120118
const urlAndSize = trimmedSrcItem.split(' ');
@@ -168,7 +166,7 @@ function serializeNode(
168166
doc: Document,
169167
blockClass: string | RegExp,
170168
inlineStylesheet: boolean,
171-
maskAllInputs: boolean,
169+
maskInputOptions: MaskInputOptions = {},
172170
): serializedNode | false {
173171
switch (n.nodeType) {
174172
case n.DOCUMENT_NODE:
@@ -188,7 +186,7 @@ function serializeNode(
188186
if (typeof blockClass === 'string') {
189187
needBlock = (n as HTMLElement).classList.contains(blockClass);
190188
} else {
191-
(n as HTMLElement).classList.forEach(className => {
189+
(n as HTMLElement).classList.forEach((className) => {
192190
if (blockClass.test(className)) {
193191
needBlock = true;
194192
}
@@ -201,7 +199,7 @@ function serializeNode(
201199
}
202200
// remote css
203201
if (tagName === 'link' && inlineStylesheet) {
204-
const stylesheet = Array.from(doc.styleSheets).find(s => {
202+
const stylesheet = Array.from(doc.styleSheets).find((s) => {
205203
return s.href === (n as HTMLLinkElement).href;
206204
});
207205
const cssText = getCssRulesString(stylesheet as CSSStyleSheet);
@@ -246,7 +244,11 @@ function serializeNode(
246244
attributes.type !== 'button' &&
247245
value
248246
) {
249-
attributes.value = maskAllInputs ? '*'.repeat(value.length) : value;
247+
attributes.value = maskInputOptions[
248+
attributes.type as keyof MaskInputOptions
249+
]
250+
? '*'.repeat(value.length)
251+
: value;
250252
} else if ((n as HTMLInputElement).checked) {
251253
attributes.checked = (n as HTMLInputElement).checked;
252254
}
@@ -320,14 +322,14 @@ export function serializeNodeWithId(
320322
blockClass: string | RegExp,
321323
skipChild = false,
322324
inlineStylesheet = true,
323-
maskAllInputs = false,
325+
maskInputOptions?: MaskInputOptions,
324326
): serializedNodeWithId | null {
325327
const _serializedNode = serializeNode(
326328
n,
327329
doc,
328330
blockClass,
329331
inlineStylesheet,
330-
maskAllInputs,
332+
maskInputOptions,
331333
);
332334
if (!_serializedNode) {
333335
// TODO: dev only
@@ -363,7 +365,7 @@ export function serializeNodeWithId(
363365
blockClass,
364366
skipChild,
365367
inlineStylesheet,
366-
maskAllInputs,
368+
maskInputOptions,
367369
);
368370
if (serializedChildNode) {
369371
serializedNode.childNodes.push(serializedChildNode);
@@ -377,9 +379,29 @@ function snapshot(
377379
n: Document,
378380
blockClass: string | RegExp = 'rr-block',
379381
inlineStylesheet = true,
380-
maskAllInputs = false,
382+
maskAllInputsOrOptions: boolean | MaskInputOptions,
381383
): [serializedNodeWithId | null, idNodeMap] {
382384
const idNodeMap: idNodeMap = {};
385+
const maskInputOptions: MaskInputOptions =
386+
maskAllInputsOrOptions === true
387+
? {
388+
color: true,
389+
date: true,
390+
'datetime-local': true,
391+
email: true,
392+
month: true,
393+
number: true,
394+
range: true,
395+
search: true,
396+
tel: true,
397+
text: true,
398+
time: true,
399+
url: true,
400+
week: true,
401+
}
402+
: maskAllInputsOrOptions === false
403+
? {}
404+
: maskAllInputsOrOptions;
383405
return [
384406
serializeNodeWithId(
385407
n,
@@ -388,7 +410,7 @@ function snapshot(
388410
blockClass,
389411
false,
390412
inlineStylesheet,
391-
maskAllInputs,
413+
maskInputOptions,
392414
),
393415
idNodeMap,
394416
];

src/types.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,19 @@ export interface INode extends Node {
6868
export type idNodeMap = {
6969
[key: number]: INode;
7070
};
71+
72+
export type MaskInputOptions = Partial<{
73+
color: boolean;
74+
date: boolean;
75+
'datetime-local': boolean;
76+
email: boolean;
77+
month: boolean;
78+
number: boolean;
79+
range: boolean;
80+
search: boolean;
81+
tel: boolean;
82+
text: boolean;
83+
time: boolean;
84+
url: boolean;
85+
week: boolean;
86+
}>;

0 commit comments

Comments
 (0)