clarity-decode 0.8.42 → 0.8.43

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/src/layout.ts CHANGED
@@ -1,186 +1,186 @@
1
- import { Constant } from "@clarity-types/data";
2
- import { Data, Layout } from "clarity-js";
3
- import { DomData, LayoutEvent, Interaction, RegionVisibility } from "../types/layout";
4
-
5
- const AverageWordLength = 6;
6
- const Space = " ";
7
-
8
- export function decode(tokens: Data.Token[]): LayoutEvent {
9
- let time = tokens[0] as number;
10
- let event = tokens[1] as Data.Event;
11
-
12
- switch (event) {
13
- case Data.Event.Document:
14
- let documentData: Layout.DocumentData = { width: tokens[2] as number, height: tokens[3] as number };
15
- return { time, event, data: documentData };
16
- case Data.Event.Region:
17
- let regionData: Layout.RegionData[] = [];
18
- // From 0.6.15 we send each reach update in an individual event. This allows us to include time with it.
19
- // To keep it backward compatible (<= 0.6.14), we look for multiple regions in the same event. This works both with newer and older payloads.
20
- // In future, we can update the logic to look deterministically for only 3 fields and remove the for loop.
21
- let increment: number;
22
- for (let i = 2; i < tokens.length; i += increment) {
23
- let region: Layout.RegionData;
24
- if (typeof(tokens[i+2]) == Constant.Number) {
25
- region = {
26
- id: tokens[i] as number,
27
- interaction: tokens[i + 1] as number,
28
- visibility: tokens[i + 2] as number,
29
- name: tokens[i + 3] as string
30
- };
31
- increment = 4;
32
- } else {
33
- let state = tokens[i + 1] as number;
34
- region = {
35
- id: tokens[i] as number,
36
- // For backward compatibility before 0.6.24 - where region states were sent as a single enum
37
- // we convert the value into the two states tracked after 0.6.24
38
- interaction: state >= Interaction.None ? state : Interaction.None,
39
- visibility: state <= RegionVisibility.ScrolledToEnd ? state : RegionVisibility.Rendered,
40
- name: tokens[i + 2] as string
41
- };
42
- increment = 3;
43
- }
44
- regionData.push(region);
45
- }
46
- return { time, event, data: regionData };
47
- case Data.Event.StyleSheetAdoption:
48
- let styleSheetAdoptionData: Layout.StyleSheetData = {
49
- id: tokens[2] as number,
50
- operation: tokens[3] as number,
51
- newIds: tokens[4] as string[]
52
- };
53
- return { time, event, data: styleSheetAdoptionData };
54
- case Data.Event.StyleSheetUpdate:
55
- let styleSheetUpdateData: Layout.StyleSheetData = {
56
- id: tokens[2] as string,
57
- operation: tokens[3] as number,
58
- cssRules: tokens[4] as string
59
- }
60
- return { time, event, data: styleSheetUpdateData };
61
- case Data.Event.Animation:
62
- let animationData: Layout.AnimationData = {
63
- id: tokens[2] as string,
64
- operation: tokens[3] as number,
65
- keyFrames: tokens[4] as string,
66
- timing: tokens[5] as string,
67
- timeline: tokens[6] as string,
68
- targetId: tokens[7] as number
69
- }
70
- return { time, event, data: animationData};
71
- case Data.Event.Discover:
72
- case Data.Event.Mutation:
73
- case Data.Event.Snapshot:
74
- let lastType = null;
75
- let node = [];
76
- let tagIndex = 0;
77
- let domData: DomData[] = [];
78
- for (let i = 2; i < tokens.length; i++) {
79
- let token = tokens[i];
80
- let type = typeof(token);
81
- switch (type) {
82
- case "number":
83
- if (type !== lastType && lastType !== null) {
84
- domData.push(process(node, tagIndex));
85
- node = [];
86
- tagIndex = 0;
87
- }
88
- node.push(token);
89
- tagIndex++;
90
- break;
91
- case "string":
92
- node.push(token);
93
- break;
94
- case "object":
95
- let subtoken = token[0];
96
- let subtype = typeof(subtoken);
97
- switch (subtype) {
98
- case "number":
99
- for (let t of (token as number[])) {
100
- node.push(tokens.length > t ? tokens[t] : null);
101
- }
102
- break;
103
- }
104
- }
105
- lastType = type;
106
- }
107
- // Process last node
108
- domData.push(process(node, tagIndex));
109
-
110
- return { time, event, data: domData };
111
- case Data.Event.CustomElement:
112
- let customElement: Layout.CustomElementData = { name: tokens[2] as string };
113
- return { time, event, data: customElement };
114
- }
115
- return null;
116
- }
117
-
118
- function process(node: any[] | number[], tagIndex: number): DomData {
119
- // For backward compatibility, only extract the tag even if position is available as part of the tag name
120
- // And, continue computing position in the visualization library from decoded payload.
121
- let tag = node[tagIndex] ? node[tagIndex].split("~")[0] : node[tagIndex];
122
- let output: DomData = {
123
- id: Math.abs(node[0]),
124
- parent: tagIndex > 1 ? node[1] : null,
125
- previous: tagIndex > 2 ? node[2] : null,
126
- tag
127
- };
128
- let masked = node[0] < 0;
129
- let hasAttribute = false;
130
- let attributes: Layout.Attributes = {};
131
- let value = null;
132
-
133
- for (let i = tagIndex + 1; i < node.length; i++) {
134
- // Explicitly convert the token into a string value
135
- let token = node[i].toString();
136
- let keyIndex = token.indexOf("=");
137
- let firstChar = token[0];
138
- let lastChar = token[token.length - 1];
139
- if (i === (node.length - 1) && output.tag === "STYLE") {
140
- value = token;
141
- } else if (output.tag !== Layout.Constant.TextTag && lastChar === ">" && keyIndex === -1) {
142
- // Backward compatibility - since v0.6.25
143
- // Ignore this conditional block since we no longer compute selectors at decode time to save on uploaded bytes
144
- // Instead, we now compute selector and hash at visualization layer where we have access to all payloads together
145
- } else if (output.tag !== Layout.Constant.TextTag && firstChar === Layout.Constant.Hash && keyIndex === -1) {
146
- let parts = token.substr(1).split(Layout.Constant.Period);
147
- if (parts.length === 2) {
148
- output.width = num(parts[0]) / Data.Setting.BoxPrecision;
149
- output.height = num(parts[1]) / Data.Setting.BoxPrecision;
150
- }
151
- } else if (output.tag !== Layout.Constant.TextTag && keyIndex > 0) {
152
- hasAttribute = true;
153
- let k = token.substr(0, keyIndex);
154
- let v = token.substr(keyIndex + 1);
155
- attributes[k] = v;
156
- } else if (output.tag === Layout.Constant.TextTag) {
157
- value = masked ? unmask(token) : token;
158
- }
159
- }
160
-
161
- if (hasAttribute) { output.attributes = attributes; }
162
- if (value) { output.value = value; }
163
-
164
- return output;
165
- }
166
-
167
- function num(input: string): number {
168
- return input ? parseInt(input, 36) : null;
169
- }
170
-
171
- function unmask(value: string): string {
172
- let trimmed = value.trim();
173
- if (trimmed.length > 0 && trimmed.indexOf(Space) === -1) {
174
- let length = num(trimmed);
175
- if (length > 0) {
176
- let quotient = Math.floor(length / AverageWordLength);
177
- let remainder = length % AverageWordLength;
178
- let output = Array(remainder + 1).join(Data.Constant.Mask);
179
- for (let i = 0; i < quotient; i++) {
180
- output += (i === 0 && remainder === 0 ? Data.Constant.Mask : Space) + Array(AverageWordLength).join(Data.Constant.Mask);
181
- }
182
- return output;
183
- }
184
- }
185
- return value;
186
- }
1
+ import { Constant } from "@clarity-types/data";
2
+ import { Data, Layout } from "clarity-js";
3
+ import { DomData, LayoutEvent, Interaction, RegionVisibility } from "../types/layout";
4
+
5
+ const AverageWordLength = 6;
6
+ const Space = " ";
7
+
8
+ export function decode(tokens: Data.Token[]): LayoutEvent {
9
+ let time = tokens[0] as number;
10
+ let event = tokens[1] as Data.Event;
11
+
12
+ switch (event) {
13
+ case Data.Event.Document:
14
+ let documentData: Layout.DocumentData = { width: tokens[2] as number, height: tokens[3] as number };
15
+ return { time, event, data: documentData };
16
+ case Data.Event.Region:
17
+ let regionData: Layout.RegionData[] = [];
18
+ // From 0.6.15 we send each reach update in an individual event. This allows us to include time with it.
19
+ // To keep it backward compatible (<= 0.6.14), we look for multiple regions in the same event. This works both with newer and older payloads.
20
+ // In future, we can update the logic to look deterministically for only 3 fields and remove the for loop.
21
+ let increment: number;
22
+ for (let i = 2; i < tokens.length; i += increment) {
23
+ let region: Layout.RegionData;
24
+ if (typeof(tokens[i+2]) == Constant.Number) {
25
+ region = {
26
+ id: tokens[i] as number,
27
+ interaction: tokens[i + 1] as number,
28
+ visibility: tokens[i + 2] as number,
29
+ name: tokens[i + 3] as string
30
+ };
31
+ increment = 4;
32
+ } else {
33
+ let state = tokens[i + 1] as number;
34
+ region = {
35
+ id: tokens[i] as number,
36
+ // For backward compatibility before 0.6.24 - where region states were sent as a single enum
37
+ // we convert the value into the two states tracked after 0.6.24
38
+ interaction: state >= Interaction.None ? state : Interaction.None,
39
+ visibility: state <= RegionVisibility.ScrolledToEnd ? state : RegionVisibility.Rendered,
40
+ name: tokens[i + 2] as string
41
+ };
42
+ increment = 3;
43
+ }
44
+ regionData.push(region);
45
+ }
46
+ return { time, event, data: regionData };
47
+ case Data.Event.StyleSheetAdoption:
48
+ let styleSheetAdoptionData: Layout.StyleSheetData = {
49
+ id: tokens[2] as number,
50
+ operation: tokens[3] as number,
51
+ newIds: tokens[4] as string[]
52
+ };
53
+ return { time, event, data: styleSheetAdoptionData };
54
+ case Data.Event.StyleSheetUpdate:
55
+ let styleSheetUpdateData: Layout.StyleSheetData = {
56
+ id: tokens[2] as string,
57
+ operation: tokens[3] as number,
58
+ cssRules: tokens[4] as string
59
+ }
60
+ return { time, event, data: styleSheetUpdateData };
61
+ case Data.Event.Animation:
62
+ let animationData: Layout.AnimationData = {
63
+ id: tokens[2] as string,
64
+ operation: tokens[3] as number,
65
+ keyFrames: tokens[4] as string,
66
+ timing: tokens[5] as string,
67
+ timeline: tokens[6] as string,
68
+ targetId: tokens[7] as number
69
+ }
70
+ return { time, event, data: animationData};
71
+ case Data.Event.Discover:
72
+ case Data.Event.Mutation:
73
+ case Data.Event.Snapshot:
74
+ let lastType = null;
75
+ let node = [];
76
+ let tagIndex = 0;
77
+ let domData: DomData[] = [];
78
+ for (let i = 2; i < tokens.length; i++) {
79
+ let token = tokens[i];
80
+ let type = typeof(token);
81
+ switch (type) {
82
+ case "number":
83
+ if (type !== lastType && lastType !== null) {
84
+ domData.push(process(node, tagIndex));
85
+ node = [];
86
+ tagIndex = 0;
87
+ }
88
+ node.push(token);
89
+ tagIndex++;
90
+ break;
91
+ case "string":
92
+ node.push(token);
93
+ break;
94
+ case "object":
95
+ let subtoken = token[0];
96
+ let subtype = typeof(subtoken);
97
+ switch (subtype) {
98
+ case "number":
99
+ for (let t of (token as number[])) {
100
+ node.push(tokens.length > t ? tokens[t] : null);
101
+ }
102
+ break;
103
+ }
104
+ }
105
+ lastType = type;
106
+ }
107
+ // Process last node
108
+ domData.push(process(node, tagIndex));
109
+
110
+ return { time, event, data: domData };
111
+ case Data.Event.CustomElement:
112
+ let customElement: Layout.CustomElementData = { name: tokens[2] as string };
113
+ return { time, event, data: customElement };
114
+ }
115
+ return null;
116
+ }
117
+
118
+ function process(node: any[] | number[], tagIndex: number): DomData {
119
+ // For backward compatibility, only extract the tag even if position is available as part of the tag name
120
+ // And, continue computing position in the visualization library from decoded payload.
121
+ let tag = node[tagIndex] ? node[tagIndex].split("~")[0] : node[tagIndex];
122
+ let output: DomData = {
123
+ id: Math.abs(node[0]),
124
+ parent: tagIndex > 1 ? node[1] : null,
125
+ previous: tagIndex > 2 ? node[2] : null,
126
+ tag
127
+ };
128
+ let masked = node[0] < 0;
129
+ let hasAttribute = false;
130
+ let attributes: Layout.Attributes = {};
131
+ let value = null;
132
+
133
+ for (let i = tagIndex + 1; i < node.length; i++) {
134
+ // Explicitly convert the token into a string value
135
+ let token = node[i].toString();
136
+ let keyIndex = token.indexOf("=");
137
+ let firstChar = token[0];
138
+ let lastChar = token[token.length - 1];
139
+ if (i === (node.length - 1) && output.tag === "STYLE") {
140
+ value = token;
141
+ } else if (output.tag !== Layout.Constant.TextTag && lastChar === ">" && keyIndex === -1) {
142
+ // Backward compatibility - since v0.6.25
143
+ // Ignore this conditional block since we no longer compute selectors at decode time to save on uploaded bytes
144
+ // Instead, we now compute selector and hash at visualization layer where we have access to all payloads together
145
+ } else if (output.tag !== Layout.Constant.TextTag && firstChar === Layout.Constant.Hash && keyIndex === -1) {
146
+ let parts = token.substr(1).split(Layout.Constant.Period);
147
+ if (parts.length === 2) {
148
+ output.width = num(parts[0]) / Data.Setting.BoxPrecision;
149
+ output.height = num(parts[1]) / Data.Setting.BoxPrecision;
150
+ }
151
+ } else if (output.tag !== Layout.Constant.TextTag && keyIndex > 0) {
152
+ hasAttribute = true;
153
+ let k = token.substr(0, keyIndex);
154
+ let v = token.substr(keyIndex + 1);
155
+ attributes[k] = v;
156
+ } else if (output.tag === Layout.Constant.TextTag) {
157
+ value = masked ? unmask(token) : token;
158
+ }
159
+ }
160
+
161
+ if (hasAttribute) { output.attributes = attributes; }
162
+ if (value) { output.value = value; }
163
+
164
+ return output;
165
+ }
166
+
167
+ function num(input: string): number {
168
+ return input ? parseInt(input, 36) : null;
169
+ }
170
+
171
+ function unmask(value: string): string {
172
+ let trimmed = value.trim();
173
+ if (trimmed.length > 0 && trimmed.indexOf(Space) === -1) {
174
+ let length = num(trimmed);
175
+ if (length > 0) {
176
+ let quotient = Math.floor(length / AverageWordLength);
177
+ let remainder = length % AverageWordLength;
178
+ let output = Array(remainder + 1).join(Data.Constant.Mask);
179
+ for (let i = 0; i < quotient; i++) {
180
+ output += (i === 0 && remainder === 0 ? Data.Constant.Mask : Space) + Array(AverageWordLength).join(Data.Constant.Mask);
181
+ }
182
+ return output;
183
+ }
184
+ }
185
+ return value;
186
+ }
@@ -1,30 +1,30 @@
1
- import { Data, Performance } from "clarity-js";
2
- import { PerformanceEvent } from "../types/performance";
3
-
4
- export function decode(tokens: Data.Token[]): PerformanceEvent {
5
- let time = tokens[0] as number;
6
- let event = tokens[1] as Data.Event;
7
- switch (event) {
8
- case Data.Event.Navigation:
9
- let navigationData: Performance.NavigationData = {
10
- fetchStart: tokens[2] as number,
11
- connectStart: tokens[3] as number,
12
- connectEnd: tokens[4] as number,
13
- requestStart: tokens[5] as number,
14
- responseStart: tokens[6] as number,
15
- responseEnd: tokens[7] as number,
16
- domInteractive: tokens[8] as number,
17
- domComplete: tokens[9] as number,
18
- loadEventStart: tokens[10] as number,
19
- loadEventEnd: tokens[11] as number,
20
- redirectCount: tokens[12] as number,
21
- size: tokens[13] as number,
22
- type: tokens[14] as string,
23
- protocol: tokens[15] as string,
24
- encodedSize: tokens[16] as number,
25
- decodedSize: tokens[17] as number
26
- };
27
- return { time, event, data: navigationData };
28
- }
29
- return null;
30
- }
1
+ import { Data, Performance } from "clarity-js";
2
+ import { PerformanceEvent } from "../types/performance";
3
+
4
+ export function decode(tokens: Data.Token[]): PerformanceEvent {
5
+ let time = tokens[0] as number;
6
+ let event = tokens[1] as Data.Event;
7
+ switch (event) {
8
+ case Data.Event.Navigation:
9
+ let navigationData: Performance.NavigationData = {
10
+ fetchStart: tokens[2] as number,
11
+ connectStart: tokens[3] as number,
12
+ connectEnd: tokens[4] as number,
13
+ requestStart: tokens[5] as number,
14
+ responseStart: tokens[6] as number,
15
+ responseEnd: tokens[7] as number,
16
+ domInteractive: tokens[8] as number,
17
+ domComplete: tokens[9] as number,
18
+ loadEventStart: tokens[10] as number,
19
+ loadEventEnd: tokens[11] as number,
20
+ redirectCount: tokens[12] as number,
21
+ size: tokens[13] as number,
22
+ type: tokens[14] as string,
23
+ protocol: tokens[15] as string,
24
+ encodedSize: tokens[16] as number,
25
+ decodedSize: tokens[17] as number
26
+ };
27
+ return { time, event, data: navigationData };
28
+ }
29
+ return null;
30
+ }
package/tsconfig.json CHANGED
@@ -1,21 +1,21 @@
1
- {
2
- "compilerOptions": {
3
- "module": "esnext",
4
- "target": "es5",
5
- "lib": ["es6", "dom", "es2016", "es2017"],
6
- "moduleResolution": "node",
7
- "forceConsistentCasingInFileNames": true,
8
- "noImplicitReturns": true,
9
- "noUnusedLocals": true,
10
- "noUnusedParameters": true,
11
- "resolveJsonModule": true,
12
- "esModuleInterop": true,
13
- "baseUrl": ".",
14
- "paths": {
15
- "@src/*": ["src/*"],
16
- "@clarity-types/*": ["types/*"]
17
- }
18
- },
19
- "include":["src/**/*.ts", "types/**/*.d.ts", "rollup.config.ts"],
20
- "exclude": ["node_modules", "build"]
21
- }
1
+ {
2
+ "compilerOptions": {
3
+ "module": "esnext",
4
+ "target": "es5",
5
+ "lib": ["es6", "dom", "es2016", "es2017"],
6
+ "moduleResolution": "node",
7
+ "forceConsistentCasingInFileNames": true,
8
+ "noImplicitReturns": true,
9
+ "noUnusedLocals": true,
10
+ "noUnusedParameters": true,
11
+ "resolveJsonModule": true,
12
+ "esModuleInterop": true,
13
+ "baseUrl": ".",
14
+ "paths": {
15
+ "@src/*": ["src/*"],
16
+ "@clarity-types/*": ["types/*"]
17
+ }
18
+ },
19
+ "include":["src/**/*.ts", "types/**/*.d.ts", "rollup.config.ts"],
20
+ "exclude": ["node_modules", "build"]
21
+ }
package/tslint.json CHANGED
@@ -1,33 +1,33 @@
1
- {
2
- "extends": "tslint:recommended",
3
- "rules": {
4
- "max-line-length": [
5
- true,
6
- 140
7
- ],
8
- "no-console": [
9
- false
10
- ],
11
- "no-string-literal": false,
12
- "prefer-const": false,
13
- "prefer-for-of": false,
14
- "object-literal-sort-keys": false,
15
- "one-variable-per-declaration": false,
16
- "trailing-comma": [
17
- false
18
- ],
19
- "variable-name": false,
20
- "interface-name": false,
21
- "interface-over-type-literal": false,
22
- "only-arrow-functions": false,
23
- "typedef": [
24
- true,
25
- "call-signature",
26
- "parameter",
27
- "property-declaration",
28
- "member-variable-declaration",
29
- "object-destructuring",
30
- "array-destructuring"
31
- ]
32
- }
1
+ {
2
+ "extends": "tslint:recommended",
3
+ "rules": {
4
+ "max-line-length": [
5
+ true,
6
+ 140
7
+ ],
8
+ "no-console": [
9
+ false
10
+ ],
11
+ "no-string-literal": false,
12
+ "prefer-const": false,
13
+ "prefer-for-of": false,
14
+ "object-literal-sort-keys": false,
15
+ "one-variable-per-declaration": false,
16
+ "trailing-comma": [
17
+ false
18
+ ],
19
+ "variable-name": false,
20
+ "interface-name": false,
21
+ "interface-over-type-literal": false,
22
+ "only-arrow-functions": false,
23
+ "typedef": [
24
+ true,
25
+ "call-signature",
26
+ "parameter",
27
+ "property-declaration",
28
+ "member-variable-declaration",
29
+ "object-destructuring",
30
+ "array-destructuring"
31
+ ]
32
+ }
33
33
  }
package/types/core.d.ts CHANGED
@@ -1,8 +1,8 @@
1
- import { Core, Data } from "clarity-js";
2
-
3
- export import Config = Core.Config;
4
-
5
- export interface PartialEvent {
6
- time: number;
7
- event: Data.Event;
8
- }
1
+ import { Core, Data } from "clarity-js";
2
+
3
+ export import Config = Core.Config;
4
+
5
+ export interface PartialEvent {
6
+ time: number;
7
+ event: Data.Event;
8
+ }