posthog-js 1.76.0 → 1.77.1

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.
Files changed (129) hide show
  1. package/dist/array.full.js +2 -2
  2. package/dist/array.full.js.map +1 -1
  3. package/dist/array.js +2 -2
  4. package/dist/array.js.map +1 -1
  5. package/dist/es.js +2 -2
  6. package/dist/es.js.map +1 -1
  7. package/dist/module.d.ts +38 -6
  8. package/dist/module.js +2 -2
  9. package/dist/module.js.map +1 -1
  10. package/lib/package.json +8 -6
  11. package/lib/src/autocapture-utils.d.ts +15 -0
  12. package/lib/src/autocapture-utils.js +303 -0
  13. package/lib/src/autocapture-utils.js.map +1 -0
  14. package/lib/src/autocapture.d.ts +27 -0
  15. package/lib/src/autocapture.js +290 -0
  16. package/lib/src/autocapture.js.map +1 -0
  17. package/lib/src/base-request-queue.d.ts +12 -0
  18. package/lib/src/base-request-queue.js +33 -0
  19. package/lib/src/base-request-queue.js.map +1 -0
  20. package/lib/src/compression.d.ts +3 -0
  21. package/lib/src/compression.js +35 -0
  22. package/lib/src/compression.js.map +1 -0
  23. package/lib/src/config.d.ts +5 -0
  24. package/lib/src/config.js +9 -0
  25. package/lib/src/config.js.map +1 -0
  26. package/lib/src/constants.d.ts +19 -0
  27. package/lib/src/constants.js +41 -0
  28. package/lib/src/constants.js.map +1 -0
  29. package/lib/src/decide.d.ts +8 -0
  30. package/lib/src/decide.js +118 -0
  31. package/lib/src/decide.js.map +1 -0
  32. package/lib/src/extensions/cloud.d.ts +1 -0
  33. package/lib/src/extensions/cloud.js +2 -0
  34. package/lib/src/extensions/cloud.js.map +1 -0
  35. package/lib/src/extensions/exceptions/error-conversion.d.ts +26 -0
  36. package/lib/src/extensions/exceptions/error-conversion.js +204 -0
  37. package/lib/src/extensions/exceptions/error-conversion.js.map +1 -0
  38. package/lib/src/extensions/exceptions/exception-autocapture.d.ts +24 -0
  39. package/lib/src/extensions/exceptions/exception-autocapture.js +164 -0
  40. package/lib/src/extensions/exceptions/exception-autocapture.js.map +1 -0
  41. package/lib/src/extensions/exceptions/stack-trace.d.ts +31 -0
  42. package/lib/src/extensions/exceptions/stack-trace.js +259 -0
  43. package/lib/src/extensions/exceptions/stack-trace.js.map +1 -0
  44. package/lib/src/extensions/exceptions/type-checking.d.ts +10 -0
  45. package/lib/src/extensions/exceptions/type-checking.js +43 -0
  46. package/lib/src/extensions/exceptions/type-checking.js.map +1 -0
  47. package/lib/src/extensions/rageclick.d.ts +10 -0
  48. package/lib/src/extensions/rageclick.js +33 -0
  49. package/lib/src/extensions/rageclick.js.map +1 -0
  50. package/lib/src/extensions/segment-integration.d.ts +44 -0
  51. package/lib/src/extensions/segment-integration.js +34 -0
  52. package/lib/src/extensions/segment-integration.js.map +1 -0
  53. package/lib/src/extensions/sentry-integration.d.ts +30 -0
  54. package/lib/src/extensions/sentry-integration.js +63 -0
  55. package/lib/src/extensions/sentry-integration.js.map +1 -0
  56. package/lib/src/extensions/sessionrecording-utils.d.ts +67 -0
  57. package/lib/src/extensions/sessionrecording-utils.js +192 -0
  58. package/lib/src/extensions/sessionrecording-utils.js.map +1 -0
  59. package/lib/src/extensions/sessionrecording.d.ts +45 -0
  60. package/lib/src/extensions/sessionrecording.js +430 -0
  61. package/lib/src/extensions/sessionrecording.js.map +1 -0
  62. package/lib/src/extensions/toolbar.d.ts +18 -0
  63. package/lib/src/extensions/toolbar.js +151 -0
  64. package/lib/src/extensions/toolbar.js.map +1 -0
  65. package/lib/src/extensions/web-performance.d.ts +20 -0
  66. package/lib/src/extensions/web-performance.js +245 -0
  67. package/lib/src/extensions/web-performance.js.map +1 -0
  68. package/lib/src/gdpr-utils.d.ts +80 -0
  69. package/lib/src/gdpr-utils.js +236 -0
  70. package/lib/src/gdpr-utils.js.map +1 -0
  71. package/lib/src/loader-globals-full.d.ts +1 -0
  72. package/lib/src/loader-globals-full.js +5 -0
  73. package/lib/src/loader-globals-full.js.map +1 -0
  74. package/lib/src/loader-globals.d.ts +1 -0
  75. package/lib/src/loader-globals.js +3 -0
  76. package/lib/src/loader-globals.js.map +1 -0
  77. package/lib/src/loader-module.d.ts +4 -0
  78. package/lib/src/loader-module.js +6 -0
  79. package/lib/src/loader-module.js.map +1 -0
  80. package/lib/src/loader-recorder-v2.d.ts +2 -0
  81. package/lib/src/loader-recorder-v2.js +15 -0
  82. package/lib/src/loader-recorder-v2.js.map +1 -0
  83. package/lib/src/loader-recorder.d.ts +2 -0
  84. package/lib/src/loader-recorder.js +15 -0
  85. package/lib/src/loader-recorder.js.map +1 -0
  86. package/lib/src/page-view.d.ts +38 -0
  87. package/lib/src/page-view.js +127 -0
  88. package/lib/src/page-view.js.map +1 -0
  89. package/lib/src/posthog-core.d.ts +701 -0
  90. package/lib/src/posthog-core.js +1916 -0
  91. package/lib/src/posthog-core.js.map +1 -0
  92. package/lib/src/posthog-featureflags.d.ts +70 -0
  93. package/lib/src/posthog-featureflags.js +438 -0
  94. package/lib/src/posthog-featureflags.js.map +1 -0
  95. package/lib/src/posthog-persistence.d.ts +57 -0
  96. package/lib/src/posthog-persistence.js +256 -0
  97. package/lib/src/posthog-persistence.js.map +1 -0
  98. package/lib/src/posthog-surveys.d.ts +57 -0
  99. package/lib/src/posthog-surveys.js +76 -0
  100. package/lib/src/posthog-surveys.js.map +1 -0
  101. package/lib/src/rate-limiter.d.ts +5 -0
  102. package/lib/src/rate-limiter.js +66 -0
  103. package/lib/src/rate-limiter.js.map +1 -0
  104. package/lib/src/request-queue.d.ts +10 -0
  105. package/lib/src/request-queue.js +146 -0
  106. package/lib/src/request-queue.js.map +1 -0
  107. package/lib/src/retry-queue.d.ts +28 -0
  108. package/lib/src/retry-queue.js +198 -0
  109. package/lib/src/retry-queue.js.map +1 -0
  110. package/lib/src/send-request.d.ts +6 -0
  111. package/lib/src/send-request.js +125 -0
  112. package/lib/src/send-request.js.map +1 -0
  113. package/lib/src/sessionid.d.ts +28 -0
  114. package/lib/src/sessionid.js +205 -0
  115. package/lib/src/sessionid.js.map +1 -0
  116. package/lib/src/storage.d.ts +7 -0
  117. package/lib/src/storage.js +291 -0
  118. package/lib/src/storage.js.map +1 -0
  119. package/lib/src/types.d.ts +294 -0
  120. package/lib/src/types.js +6 -0
  121. package/lib/src/types.js.map +1 -0
  122. package/lib/src/utils.d.ts +89 -0
  123. package/lib/src/utils.js +868 -0
  124. package/lib/src/utils.js.map +1 -0
  125. package/lib/src/uuidv7.d.ts +42 -0
  126. package/lib/src/uuidv7.js +228 -0
  127. package/lib/src/uuidv7.js.map +1 -0
  128. package/package.json +8 -6
  129. package/CHANGELOG.md +0 -1145
package/lib/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "posthog-js",
3
- "version": "1.76.0",
3
+ "version": "1.77.1",
4
4
  "description": "Posthog-js allows you to automatically capture usage and send events to PostHog.",
5
5
  "repository": "https://github.com/PostHog/posthog-js",
6
6
  "author": "hey@posthog.com",
@@ -46,14 +46,15 @@
46
46
  "@types/jest": "^29.5.1",
47
47
  "@types/react-dom": "^18.0.10",
48
48
  "@types/uuid": "^9.0.1",
49
- "@typescript-eslint/eslint-plugin": "^5.30.7",
50
- "@typescript-eslint/parser": "^5.30.7",
49
+ "@typescript-eslint/eslint-plugin": "^6.4.0",
50
+ "@typescript-eslint/parser": "^6.4.0",
51
51
  "babel-eslint": "10.1.0",
52
52
  "babel-jest": "^26.6.3",
53
53
  "cypress": "10.3.1",
54
54
  "eslint": "8.20.0",
55
55
  "eslint-config-prettier": "^8.5.0",
56
56
  "eslint-plugin-compat": "^4.1.4",
57
+ "eslint-plugin-jest": "^27.2.3",
57
58
  "eslint-plugin-prettier": "^4.2.1",
58
59
  "eslint-plugin-react": "^7.30.1",
59
60
  "eslint-plugin-react-hooks": "^4.6.0",
@@ -77,10 +78,11 @@
77
78
  "rrweb-snapshot": "2.0.0-alpha.8",
78
79
  "rrweb-v1": "npm:rrweb@1.1.3",
79
80
  "sinon": "9.0.2",
80
- "testcafe": "^1.19.0",
81
- "testcafe-browser-provider-browserstack": "^1.14.0",
81
+ "testcafe": "1.19.0",
82
+ "testcafe-browser-provider-browserstack": "1.14.0",
82
83
  "tslib": "^2.4.0",
83
- "typescript": "^4.7.4"
84
+ "typescript": "^4.7.4",
85
+ "yargs": "^17.7.2"
84
86
  },
85
87
  "lint-staged": {
86
88
  "*.{ts,tsx,js,json}": "prettier --write",
@@ -0,0 +1,15 @@
1
+ import { AutocaptureConfig } from 'types';
2
+ export declare function getClassName(el: Element): string;
3
+ export declare function getSafeText(el: Element): string;
4
+ export declare function isElementNode(el: Element | undefined | null): el is HTMLElement;
5
+ export declare function isTag(el: Element | undefined | null, tag: string): el is HTMLElement;
6
+ export declare function isTextNode(el: Element | undefined | null): el is HTMLElement;
7
+ export declare function isDocumentFragment(el: Element | ParentNode | undefined | null): el is DocumentFragment;
8
+ export declare const autocaptureCompatibleElements: string[];
9
+ export declare function shouldCaptureDomEvent(el: Element, event: Event, autocaptureConfig?: AutocaptureConfig | undefined): boolean;
10
+ export declare function shouldCaptureElement(el: Element): boolean;
11
+ export declare function isSensitiveElement(el: Element): boolean;
12
+ export declare function shouldCaptureValue(value: string): boolean;
13
+ export declare function isAngularStyleAttr(attributeName: string): boolean;
14
+ export declare function getDirectAndNestedSpanText(target: Element): string;
15
+ export declare function getNestedSpanText(target: Element): string;
@@ -0,0 +1,303 @@
1
+ import { _each, _includes, _isUndefined, _trim } from './utils';
2
+ export function getClassName(el) {
3
+ switch (typeof el.className) {
4
+ case 'string':
5
+ return el.className;
6
+ // TODO: when is this ever used?
7
+ case 'object': // handle cases where className might be SVGAnimatedString or some other type
8
+ return ('baseVal' in el.className ? el.className.baseVal : null) || el.getAttribute('class') || '';
9
+ default:
10
+ // future proof
11
+ return '';
12
+ }
13
+ }
14
+ /*
15
+ * Get the direct text content of an element, protecting against sensitive data collection.
16
+ * Concats textContent of each of the element's text node children; this avoids potential
17
+ * collection of sensitive data that could happen if we used element.textContent and the
18
+ * element had sensitive child elements, since element.textContent includes child content.
19
+ * Scrubs values that look like they could be sensitive (i.e. cc or ssn number).
20
+ * @param {Element} el - element to get the text of
21
+ * @returns {string} the element's direct text content
22
+ */
23
+ export function getSafeText(el) {
24
+ var elText = '';
25
+ if (shouldCaptureElement(el) && !isSensitiveElement(el) && el.childNodes && el.childNodes.length) {
26
+ _each(el.childNodes, function (child) {
27
+ if (isTextNode(child) && child.textContent) {
28
+ elText += _trim(child.textContent)
29
+ // scrub potentially sensitive values
30
+ .split(/(\s+)/)
31
+ .filter(shouldCaptureValue)
32
+ .join('')
33
+ // normalize whitespace
34
+ .replace(/[\r\n]/g, ' ')
35
+ .replace(/[ ]+/g, ' ')
36
+ // truncate
37
+ .substring(0, 255);
38
+ }
39
+ });
40
+ }
41
+ return _trim(elText);
42
+ }
43
+ /*
44
+ * Check whether an element has nodeType Node.ELEMENT_NODE
45
+ * @param {Element} el - element to check
46
+ * @returns {boolean} whether el is of the correct nodeType
47
+ */
48
+ export function isElementNode(el) {
49
+ return !!el && el.nodeType === 1; // Node.ELEMENT_NODE - use integer constant for browser portability
50
+ }
51
+ /*
52
+ * Check whether an element is of a given tag type.
53
+ * Due to potential reference discrepancies (such as the webcomponents.js polyfill),
54
+ * we want to match tagNames instead of specific references because something like
55
+ * element === document.body won't always work because element might not be a native
56
+ * element.
57
+ * @param {Element} el - element to check
58
+ * @param {string} tag - tag name (e.g., "div")
59
+ * @returns {boolean} whether el is of the given tag type
60
+ */
61
+ export function isTag(el, tag) {
62
+ return !!el && !!el.tagName && el.tagName.toLowerCase() === tag.toLowerCase();
63
+ }
64
+ /*
65
+ * Check whether an element has nodeType Node.TEXT_NODE
66
+ * @param {Element} el - element to check
67
+ * @returns {boolean} whether el is of the correct nodeType
68
+ */
69
+ export function isTextNode(el) {
70
+ return !!el && el.nodeType === 3; // Node.TEXT_NODE - use integer constant for browser portability
71
+ }
72
+ /*
73
+ * Check whether an element has nodeType Node.DOCUMENT_FRAGMENT_NODE
74
+ * @param {Element} el - element to check
75
+ * @returns {boolean} whether el is of the correct nodeType
76
+ */
77
+ export function isDocumentFragment(el) {
78
+ return !!el && el.nodeType === 11; // Node.DOCUMENT_FRAGMENT_NODE - use integer constant for browser portability
79
+ }
80
+ export var autocaptureCompatibleElements = ['a', 'button', 'form', 'input', 'select', 'textarea', 'label'];
81
+ /*
82
+ * Check whether a DOM event should be "captured" or if it may contain sentitive data
83
+ * using a variety of heuristics.
84
+ * @param {Element} el - element to check
85
+ * @param {Event} event - event to check
86
+ * @param {Object} autocaptureConfig - autocapture config
87
+ * @returns {boolean} whether the event should be captured
88
+ */
89
+ export function shouldCaptureDomEvent(el, event, autocaptureConfig) {
90
+ if (autocaptureConfig === void 0) { autocaptureConfig = undefined; }
91
+ if (!el || isTag(el, 'html') || !isElementNode(el)) {
92
+ return false;
93
+ }
94
+ if (autocaptureConfig === null || autocaptureConfig === void 0 ? void 0 : autocaptureConfig.url_allowlist) {
95
+ var url_1 = window.location.href;
96
+ var allowlist = autocaptureConfig.url_allowlist;
97
+ if (allowlist && !allowlist.some(function (regex) { return url_1.match(regex); })) {
98
+ return false;
99
+ }
100
+ }
101
+ if (autocaptureConfig === null || autocaptureConfig === void 0 ? void 0 : autocaptureConfig.dom_event_allowlist) {
102
+ var allowlist = autocaptureConfig.dom_event_allowlist;
103
+ if (allowlist && !allowlist.some(function (eventType) { return event.type === eventType; })) {
104
+ return false;
105
+ }
106
+ }
107
+ if (autocaptureConfig === null || autocaptureConfig === void 0 ? void 0 : autocaptureConfig.element_allowlist) {
108
+ var allowlist = autocaptureConfig.element_allowlist;
109
+ if (allowlist && !allowlist.some(function (elementType) { return el.tagName.toLowerCase() === elementType; })) {
110
+ return false;
111
+ }
112
+ }
113
+ if (autocaptureConfig === null || autocaptureConfig === void 0 ? void 0 : autocaptureConfig.css_selector_allowlist) {
114
+ var allowlist = autocaptureConfig.css_selector_allowlist;
115
+ if (allowlist && !allowlist.some(function (selector) { return el.matches(selector); })) {
116
+ return false;
117
+ }
118
+ }
119
+ var parentIsUsefulElement = false;
120
+ var targetElementList = [el]; // TODO: remove this var, it's never queried
121
+ var parentNode = true;
122
+ var curEl = el;
123
+ while (curEl.parentNode && !isTag(curEl, 'body')) {
124
+ // If element is a shadow root, we skip it
125
+ if (isDocumentFragment(curEl.parentNode)) {
126
+ targetElementList.push(curEl.parentNode.host);
127
+ curEl = curEl.parentNode.host;
128
+ continue;
129
+ }
130
+ parentNode = curEl.parentNode || false;
131
+ if (!parentNode)
132
+ break;
133
+ if (autocaptureCompatibleElements.indexOf(parentNode.tagName.toLowerCase()) > -1) {
134
+ parentIsUsefulElement = true;
135
+ }
136
+ else {
137
+ var compStyles_1 = window.getComputedStyle(parentNode);
138
+ if (compStyles_1 && compStyles_1.getPropertyValue('cursor') === 'pointer') {
139
+ parentIsUsefulElement = true;
140
+ }
141
+ }
142
+ targetElementList.push(parentNode);
143
+ curEl = parentNode;
144
+ }
145
+ var compStyles = window.getComputedStyle(el);
146
+ if (compStyles && compStyles.getPropertyValue('cursor') === 'pointer' && event.type === 'click') {
147
+ return true;
148
+ }
149
+ var tag = el.tagName.toLowerCase();
150
+ switch (tag) {
151
+ case 'html':
152
+ return false;
153
+ case 'form':
154
+ return event.type === 'submit';
155
+ case 'input':
156
+ return event.type === 'change' || event.type === 'click';
157
+ case 'select':
158
+ case 'textarea':
159
+ return event.type === 'change' || event.type === 'click';
160
+ default:
161
+ if (parentIsUsefulElement)
162
+ return event.type === 'click';
163
+ return (event.type === 'click' &&
164
+ (autocaptureCompatibleElements.indexOf(tag) > -1 || el.getAttribute('contenteditable') === 'true'));
165
+ }
166
+ }
167
+ /*
168
+ * Check whether a DOM element should be "captured" or if it may contain sentitive data
169
+ * using a variety of heuristics.
170
+ * @param {Element} el - element to check
171
+ * @returns {boolean} whether the element should be captured
172
+ */
173
+ export function shouldCaptureElement(el) {
174
+ for (var curEl = el; curEl.parentNode && !isTag(curEl, 'body'); curEl = curEl.parentNode) {
175
+ var classes = getClassName(curEl).split(' ');
176
+ if (_includes(classes, 'ph-sensitive') || _includes(classes, 'ph-no-capture')) {
177
+ return false;
178
+ }
179
+ }
180
+ if (_includes(getClassName(el).split(' '), 'ph-include')) {
181
+ return true;
182
+ }
183
+ // don't include hidden or password fields
184
+ var type = el.type || '';
185
+ if (typeof type === 'string') {
186
+ // it's possible for el.type to be a DOM element if el is a form with a child input[name="type"]
187
+ switch (type.toLowerCase()) {
188
+ case 'hidden':
189
+ return false;
190
+ case 'password':
191
+ return false;
192
+ }
193
+ }
194
+ // filter out data from fields that look like sensitive fields
195
+ var name = el.name || el.id || '';
196
+ // See https://github.com/posthog/posthog-js/issues/165
197
+ // Under specific circumstances a bug caused .replace to be called on a DOM element
198
+ // instead of a string, removing the element from the page. Ensure this issue is mitigated.
199
+ if (typeof name === 'string') {
200
+ // it's possible for el.name or el.id to be a DOM element if el is a form with a child input[name="name"]
201
+ var sensitiveNameRegex = /^cc|cardnum|ccnum|creditcard|csc|cvc|cvv|exp|pass|pwd|routing|seccode|securitycode|securitynum|socialsec|socsec|ssn/i;
202
+ if (sensitiveNameRegex.test(name.replace(/[^a-zA-Z0-9]/g, ''))) {
203
+ return false;
204
+ }
205
+ }
206
+ return true;
207
+ }
208
+ /*
209
+ * Check whether a DOM element is 'sensitive' and we should only capture limited data
210
+ * @param {Element} el - element to check
211
+ * @returns {boolean} whether the element should be captured
212
+ */
213
+ export function isSensitiveElement(el) {
214
+ // don't send data from inputs or similar elements since there will always be
215
+ // a risk of clientside javascript placing sensitive data in attributes
216
+ var allowedInputTypes = ['button', 'checkbox', 'submit', 'reset'];
217
+ if ((isTag(el, 'input') && !allowedInputTypes.includes(el.type)) ||
218
+ isTag(el, 'select') ||
219
+ isTag(el, 'textarea') ||
220
+ el.getAttribute('contenteditable') === 'true') {
221
+ return true;
222
+ }
223
+ return false;
224
+ }
225
+ /*
226
+ * Check whether a string value should be "captured" or if it may contain sentitive data
227
+ * using a variety of heuristics.
228
+ * @param {string} value - string value to check
229
+ * @returns {boolean} whether the element should be captured
230
+ */
231
+ export function shouldCaptureValue(value) {
232
+ if (value === null || _isUndefined(value)) {
233
+ return false;
234
+ }
235
+ if (typeof value === 'string') {
236
+ value = _trim(value);
237
+ // check to see if input value looks like a credit card number
238
+ // see: https://www.safaribooksonline.com/library/view/regular-expressions-cookbook/9781449327453/ch04s20.html
239
+ var ccRegex = /^(?:(4[0-9]{12}(?:[0-9]{3})?)|(5[1-5][0-9]{14})|(6(?:011|5[0-9]{2})[0-9]{12})|(3[47][0-9]{13})|(3(?:0[0-5]|[68][0-9])[0-9]{11})|((?:2131|1800|35[0-9]{3})[0-9]{11}))$/;
240
+ if (ccRegex.test((value || '').replace(/[- ]/g, ''))) {
241
+ return false;
242
+ }
243
+ // check to see if input value looks like a social security number
244
+ var ssnRegex = /(^\d{3}-?\d{2}-?\d{4}$)/;
245
+ if (ssnRegex.test(value)) {
246
+ return false;
247
+ }
248
+ }
249
+ return true;
250
+ }
251
+ /*
252
+ * Check whether an attribute name is an Angular style attr (either _ngcontent or _nghost)
253
+ * These update on each build and lead to noise in the element chain
254
+ * More details on the attributes here: https://angular.io/guide/view-encapsulation
255
+ * @param {string} attributeName - string value to check
256
+ * @returns {boolean} whether the element is an angular tag
257
+ */
258
+ export function isAngularStyleAttr(attributeName) {
259
+ if (typeof attributeName === 'string') {
260
+ return attributeName.substring(0, 10) === '_ngcontent' || attributeName.substring(0, 7) === '_nghost';
261
+ }
262
+ return false;
263
+ }
264
+ /*
265
+ * Iterate through children of a target element looking for span tags
266
+ * and return the text content of the span tags, separated by spaces,
267
+ * along with the direct text content of the target element
268
+ * @param {Element} target - element to check
269
+ * @returns {string} text content of the target element and its child span tags
270
+ */
271
+ export function getDirectAndNestedSpanText(target) {
272
+ var text = getSafeText(target);
273
+ text = "".concat(text, " ").concat(getNestedSpanText(target)).trim();
274
+ return shouldCaptureValue(text) ? text : '';
275
+ }
276
+ /*
277
+ * Iterate through children of a target element looking for span tags
278
+ * and return the text content of the span tags, separated by spaces
279
+ * @param {Element} target - element to check
280
+ * @returns {string} text content of span tags
281
+ */
282
+ export function getNestedSpanText(target) {
283
+ var text = '';
284
+ if (target && target.childNodes && target.childNodes.length) {
285
+ _each(target.childNodes, function (child) {
286
+ var _a;
287
+ if (child && ((_a = child.tagName) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === 'span') {
288
+ try {
289
+ var spanText = getSafeText(child);
290
+ text = "".concat(text, " ").concat(spanText).trim();
291
+ if (child.childNodes && child.childNodes.length) {
292
+ text = "".concat(text, " ").concat(getNestedSpanText(child)).trim();
293
+ }
294
+ }
295
+ catch (e) {
296
+ console.error(e);
297
+ }
298
+ }
299
+ });
300
+ }
301
+ return text;
302
+ }
303
+ //# sourceMappingURL=autocapture-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"autocapture-utils.js","sourceRoot":"","sources":["../../src/autocapture-utils.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Get the className of an element, accounting for edge cases where element.className is an object\n * @param {Element} el - element to get the className of\n * @returns {string} the element's class\n */\nimport { AutocaptureConfig } from 'types'\nimport { _each, _includes, _isUndefined, _trim } from './utils'\n\nexport function getClassName(el: Element): string {\n switch (typeof el.className) {\n case 'string':\n return el.className\n // TODO: when is this ever used?\n case 'object': // handle cases where className might be SVGAnimatedString or some other type\n return ('baseVal' in el.className ? (el.className as any).baseVal : null) || el.getAttribute('class') || ''\n default:\n // future proof\n return ''\n }\n}\n\n/*\n * Get the direct text content of an element, protecting against sensitive data collection.\n * Concats textContent of each of the element's text node children; this avoids potential\n * collection of sensitive data that could happen if we used element.textContent and the\n * element had sensitive child elements, since element.textContent includes child content.\n * Scrubs values that look like they could be sensitive (i.e. cc or ssn number).\n * @param {Element} el - element to get the text of\n * @returns {string} the element's direct text content\n */\nexport function getSafeText(el: Element): string {\n let elText = ''\n\n if (shouldCaptureElement(el) && !isSensitiveElement(el) && el.childNodes && el.childNodes.length) {\n _each(el.childNodes, function (child) {\n if (isTextNode(child) && child.textContent) {\n elText += _trim(child.textContent)\n // scrub potentially sensitive values\n .split(/(\\s+)/)\n .filter(shouldCaptureValue)\n .join('')\n // normalize whitespace\n .replace(/[\\r\\n]/g, ' ')\n .replace(/[ ]+/g, ' ')\n // truncate\n .substring(0, 255)\n }\n })\n }\n\n return _trim(elText)\n}\n\n/*\n * Check whether an element has nodeType Node.ELEMENT_NODE\n * @param {Element} el - element to check\n * @returns {boolean} whether el is of the correct nodeType\n */\nexport function isElementNode(el: Element | undefined | null): el is HTMLElement {\n return !!el && el.nodeType === 1 // Node.ELEMENT_NODE - use integer constant for browser portability\n}\n\n/*\n * Check whether an element is of a given tag type.\n * Due to potential reference discrepancies (such as the webcomponents.js polyfill),\n * we want to match tagNames instead of specific references because something like\n * element === document.body won't always work because element might not be a native\n * element.\n * @param {Element} el - element to check\n * @param {string} tag - tag name (e.g., \"div\")\n * @returns {boolean} whether el is of the given tag type\n */\nexport function isTag(el: Element | undefined | null, tag: string): el is HTMLElement {\n return !!el && !!el.tagName && el.tagName.toLowerCase() === tag.toLowerCase()\n}\n\n/*\n * Check whether an element has nodeType Node.TEXT_NODE\n * @param {Element} el - element to check\n * @returns {boolean} whether el is of the correct nodeType\n */\nexport function isTextNode(el: Element | undefined | null): el is HTMLElement {\n return !!el && el.nodeType === 3 // Node.TEXT_NODE - use integer constant for browser portability\n}\n\n/*\n * Check whether an element has nodeType Node.DOCUMENT_FRAGMENT_NODE\n * @param {Element} el - element to check\n * @returns {boolean} whether el is of the correct nodeType\n */\nexport function isDocumentFragment(el: Element | ParentNode | undefined | null): el is DocumentFragment {\n return !!el && el.nodeType === 11 // Node.DOCUMENT_FRAGMENT_NODE - use integer constant for browser portability\n}\n\nexport const autocaptureCompatibleElements = ['a', 'button', 'form', 'input', 'select', 'textarea', 'label']\n/*\n * Check whether a DOM event should be \"captured\" or if it may contain sentitive data\n * using a variety of heuristics.\n * @param {Element} el - element to check\n * @param {Event} event - event to check\n * @param {Object} autocaptureConfig - autocapture config\n * @returns {boolean} whether the event should be captured\n */\nexport function shouldCaptureDomEvent(\n el: Element,\n event: Event,\n autocaptureConfig: AutocaptureConfig | undefined = undefined\n): boolean {\n if (!el || isTag(el, 'html') || !isElementNode(el)) {\n return false\n }\n\n if (autocaptureConfig?.url_allowlist) {\n const url = window.location.href\n const allowlist = autocaptureConfig.url_allowlist\n if (allowlist && !allowlist.some((regex) => url.match(regex))) {\n return false\n }\n }\n\n if (autocaptureConfig?.dom_event_allowlist) {\n const allowlist = autocaptureConfig.dom_event_allowlist\n if (allowlist && !allowlist.some((eventType) => event.type === eventType)) {\n return false\n }\n }\n\n if (autocaptureConfig?.element_allowlist) {\n const allowlist = autocaptureConfig.element_allowlist\n if (allowlist && !allowlist.some((elementType) => el.tagName.toLowerCase() === elementType)) {\n return false\n }\n }\n\n if (autocaptureConfig?.css_selector_allowlist) {\n const allowlist = autocaptureConfig.css_selector_allowlist\n if (allowlist && !allowlist.some((selector) => el.matches(selector))) {\n return false\n }\n }\n\n let parentIsUsefulElement = false\n const targetElementList: Element[] = [el] // TODO: remove this var, it's never queried\n let parentNode: Element | boolean = true\n let curEl: Element = el\n while (curEl.parentNode && !isTag(curEl, 'body')) {\n // If element is a shadow root, we skip it\n if (isDocumentFragment(curEl.parentNode)) {\n targetElementList.push((curEl.parentNode as any).host)\n curEl = (curEl.parentNode as any).host\n continue\n }\n parentNode = (curEl.parentNode as Element) || false\n if (!parentNode) break\n if (autocaptureCompatibleElements.indexOf(parentNode.tagName.toLowerCase()) > -1) {\n parentIsUsefulElement = true\n } else {\n const compStyles = window.getComputedStyle(parentNode)\n if (compStyles && compStyles.getPropertyValue('cursor') === 'pointer') {\n parentIsUsefulElement = true\n }\n }\n\n targetElementList.push(parentNode)\n curEl = parentNode\n }\n\n const compStyles = window.getComputedStyle(el)\n if (compStyles && compStyles.getPropertyValue('cursor') === 'pointer' && event.type === 'click') {\n return true\n }\n\n const tag = el.tagName.toLowerCase()\n switch (tag) {\n case 'html':\n return false\n case 'form':\n return event.type === 'submit'\n case 'input':\n return event.type === 'change' || event.type === 'click'\n case 'select':\n case 'textarea':\n return event.type === 'change' || event.type === 'click'\n default:\n if (parentIsUsefulElement) return event.type === 'click'\n return (\n event.type === 'click' &&\n (autocaptureCompatibleElements.indexOf(tag) > -1 || el.getAttribute('contenteditable') === 'true')\n )\n }\n}\n\n/*\n * Check whether a DOM element should be \"captured\" or if it may contain sentitive data\n * using a variety of heuristics.\n * @param {Element} el - element to check\n * @returns {boolean} whether the element should be captured\n */\nexport function shouldCaptureElement(el: Element): boolean {\n for (let curEl = el; curEl.parentNode && !isTag(curEl, 'body'); curEl = curEl.parentNode as Element) {\n const classes = getClassName(curEl).split(' ')\n if (_includes(classes, 'ph-sensitive') || _includes(classes, 'ph-no-capture')) {\n return false\n }\n }\n\n if (_includes(getClassName(el).split(' '), 'ph-include')) {\n return true\n }\n\n // don't include hidden or password fields\n const type = (el as HTMLInputElement).type || ''\n if (typeof type === 'string') {\n // it's possible for el.type to be a DOM element if el is a form with a child input[name=\"type\"]\n switch (type.toLowerCase()) {\n case 'hidden':\n return false\n case 'password':\n return false\n }\n }\n\n // filter out data from fields that look like sensitive fields\n const name = (el as HTMLInputElement).name || el.id || ''\n // See https://github.com/posthog/posthog-js/issues/165\n // Under specific circumstances a bug caused .replace to be called on a DOM element\n // instead of a string, removing the element from the page. Ensure this issue is mitigated.\n if (typeof name === 'string') {\n // it's possible for el.name or el.id to be a DOM element if el is a form with a child input[name=\"name\"]\n const sensitiveNameRegex =\n /^cc|cardnum|ccnum|creditcard|csc|cvc|cvv|exp|pass|pwd|routing|seccode|securitycode|securitynum|socialsec|socsec|ssn/i\n if (sensitiveNameRegex.test(name.replace(/[^a-zA-Z0-9]/g, ''))) {\n return false\n }\n }\n\n return true\n}\n\n/*\n * Check whether a DOM element is 'sensitive' and we should only capture limited data\n * @param {Element} el - element to check\n * @returns {boolean} whether the element should be captured\n */\nexport function isSensitiveElement(el: Element): boolean {\n // don't send data from inputs or similar elements since there will always be\n // a risk of clientside javascript placing sensitive data in attributes\n const allowedInputTypes = ['button', 'checkbox', 'submit', 'reset']\n if (\n (isTag(el, 'input') && !allowedInputTypes.includes((el as HTMLInputElement).type)) ||\n isTag(el, 'select') ||\n isTag(el, 'textarea') ||\n el.getAttribute('contenteditable') === 'true'\n ) {\n return true\n }\n return false\n}\n\n/*\n * Check whether a string value should be \"captured\" or if it may contain sentitive data\n * using a variety of heuristics.\n * @param {string} value - string value to check\n * @returns {boolean} whether the element should be captured\n */\nexport function shouldCaptureValue(value: string): boolean {\n if (value === null || _isUndefined(value)) {\n return false\n }\n\n if (typeof value === 'string') {\n value = _trim(value)\n\n // check to see if input value looks like a credit card number\n // see: https://www.safaribooksonline.com/library/view/regular-expressions-cookbook/9781449327453/ch04s20.html\n const ccRegex =\n /^(?:(4[0-9]{12}(?:[0-9]{3})?)|(5[1-5][0-9]{14})|(6(?:011|5[0-9]{2})[0-9]{12})|(3[47][0-9]{13})|(3(?:0[0-5]|[68][0-9])[0-9]{11})|((?:2131|1800|35[0-9]{3})[0-9]{11}))$/\n if (ccRegex.test((value || '').replace(/[- ]/g, ''))) {\n return false\n }\n\n // check to see if input value looks like a social security number\n const ssnRegex = /(^\\d{3}-?\\d{2}-?\\d{4}$)/\n if (ssnRegex.test(value)) {\n return false\n }\n }\n\n return true\n}\n\n/*\n * Check whether an attribute name is an Angular style attr (either _ngcontent or _nghost)\n * These update on each build and lead to noise in the element chain\n * More details on the attributes here: https://angular.io/guide/view-encapsulation\n * @param {string} attributeName - string value to check\n * @returns {boolean} whether the element is an angular tag\n */\nexport function isAngularStyleAttr(attributeName: string): boolean {\n if (typeof attributeName === 'string') {\n return attributeName.substring(0, 10) === '_ngcontent' || attributeName.substring(0, 7) === '_nghost'\n }\n return false\n}\n\n/*\n * Iterate through children of a target element looking for span tags\n * and return the text content of the span tags, separated by spaces,\n * along with the direct text content of the target element\n * @param {Element} target - element to check\n * @returns {string} text content of the target element and its child span tags\n */\nexport function getDirectAndNestedSpanText(target: Element): string {\n let text = getSafeText(target)\n text = `${text} ${getNestedSpanText(target)}`.trim()\n return shouldCaptureValue(text) ? text : ''\n}\n\n/*\n * Iterate through children of a target element looking for span tags\n * and return the text content of the span tags, separated by spaces\n * @param {Element} target - element to check\n * @returns {string} text content of span tags\n */\nexport function getNestedSpanText(target: Element): string {\n let text = ''\n if (target && target.childNodes && target.childNodes.length) {\n _each(target.childNodes, function (child) {\n if (child && child.tagName?.toLowerCase() === 'span') {\n try {\n const spanText = getSafeText(child)\n text = `${text} ${spanText}`.trim()\n\n if (child.childNodes && child.childNodes.length) {\n text = `${text} ${getNestedSpanText(child)}`.trim()\n }\n } catch (e) {\n console.error(e)\n }\n }\n })\n }\n return text\n}\n"]}
@@ -0,0 +1,27 @@
1
+ import RageClick from './extensions/rageclick';
2
+ import { AutocaptureConfig, AutoCaptureCustomProperty, DecideResponse, Properties } from './types';
3
+ import { PostHog } from './posthog-core';
4
+ declare const autocapture: {
5
+ _initializedTokens: string[];
6
+ _isDisabledServerSide: boolean | null;
7
+ _isAutocaptureEnabled: boolean;
8
+ _setIsAutocaptureEnabled: (instance: PostHog) => void;
9
+ _previousElementSibling: (el: Element) => Element | null;
10
+ _getAugmentPropertiesFromElement: (elem: Element) => Properties;
11
+ _getPropertiesFromElement: (elem: Element, maskInputs: boolean, maskText: boolean) => Properties;
12
+ _getDefaultProperties: (eventType: string) => Properties;
13
+ _extractCustomPropertyValue: (customProperty: AutoCaptureCustomProperty) => string;
14
+ _getCustomProperties: (targetElementList: Element[]) => Properties;
15
+ _getEventTarget: (e: Event) => Element | null;
16
+ _captureEvent: (e: Event, instance: PostHog, eventName?: string) => boolean | void;
17
+ _navigate: (href: string) => void;
18
+ _addDomEventHandlers: (instance: PostHog) => void;
19
+ _customProperties: AutoCaptureCustomProperty[];
20
+ rageclicks: RageClick | null;
21
+ config: AutocaptureConfig | undefined;
22
+ init: (instance: PostHog) => void;
23
+ afterDecideResponse: (response: DecideResponse, instance: PostHog) => void;
24
+ enabledForProject: (token: string | null | undefined, numBuckets: number, numEnabledBuckets: number) => boolean;
25
+ isBrowserSupported: () => boolean;
26
+ };
27
+ export { autocapture };