clarity-js 0.6.39 → 0.6.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/clarity.js +103 -62
- package/build/clarity.min.js +1 -1
- package/build/clarity.module.js +103 -62
- package/package.json +1 -1
- package/src/core/config.ts +2 -1
- package/src/core/version.ts +1 -1
- package/src/data/upload.ts +6 -2
- package/src/index.ts +1 -1
- package/src/layout/dom.ts +14 -13
- package/src/layout/encode.ts +1 -1
- package/src/layout/selector.ts +47 -27
- package/test/core.test.ts +11 -5
- package/test/html/core.html +1 -0
- package/types/core.d.ts +1 -0
- package/types/data.d.ts +3 -2
- package/types/index.d.ts +6 -1
- package/types/layout.d.ts +11 -5
package/build/clarity.js
CHANGED
|
@@ -92,7 +92,8 @@ var config$1 = {
|
|
|
92
92
|
report: null,
|
|
93
93
|
upload: null,
|
|
94
94
|
fallback: null,
|
|
95
|
-
upgrade: null
|
|
95
|
+
upgrade: null,
|
|
96
|
+
action: null
|
|
96
97
|
};
|
|
97
98
|
|
|
98
99
|
function api(method) {
|
|
@@ -115,7 +116,7 @@ function stop$B() {
|
|
|
115
116
|
startTime = 0;
|
|
116
117
|
}
|
|
117
118
|
|
|
118
|
-
var version$1 = "0.6.
|
|
119
|
+
var version$1 = "0.6.41";
|
|
119
120
|
|
|
120
121
|
// tslint:disable: no-bitwise
|
|
121
122
|
function hash (input) {
|
|
@@ -142,9 +143,9 @@ var buffer = null;
|
|
|
142
143
|
var update$2 = false;
|
|
143
144
|
function start$E() {
|
|
144
145
|
update$2 = false;
|
|
145
|
-
reset$
|
|
146
|
+
reset$p();
|
|
146
147
|
}
|
|
147
|
-
function reset$
|
|
148
|
+
function reset$p() {
|
|
148
149
|
// Baseline state holds the previous values - if it is updated in the current payload,
|
|
149
150
|
// reset the state to current value after sending the previous state
|
|
150
151
|
if (update$2) {
|
|
@@ -212,14 +213,14 @@ function compute$c() {
|
|
|
212
213
|
}
|
|
213
214
|
}
|
|
214
215
|
function stop$A() {
|
|
215
|
-
reset$
|
|
216
|
+
reset$p();
|
|
216
217
|
}
|
|
217
218
|
|
|
218
219
|
var baseline = /*#__PURE__*/Object.freeze({
|
|
219
220
|
__proto__: null,
|
|
220
221
|
get state () { return state$9; },
|
|
221
222
|
start: start$E,
|
|
222
|
-
reset: reset$
|
|
223
|
+
reset: reset$p,
|
|
223
224
|
track: track$7,
|
|
224
225
|
activity: activity,
|
|
225
226
|
visibility: visibility,
|
|
@@ -289,7 +290,7 @@ function max(metric, value) {
|
|
|
289
290
|
function compute$b() {
|
|
290
291
|
encode$1(0 /* Event.Metric */);
|
|
291
292
|
}
|
|
292
|
-
function reset$
|
|
293
|
+
function reset$o() {
|
|
293
294
|
updates$3 = {};
|
|
294
295
|
}
|
|
295
296
|
|
|
@@ -308,7 +309,7 @@ function start$C() {
|
|
|
308
309
|
interval = 60000 /* Setting.PingInterval */;
|
|
309
310
|
last = 0;
|
|
310
311
|
}
|
|
311
|
-
function reset$
|
|
312
|
+
function reset$n() {
|
|
312
313
|
if (timeout$6) {
|
|
313
314
|
clearTimeout(timeout$6);
|
|
314
315
|
}
|
|
@@ -336,7 +337,7 @@ var ping$1 = /*#__PURE__*/Object.freeze({
|
|
|
336
337
|
__proto__: null,
|
|
337
338
|
get data () { return data$h; },
|
|
338
339
|
start: start$C,
|
|
339
|
-
reset: reset$
|
|
340
|
+
reset: reset$n,
|
|
340
341
|
stop: stop$y
|
|
341
342
|
});
|
|
342
343
|
|
|
@@ -367,7 +368,7 @@ function track$6(event, time) {
|
|
|
367
368
|
function compute$a() {
|
|
368
369
|
encode$1(36 /* Event.Summary */);
|
|
369
370
|
}
|
|
370
|
-
function reset$
|
|
371
|
+
function reset$m() {
|
|
371
372
|
data$g = {};
|
|
372
373
|
}
|
|
373
374
|
|
|
@@ -378,7 +379,7 @@ var summary = /*#__PURE__*/Object.freeze({
|
|
|
378
379
|
stop: stop$x,
|
|
379
380
|
track: track$6,
|
|
380
381
|
compute: compute$a,
|
|
381
|
-
reset: reset$
|
|
382
|
+
reset: reset$m
|
|
382
383
|
});
|
|
383
384
|
|
|
384
385
|
var data$f = null;
|
|
@@ -420,7 +421,7 @@ var upgrade$1 = /*#__PURE__*/Object.freeze({
|
|
|
420
421
|
|
|
421
422
|
var data$e = null;
|
|
422
423
|
function start$z() {
|
|
423
|
-
reset$
|
|
424
|
+
reset$l();
|
|
424
425
|
}
|
|
425
426
|
function set(variable, value) {
|
|
426
427
|
var values = typeof value === "string" /* Constant.String */ ? [value] : value;
|
|
@@ -451,11 +452,11 @@ function log$2(variable, value) {
|
|
|
451
452
|
function compute$9() {
|
|
452
453
|
encode$1(34 /* Event.Variable */);
|
|
453
454
|
}
|
|
454
|
-
function reset$
|
|
455
|
+
function reset$l() {
|
|
455
456
|
data$e = {};
|
|
456
457
|
}
|
|
457
458
|
function stop$v() {
|
|
458
|
-
reset$
|
|
459
|
+
reset$l();
|
|
459
460
|
}
|
|
460
461
|
|
|
461
462
|
var variable = /*#__PURE__*/Object.freeze({
|
|
@@ -465,7 +466,7 @@ var variable = /*#__PURE__*/Object.freeze({
|
|
|
465
466
|
set: set,
|
|
466
467
|
identify: identify,
|
|
467
468
|
compute: compute$9,
|
|
468
|
-
reset: reset$
|
|
469
|
+
reset: reset$l,
|
|
469
470
|
stop: stop$v
|
|
470
471
|
});
|
|
471
472
|
|
|
@@ -705,7 +706,7 @@ function redact(value) {
|
|
|
705
706
|
// Check if unicode regex is supported, otherwise fallback to calling mask function on this token
|
|
706
707
|
if (unicodeRegex && currencyRegex !== null) {
|
|
707
708
|
// Do not redact information if the token contains a currency symbol
|
|
708
|
-
token = token.match(currencyRegex) ? token : token.replace(letterRegex, "\
|
|
709
|
+
token = token.match(currencyRegex) ? token : token.replace(letterRegex, "\u25AA" /* Data.Constant.Letter */).replace(digitRegex, "\u25AB" /* Data.Constant.Digit */);
|
|
709
710
|
}
|
|
710
711
|
else {
|
|
711
712
|
token = mask(token);
|
|
@@ -743,12 +744,15 @@ function check$4(id, target, input) {
|
|
|
743
744
|
}
|
|
744
745
|
}
|
|
745
746
|
|
|
746
|
-
var
|
|
747
|
-
|
|
748
|
-
|
|
747
|
+
var excludeClassNames = "load,active,fixed,visible,focus,show,collaps,animat" /* Constant.ExcludeClassNames */.split("," /* Constant.Comma */);
|
|
748
|
+
var selectorMap = {};
|
|
749
|
+
function reset$k() {
|
|
750
|
+
selectorMap = {};
|
|
751
|
+
}
|
|
752
|
+
function get$1(input, type) {
|
|
749
753
|
var a = input.attributes;
|
|
750
|
-
var prefix = input.prefix ? input.prefix[
|
|
751
|
-
var suffix =
|
|
754
|
+
var prefix = input.prefix ? input.prefix[type] : null;
|
|
755
|
+
var suffix = type === 0 /* Selector.Alpha */ ? "".concat("~" /* Constant.Tilde */).concat(input.position - 1) : ":nth-of-type(".concat(input.position, ")");
|
|
752
756
|
switch (input.tag) {
|
|
753
757
|
case "STYLE":
|
|
754
758
|
case "TITLE":
|
|
@@ -763,23 +767,33 @@ function selector (input, beta) {
|
|
|
763
767
|
if (prefix === null) {
|
|
764
768
|
return "" /* Constant.Empty */;
|
|
765
769
|
}
|
|
766
|
-
prefix = "".concat(prefix
|
|
770
|
+
prefix = "".concat(prefix).concat(">" /* Constant.Separator */);
|
|
767
771
|
input.tag = input.tag.indexOf("svg:" /* Constant.SvgPrefix */) === 0 ? input.tag.substr("svg:" /* Constant.SvgPrefix */.length) : input.tag;
|
|
768
772
|
var selector = "".concat(prefix).concat(input.tag).concat(suffix);
|
|
769
|
-
var
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
773
|
+
var id = "id" /* Constant.Id */ in a && a["id" /* Constant.Id */].length > 0 ? a["id" /* Constant.Id */] : null;
|
|
774
|
+
var classes = input.tag !== "BODY" /* Constant.BodyTag */ && "class" /* Constant.Class */ in a && a["class" /* Constant.Class */].length > 0 ? a["class" /* Constant.Class */].trim().split(/\s+/).filter(function (c) { return filter(c); }).join("." /* Constant.Period */) : null;
|
|
775
|
+
if (classes && classes.length > 0) {
|
|
776
|
+
if (type === 0 /* Selector.Alpha */) {
|
|
777
|
+
// In Alpha mode, update selector to use class names, with relative positioning within the parent id container.
|
|
778
|
+
// If the node has valid class name(s) then drop relative positioning within the parent path to keep things simple.
|
|
779
|
+
var key = "".concat(getDomPath(prefix)).concat(input.tag).concat("." /* Constant.Dot */).concat(classes);
|
|
780
|
+
if (!(key in selectorMap)) {
|
|
781
|
+
selectorMap[key] = [];
|
|
782
|
+
}
|
|
783
|
+
if (selectorMap[key].indexOf(input.id) < 0) {
|
|
784
|
+
selectorMap[key].push(input.id);
|
|
785
|
+
}
|
|
786
|
+
selector = "".concat(key).concat("~" /* Constant.Tilde */).concat(selectorMap[key].indexOf(input.id));
|
|
787
|
+
}
|
|
788
|
+
else {
|
|
789
|
+
// In Beta mode, we continue to look at query selectors in context of the full page
|
|
790
|
+
selector = "".concat(prefix).concat(input.tag, ".").concat(classes).concat(suffix);
|
|
791
|
+
}
|
|
782
792
|
}
|
|
793
|
+
// Update selector to use "id" field when available. There are two exceptions:
|
|
794
|
+
// (1) if "id" appears to be an auto generated string token, e.g. guid or a random id containing digits
|
|
795
|
+
// (2) if "id" appears inside a shadow DOM, in which case we continue to prefix up to shadow DOM to prevent conflicts
|
|
796
|
+
selector = id && filter(id) ? "".concat(getDomPrefix(prefix)).concat("#" /* Constant.Hash */).concat(id) : selector;
|
|
783
797
|
return selector;
|
|
784
798
|
}
|
|
785
799
|
}
|
|
@@ -788,22 +802,42 @@ function getDomPrefix(prefix) {
|
|
|
788
802
|
var iframeDomStart = prefix.lastIndexOf("".concat("iframe:" /* Constant.IFramePrefix */).concat("HTML" /* Constant.HTML */));
|
|
789
803
|
var domStart = Math.max(shadowDomStart, iframeDomStart);
|
|
790
804
|
if (domStart < 0) {
|
|
791
|
-
return ""
|
|
805
|
+
return "" /* Constant.Empty */;
|
|
806
|
+
}
|
|
807
|
+
return prefix.substring(0, prefix.indexOf(">" /* Constant.Separator */, domStart) + 1);
|
|
808
|
+
}
|
|
809
|
+
function getDomPath(input) {
|
|
810
|
+
var parts = input.split(">" /* Constant.Separator */);
|
|
811
|
+
for (var i = 0; i < parts.length; i++) {
|
|
812
|
+
var tIndex = parts[i].indexOf("~" /* Constant.Tilde */);
|
|
813
|
+
var dIndex = parts[i].indexOf("." /* Constant.Dot */);
|
|
814
|
+
parts[i] = parts[i].substring(0, dIndex > 0 ? dIndex : (tIndex > 0 ? tIndex : parts[i].length));
|
|
792
815
|
}
|
|
793
|
-
|
|
794
|
-
return prefix.substr(0, domEnd);
|
|
816
|
+
return parts.join(">" /* Constant.Separator */);
|
|
795
817
|
}
|
|
796
|
-
// Check if the given input string has digits or
|
|
797
|
-
function
|
|
818
|
+
// Check if the given input string has digits or excluded class names
|
|
819
|
+
function filter(value) {
|
|
820
|
+
if (!value) {
|
|
821
|
+
return false;
|
|
822
|
+
} // Do not process empty strings
|
|
823
|
+
if (excludeClassNames.some(function (x) { return value.toLowerCase().indexOf(x) >= 0; })) {
|
|
824
|
+
return false;
|
|
825
|
+
}
|
|
798
826
|
for (var i = 0; i < value.length; i++) {
|
|
799
827
|
var c = value.charCodeAt(i);
|
|
800
828
|
if (c >= 48 /* Character.Zero */ && c <= 57 /* Character.Nine */) {
|
|
801
|
-
return
|
|
829
|
+
return false;
|
|
802
830
|
}
|
|
803
831
|
}
|
|
804
|
-
return
|
|
832
|
+
return true;
|
|
805
833
|
}
|
|
806
834
|
|
|
835
|
+
var selector = /*#__PURE__*/Object.freeze({
|
|
836
|
+
__proto__: null,
|
|
837
|
+
reset: reset$k,
|
|
838
|
+
get: get$1
|
|
839
|
+
});
|
|
840
|
+
|
|
807
841
|
// Track the start time to be able to compute duration at the end of the task
|
|
808
842
|
var idleTimeout = 5000;
|
|
809
843
|
var tracker = {};
|
|
@@ -1123,7 +1157,7 @@ function encode$4 (type, timer, ts) {
|
|
|
1123
1157
|
}
|
|
1124
1158
|
tokens.push(suspend ? "*M" /* Constant.SuspendMutationTag */ : data[key]);
|
|
1125
1159
|
if (box && box.length === 2) {
|
|
1126
|
-
tokens.push("".concat("#" /* Constant.
|
|
1160
|
+
tokens.push("".concat("#" /* Constant.Hash */).concat(str$1(box[0]), ".").concat(str$1(box[1])));
|
|
1127
1161
|
}
|
|
1128
1162
|
break;
|
|
1129
1163
|
case "attributes":
|
|
@@ -2377,6 +2411,7 @@ function reset$7() {
|
|
|
2377
2411
|
iframeMap = new WeakMap();
|
|
2378
2412
|
privacyMap = new WeakMap();
|
|
2379
2413
|
fraudMap = new WeakMap();
|
|
2414
|
+
reset$k();
|
|
2380
2415
|
}
|
|
2381
2416
|
// We parse new root nodes for any regions or masked nodes in the beginning (document) and
|
|
2382
2417
|
// later whenever there are new additions or modifications to DOM (mutations)
|
|
@@ -2553,14 +2588,11 @@ function privacy(node, value, parent) {
|
|
|
2553
2588
|
metadata.privacy = 2 /* Privacy.Text */;
|
|
2554
2589
|
break;
|
|
2555
2590
|
case tag === "*T" /* Constant.TextTag */:
|
|
2556
|
-
// If it's a text node belonging to a STYLE or TITLE tag or one of
|
|
2591
|
+
// If it's a text node belonging to a STYLE or TITLE tag or one of scrub exceptions, then capture content
|
|
2557
2592
|
var pTag = parent && parent.data ? parent.data.tag : "" /* Constant.Empty */;
|
|
2558
|
-
var pSelector_1 = parent && parent.selector ? parent.selector[
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
case "type" /* Constant.Type */ in attributes:
|
|
2562
|
-
// If this node has an explicit type assigned to it, go through masking rules to determine right privacy setting
|
|
2563
|
-
metadata.privacy = inspect(attributes["type" /* Constant.Type */], maskInput, metadata);
|
|
2593
|
+
var pSelector_1 = parent && parent.selector ? parent.selector[1 /* Selector.Default */] : "" /* Constant.Empty */;
|
|
2594
|
+
var tags = ["STYLE" /* Constant.StyleTag */, "TITLE" /* Constant.TitleTag */, "svg:style" /* Constant.SvgStyle */];
|
|
2595
|
+
metadata.privacy = tags.includes(pTag) || override.some(function (x) { return pSelector_1.indexOf(x) >= 0; }) ? 0 /* Privacy.None */ : current;
|
|
2564
2596
|
break;
|
|
2565
2597
|
case tag === "INPUT" /* Constant.InputTag */ && current === 0 /* Privacy.None */:
|
|
2566
2598
|
// If even default privacy setting is to not mask, we still scan through input fields for any sensitive information
|
|
@@ -2568,11 +2600,13 @@ function privacy(node, value, parent) {
|
|
|
2568
2600
|
Object.keys(attributes).forEach(function (x) { return field_1 += attributes[x].toLowerCase(); });
|
|
2569
2601
|
metadata.privacy = inspect(field_1, maskInput, metadata);
|
|
2570
2602
|
break;
|
|
2571
|
-
case
|
|
2603
|
+
case tag === "INPUT" /* Constant.InputTag */ && current === 1 /* Privacy.Sensitive */:
|
|
2572
2604
|
// Look through class names to aggressively mask content
|
|
2573
2605
|
metadata.privacy = inspect(attributes["class" /* Constant.Class */], maskText, metadata);
|
|
2574
|
-
// If
|
|
2575
|
-
metadata.privacy =
|
|
2606
|
+
// If this node has an explicit type assigned to it, go through masking rules to determine right privacy setting
|
|
2607
|
+
metadata.privacy = inspect(attributes["type" /* Constant.Type */], maskInput, metadata);
|
|
2608
|
+
// If it's a button or an input option, make an exception to disable masking in sensitive mode
|
|
2609
|
+
metadata.privacy = maskDisable.indexOf(attributes["type" /* Constant.Type */]) >= 0 ? 0 /* Privacy.None */ : metadata.privacy;
|
|
2576
2610
|
break;
|
|
2577
2611
|
case current === 1 /* Privacy.Sensitive */:
|
|
2578
2612
|
// In a mode where we mask sensitive information by default, look through class names to aggressively mask content
|
|
@@ -2619,10 +2653,11 @@ function updateSelector(value) {
|
|
|
2619
2653
|
var prefix = parent ? parent.selector : null;
|
|
2620
2654
|
var d = value.data;
|
|
2621
2655
|
var p = position(parent, value);
|
|
2622
|
-
var s = { tag: d.tag, prefix: prefix, position: p, attributes: d.attributes };
|
|
2623
|
-
value.selector = [
|
|
2656
|
+
var s = { id: value.id, tag: d.tag, prefix: prefix, position: p, attributes: d.attributes };
|
|
2657
|
+
value.selector = [get$1(s, 0 /* Selector.Alpha */), get$1(s, 1 /* Selector.Beta */)];
|
|
2624
2658
|
value.hash = value.selector.map(function (x) { return x ? hash(x) : null; });
|
|
2625
2659
|
value.hash.forEach(function (h) { return hashMap[h] = value.id; });
|
|
2660
|
+
// Match fragment configuration against both alpha and beta hash
|
|
2626
2661
|
if (value.hash.some(function (h) { return fragments.indexOf(h) !== -1; })) {
|
|
2627
2662
|
value.fragment = value.id;
|
|
2628
2663
|
}
|
|
@@ -3166,7 +3201,7 @@ function queue(tokens, transmit) {
|
|
|
3166
3201
|
// We enrich the data going out with the existing upload. In these cases, call to upload comes with 'transmit' set to false.
|
|
3167
3202
|
if (transmit && timeout === null) {
|
|
3168
3203
|
if (type !== 25 /* Event.Ping */) {
|
|
3169
|
-
reset$
|
|
3204
|
+
reset$n();
|
|
3170
3205
|
}
|
|
3171
3206
|
timeout = setTimeout(upload, gap);
|
|
3172
3207
|
queuedTime = now;
|
|
@@ -3356,8 +3391,8 @@ function delay() {
|
|
|
3356
3391
|
return typeof config$1.upload === "string" /* Constant.String */ ? Math.max(Math.min(gap, 30000 /* Setting.MaxUploadDelay */), 100 /* Setting.MinUploadDelay */) : config$1.delay;
|
|
3357
3392
|
}
|
|
3358
3393
|
function response(payload) {
|
|
3359
|
-
var
|
|
3360
|
-
switch (
|
|
3394
|
+
var parts = payload && payload.length > 0 ? payload.split(" ") : ["" /* Constant.Empty */];
|
|
3395
|
+
switch (parts[0]) {
|
|
3361
3396
|
case "END" /* Constant.End */:
|
|
3362
3397
|
// Clear out session storage and end the session so we can start fresh the next time
|
|
3363
3398
|
trigger(6 /* Check.Server */);
|
|
@@ -3366,6 +3401,12 @@ function response(payload) {
|
|
|
3366
3401
|
// Upgrade current session to send back playback information
|
|
3367
3402
|
upgrade("Auto" /* Constant.Auto */);
|
|
3368
3403
|
break;
|
|
3404
|
+
case "ACTION" /* Constant.Action */:
|
|
3405
|
+
// Invoke action callback, if configured and has a valid value
|
|
3406
|
+
if (config$1.action && parts.length > 1) {
|
|
3407
|
+
config$1.action(parts[1]);
|
|
3408
|
+
}
|
|
3409
|
+
break;
|
|
3369
3410
|
}
|
|
3370
3411
|
}
|
|
3371
3412
|
|
|
@@ -3621,7 +3662,7 @@ function encode$1 (event) {
|
|
|
3621
3662
|
tokens.push(b.data.activityTime);
|
|
3622
3663
|
queue(tokens, false);
|
|
3623
3664
|
}
|
|
3624
|
-
reset$
|
|
3665
|
+
reset$p();
|
|
3625
3666
|
break;
|
|
3626
3667
|
case 25 /* Event.Ping */:
|
|
3627
3668
|
tokens.push(data$h.gap);
|
|
@@ -3654,7 +3695,7 @@ function encode$1 (event) {
|
|
|
3654
3695
|
tokens.push(v);
|
|
3655
3696
|
tokens.push(data$e[v]);
|
|
3656
3697
|
}
|
|
3657
|
-
reset$
|
|
3698
|
+
reset$l();
|
|
3658
3699
|
queue(tokens, false);
|
|
3659
3700
|
}
|
|
3660
3701
|
break;
|
|
@@ -3669,7 +3710,7 @@ function encode$1 (event) {
|
|
|
3669
3710
|
// However, for data over the wire, we round it off to milliseconds precision.
|
|
3670
3711
|
tokens.push(Math.round(updates$3[m]));
|
|
3671
3712
|
}
|
|
3672
|
-
reset$
|
|
3713
|
+
reset$o();
|
|
3673
3714
|
queue(tokens, false);
|
|
3674
3715
|
}
|
|
3675
3716
|
break;
|
|
@@ -3695,7 +3736,7 @@ function encode$1 (event) {
|
|
|
3695
3736
|
tokens.push(key);
|
|
3696
3737
|
tokens.push([].concat.apply([], data$g[e]));
|
|
3697
3738
|
}
|
|
3698
|
-
reset$
|
|
3739
|
+
reset$m();
|
|
3699
3740
|
queue(tokens, false);
|
|
3700
3741
|
}
|
|
3701
3742
|
break;
|