clarity-js 0.7.27 → 0.7.31

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.
@@ -129,19 +129,19 @@ async function process(): Promise<void> {
129
129
  if (state === Task.Wait) { state = await task.suspend(timer); }
130
130
  if (state === Task.Stop) { break; }
131
131
  let target = mutation.target;
132
- let type = track(mutation, timer, instance);
132
+ let type = track(mutation, timer, instance, record.time);
133
133
  if (type && target && target.ownerDocument) { dom.parse(target.ownerDocument); }
134
134
  if (type && target && target.nodeType == Node.DOCUMENT_FRAGMENT_NODE && (target as ShadowRoot).host) { dom.parse(target as ShadowRoot); }
135
135
  switch (type) {
136
136
  case Constant.Attributes:
137
- processNode(target, Source.Attributes);
137
+ processNode(target, Source.Attributes, record.time);
138
138
  break;
139
139
  case Constant.CharacterData:
140
- processNode(target, Source.CharacterData);
140
+ processNode(target, Source.CharacterData, record.time);
141
141
  break;
142
142
  case Constant.ChildList:
143
- processNodeList(mutation.addedNodes, Source.ChildListAdd, timer);
144
- processNodeList(mutation.removedNodes, Source.ChildListRemove, timer);
143
+ processNodeList(mutation.addedNodes, Source.ChildListAdd, timer, record.time);
144
+ processNodeList(mutation.removedNodes, Source.ChildListRemove, timer, record.time);
145
145
  break;
146
146
  case Constant.Suspend:
147
147
  let value = dom.get(target);
@@ -156,7 +156,7 @@ async function process(): Promise<void> {
156
156
  task.stop(timer);
157
157
  }
158
158
 
159
- function track(m: MutationRecord, timer: Timer, instance: number): string {
159
+ function track(m: MutationRecord, timer: Timer, instance: number, timestamp: number): string {
160
160
  let value = m.target ? dom.get(m.target.parentNode) : null;
161
161
  // Check if the parent is already discovered and that the parent is not the document root
162
162
  if (value && value.data.tag !== Constant.HTML) {
@@ -172,7 +172,7 @@ function track(m: MutationRecord, timer: Timer, instance: number): string {
172
172
  history[key] = key in history ? history[key] : [0, instance];
173
173
  let h = history[key];
174
174
  // Lookup any pending nodes queued up for removal, and process them now if we suspended a mutation before
175
- if (inactive === false && h[0] >= Setting.MutationSuspendThreshold) { processNodeList(h[2], Source.ChildListRemove, timer); }
175
+ if (inactive === false && h[0] >= Setting.MutationSuspendThreshold) { processNodeList(h[2], Source.ChildListRemove, timer, timestamp); }
176
176
  // Update the counter
177
177
  h[0] = inactive ? (h[1] === instance ? h[0] : h[0] + 1) : 1;
178
178
  h[1] = instance;
@@ -195,16 +195,16 @@ function names(nodes: NodeList): string {
195
195
  return output.join();
196
196
  }
197
197
 
198
- async function processNodeList(list: NodeList, source: Source, timer: Timer): Promise<void> {
198
+ async function processNodeList(list: NodeList, source: Source, timer: Timer, timestamp: number): Promise<void> {
199
199
  let length = list ? list.length : 0;
200
200
  for (let i = 0; i < length; i++) {
201
201
  if (source === Source.ChildListAdd) {
202
- traverse(list[i], timer, source);
202
+ traverse(list[i], timer, source, timestamp);
203
203
  } else {
204
204
  let state = task.state(timer);
205
205
  if (state === Task.Wait) { state = await task.suspend(timer); }
206
206
  if (state === Task.Stop) { break; }
207
- processNode(list[i], source);
207
+ processNode(list[i], source, timestamp);
208
208
  }
209
209
  }
210
210
  }
@@ -12,7 +12,7 @@ import { electron } from "@src/data/metadata";
12
12
  const IGNORE_ATTRIBUTES = ["title", "alt", "onload", "onfocus", "onerror", "data-drupal-form-submit-last"];
13
13
  const newlineRegex = /[\r\n]+/g;
14
14
 
15
- export default function (node: Node, source: Source): Node {
15
+ export default function (node: Node, source: Source, timestamp: number): Node {
16
16
  let child: Node = null;
17
17
 
18
18
  // Do not track this change if we are attempting to remove a node before discovering it
@@ -43,7 +43,7 @@ export default function (node: Node, source: Source): Node {
43
43
  // We check for regions in the beginning when discovering document and
44
44
  // later whenever there are new additions or modifications to DOM (mutations)
45
45
  if (node === document) dom.parse(document);
46
- checkDocumentStyles(node as Document);
46
+ checkDocumentStyles(node as Document, timestamp);
47
47
  observe(node);
48
48
  break;
49
49
  case Node.DOCUMENT_FRAGMENT_NODE:
@@ -67,7 +67,7 @@ export default function (node: Node, source: Source): Node {
67
67
  // the same way we observe real shadow DOM nodes (encapsulation provided by the browser).
68
68
  dom[call](node, shadowRoot.host, { tag: Constant.PolyfillShadowDomTag, attributes: {} }, source);
69
69
  }
70
- checkDocumentStyles(node as Document);
70
+ checkDocumentStyles(node as Document, timestamp);
71
71
  }
72
72
  break;
73
73
  case Node.TEXT_NODE:
@@ -187,7 +187,7 @@ export default function (node: Node, source: Source): Node {
187
187
  case "SOURCE":
188
188
  // Ignoring any base64 src attribute for media elements to prevent big unused tokens to be sent and shock the network
189
189
  if (Constant.Src in attributes && attributes[Constant.Src].startsWith("data:")) {
190
- delete attributes[Constant.Src]
190
+ attributes[Constant.Src] = "";
191
191
  }
192
192
  let mediaTag = { tag, attributes };
193
193
  dom[call](node, parent, mediaTag, source);
@@ -14,6 +14,7 @@ let replaceSync: (text?: string) => void = null;
14
14
  const styleSheetId = 'claritySheetId';
15
15
  const styleSheetPageNum = 'claritySheetNum';
16
16
  let styleSheetMap = {};
17
+ let styleTimeMap: {[key: string]: number} = {};
17
18
 
18
19
  export function start(): void {
19
20
  reset();
@@ -56,7 +57,8 @@ function bootStrapStyleSheet(styleSheet: CSSStyleSheet): void {
56
57
  }
57
58
  }
58
59
 
59
- export function checkDocumentStyles(documentNode: Document): void {
60
+ export function checkDocumentStyles(documentNode: Document, timestamp: number): void {
61
+ timestamp = timestamp || time();
60
62
  if (!documentNode?.adoptedStyleSheets) {
61
63
  // if we don't have adoptedStyledSheets on the Node passed to us, we can short circuit.
62
64
  return;
@@ -69,8 +71,8 @@ export function checkDocumentStyles(documentNode: Document): void {
69
71
  if (styleSheet[styleSheetPageNum] !== pageNum) {
70
72
  styleSheet[styleSheetPageNum] = pageNum;
71
73
  styleSheet[styleSheetId] = shortid();
72
- trackStyleChange(time(), styleSheet[styleSheetId], StyleSheetOperation.Create);
73
- trackStyleChange(time(), styleSheet[styleSheetId], StyleSheetOperation.ReplaceSync, getCssRules(styleSheet));
74
+ trackStyleChange(timestamp, styleSheet[styleSheetId], StyleSheetOperation.Create);
75
+ trackStyleChange(timestamp, styleSheet[styleSheetId], StyleSheetOperation.ReplaceSync, getCssRules(styleSheet));
74
76
  }
75
77
  currentStyleSheets.push(styleSheet[styleSheetId]);
76
78
  }
@@ -81,14 +83,16 @@ export function checkDocumentStyles(documentNode: Document): void {
81
83
  }
82
84
  if (!arraysEqual(currentStyleSheets, styleSheetMap[documentId])) {
83
85
  // Using -1 to signify the root document node as we don't track that as part of our nodeMap
84
- trackStyleAdoption(time(), documentNode == document ? -1 : getId(documentNode), StyleSheetOperation.SetAdoptedStyles, currentStyleSheets);
86
+ trackStyleAdoption(timestamp, documentNode == document ? -1 : getId(documentNode), StyleSheetOperation.SetAdoptedStyles, currentStyleSheets);
85
87
  styleSheetMap[documentId] = currentStyleSheets;
88
+ styleTimeMap[documentId] = timestamp;
86
89
  }
87
90
  }
88
91
 
89
92
  export function compute(): void {
90
- checkDocumentStyles(document);
91
- Object.keys(styleSheetMap).forEach((x) => checkDocumentStyles(getNode(parseInt(x, 10)) as Document));
93
+ let ts = -1 in styleTimeMap ? styleTimeMap[-1] : null;
94
+ checkDocumentStyles(document, ts);
95
+ Object.keys(styleSheetMap).forEach((x) => checkDocumentStyles(getNode(parseInt(x, 10)) as Document, styleTimeMap[x]));
92
96
  }
93
97
 
94
98
  export function reset(): void {
@@ -97,6 +101,7 @@ export function reset(): void {
97
101
 
98
102
  export function stop(): void {
99
103
  styleSheetMap = {};
104
+ styleTimeMap = {};
100
105
  reset();
101
106
  }
102
107
 
@@ -3,7 +3,7 @@ import { Source } from "@clarity-types/layout";
3
3
  import * as task from "@src/core/task";
4
4
  import node from "@src/layout/node";
5
5
 
6
- export default async function(root: Node, timer: Timer, source: Source): Promise<void> {
6
+ export default async function(root: Node, timer: Timer, source: Source, timestamp: number): Promise<void> {
7
7
  let queue = [root];
8
8
  while (queue.length > 0) {
9
9
  let entry = queue.shift();
@@ -22,7 +22,7 @@ export default async function(root: Node, timer: Timer, source: Source): Promise
22
22
  // Check if processing a node gives us a pointer to one of its sub nodes for traversal
23
23
  // E.g. an element node may give us a pointer to traverse shadowDom if shadowRoot property is set
24
24
  // Or, an iframe from the same origin could give a pointer to it's document for traversing contents of iframe.
25
- let subnode = node(entry, source);
25
+ let subnode = node(entry, source, timestamp);
26
26
  if (subnode) { queue.push(subnode); }
27
27
  }
28
28
  }
package/types/core.d.ts CHANGED
@@ -137,6 +137,7 @@ export interface Config {
137
137
  upgrade?: (key: string) => void;
138
138
  action?: (key: string) => void;
139
139
  dob?: number;
140
+ delayDom?: boolean;
140
141
  }
141
142
 
142
143
  export const enum Constant {
package/types/data.d.ts CHANGED
@@ -8,6 +8,7 @@ export interface MetadataCallbackOptions {
8
8
  callback: MetadataCallback,
9
9
  wait: boolean
10
10
  }
11
+ export type SignalCallback = (data: ClaritySignal) => void
11
12
 
12
13
  /* Enum */
13
14
  export const enum Event {
@@ -278,6 +279,7 @@ export const enum Constant {
278
279
  End = "END",
279
280
  Upgrade = "UPGRADE",
280
281
  Action = "ACTION",
282
+ Signal = "SIGNAL",
281
283
  Extract = "EXTRACT",
282
284
  UserHint = "userHint",
283
285
  UserType = "userType",
@@ -389,6 +391,7 @@ export interface BaselineData {
389
391
  pointerX: number;
390
392
  pointerY: number;
391
393
  activityTime: number;
394
+ scrollTime: number;
392
395
  }
393
396
 
394
397
  export interface IdentityData {
@@ -444,3 +447,8 @@ export interface UploadData {
444
447
  attempts: number;
445
448
  status: number;
446
449
  }
450
+
451
+ export interface ClaritySignal {
452
+ type: string
453
+ value?: number
454
+ }
package/types/index.d.ts CHANGED
@@ -16,6 +16,7 @@ interface Clarity {
16
16
  set: (variable: string, value: string | string[]) => void;
17
17
  identify: (userId: string, sessionId?: string, pageId?: string, userHint?: string) => void;
18
18
  metadata: (callback: Data.MetadataCallback, wait?: boolean) => void;
19
+ signal: (callback: Data.SignalCallback) => void;
19
20
  }
20
21
 
21
22
  interface Selector {
@@ -134,6 +134,8 @@ export interface ScrollData {
134
134
  target: Target;
135
135
  x: number;
136
136
  y: number;
137
+ top: string;
138
+ bottom: string;
137
139
  }
138
140
 
139
141
  export interface SelectionData {