@posthog/browser-common 0.9.8 → 0.9.10
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/dist/autocapture-config.d.ts +13 -0
- package/dist/autocapture-config.js +18 -0
- package/dist/autocapture-config.mjs +1 -0
- package/dist/autocapture.d.ts +63 -0
- package/dist/autocapture.js +533 -0
- package/dist/autocapture.mjs +467 -0
- package/dist/config.js +1 -1
- package/dist/config.mjs +1 -1
- package/dist/constants.d.ts +1 -0
- package/dist/constants.js +4 -0
- package/dist/constants.mjs +2 -1
- package/dist/rageclick.d.ts +14 -0
- package/dist/rageclick.js +72 -0
- package/dist/rageclick.mjs +34 -0
- package/dist/survey-action-matcher.js +6 -1
- package/dist/survey-action-matcher.mjs +6 -1
- package/dist/survey-event-host.d.ts +2 -0
- package/dist/survey-event-receiver.d.ts +2 -1
- package/dist/survey-event-receiver.js +3 -2
- package/dist/survey-event-receiver.mjs +3 -2
- package/dist/surveys.d.ts +3 -0
- package/dist/surveys.js +8 -2
- package/dist/surveys.mjs +8 -2
- package/dist/utils/autocapture-utils.js +12 -7
- package/dist/utils/autocapture-utils.mjs +12 -7
- package/dist/utils/convert-to-url.d.ts +7 -0
- package/dist/utils/convert-to-url.js +47 -0
- package/dist/utils/convert-to-url.mjs +9 -0
- package/dist/utils/request-utils.d.ts +1 -7
- package/dist/utils/request-utils.js +5 -10
- package/dist/utils/request-utils.mjs +6 -11
- package/dist/utils/url-targeting-utils.js +2 -1
- package/dist/utils/url-targeting-utils.mjs +2 -1
- package/package.json +27 -3
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { AutocaptureConfig as DomAutocaptureConfig, RageclickConfig } from '@posthog/types';
|
|
2
|
+
export interface AutocaptureConfig extends DomAutocaptureConfig {
|
|
3
|
+
enabled: boolean;
|
|
4
|
+
rageclick: boolean | RageclickConfig;
|
|
5
|
+
maskAllElementAttributes: boolean;
|
|
6
|
+
maskAllText: boolean;
|
|
7
|
+
disableCaptureUrlHashes: boolean;
|
|
8
|
+
getCurrentUrl?: (defaultUrl: string) => string;
|
|
9
|
+
remoteRequestsDisabled: boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface AutocaptureConfigSource {
|
|
12
|
+
refresh(config: AutocaptureConfig): void;
|
|
13
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_require__ = {};
|
|
3
|
+
(()=>{
|
|
4
|
+
__webpack_require__.r = (exports1)=>{
|
|
5
|
+
if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
6
|
+
value: 'Module'
|
|
7
|
+
});
|
|
8
|
+
Object.defineProperty(exports1, '__esModule', {
|
|
9
|
+
value: true
|
|
10
|
+
});
|
|
11
|
+
};
|
|
12
|
+
})();
|
|
13
|
+
var __webpack_exports__ = {};
|
|
14
|
+
__webpack_require__.r(__webpack_exports__);
|
|
15
|
+
for(var __rspack_i in __webpack_exports__)exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
16
|
+
Object.defineProperty(exports, '__esModule', {
|
|
17
|
+
value: true
|
|
18
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { Client } from './client';
|
|
2
|
+
import type { Extension } from './extension';
|
|
3
|
+
import type { ExtensionToken } from './token';
|
|
4
|
+
import RageClick from './rageclick';
|
|
5
|
+
import type { Properties } from '@posthog/types';
|
|
6
|
+
import type { RemoteConfigResult } from './types/remote-config';
|
|
7
|
+
import type { AutocaptureConfigSource } from './autocapture-config';
|
|
8
|
+
export declare function getAugmentPropertiesFromElement(elem: Element): Properties;
|
|
9
|
+
export declare function previousElementSibling(el: Element): Element | null;
|
|
10
|
+
export declare function getDefaultProperties(eventType: string): Properties;
|
|
11
|
+
export declare function getPropertiesFromElement(elem: Element, maskAllAttributes: boolean, maskText: boolean, elementAttributeIgnorelist: string[] | undefined, disableCaptureUrlHashes?: boolean): Properties;
|
|
12
|
+
export declare function autocapturePropertiesForElement(target: Element, { e, maskAllElementAttributes, maskAllText, elementAttributeIgnoreList, elementsChainAsString, disableCaptureUrlHashes, }: {
|
|
13
|
+
e: Event;
|
|
14
|
+
maskAllElementAttributes: boolean;
|
|
15
|
+
maskAllText: boolean;
|
|
16
|
+
elementAttributeIgnoreList?: string[] | undefined;
|
|
17
|
+
elementsChainAsString: boolean;
|
|
18
|
+
disableCaptureUrlHashes: boolean;
|
|
19
|
+
}): {
|
|
20
|
+
props: Properties;
|
|
21
|
+
explicitNoCapture?: boolean;
|
|
22
|
+
target?: Element;
|
|
23
|
+
};
|
|
24
|
+
export declare const AutocaptureExtension: ExtensionToken<Autocapture>;
|
|
25
|
+
export declare class Autocapture implements Extension {
|
|
26
|
+
private readonly _configSource;
|
|
27
|
+
readonly name: ExtensionToken<Autocapture>;
|
|
28
|
+
_initialized: boolean;
|
|
29
|
+
_isDisabledServerSide: boolean | null;
|
|
30
|
+
_hasReceivedConfigResponse: boolean;
|
|
31
|
+
_elementSelectors: Set<string> | null;
|
|
32
|
+
private _elementSelectorsByOwner;
|
|
33
|
+
rageclicks: RageClick;
|
|
34
|
+
_elementsChainAsString: boolean;
|
|
35
|
+
private _listenerWindow;
|
|
36
|
+
private _listenerDocument;
|
|
37
|
+
private _client;
|
|
38
|
+
private readonly _config;
|
|
39
|
+
private _remoteConfigSubscription;
|
|
40
|
+
private _domEventHandler;
|
|
41
|
+
private _copiedTextHandler;
|
|
42
|
+
private _disposed;
|
|
43
|
+
private _pointerDown;
|
|
44
|
+
private _pointerExpiry;
|
|
45
|
+
private _clearPointer;
|
|
46
|
+
private _isExcludedPointerTarget;
|
|
47
|
+
private _trackPointer;
|
|
48
|
+
private _recoverClickTarget;
|
|
49
|
+
constructor(_configSource: AutocaptureConfigSource);
|
|
50
|
+
setup(client: Client): void;
|
|
51
|
+
dispose(): void;
|
|
52
|
+
private _refreshConfig;
|
|
53
|
+
private _compileUrlPatterns;
|
|
54
|
+
_addDomEventHandlers(): void;
|
|
55
|
+
private _removeDomEventHandlers;
|
|
56
|
+
startIfEnabled(): void;
|
|
57
|
+
onRemoteConfig(result: RemoteConfigResult): void;
|
|
58
|
+
setElementSelectors(selectors: Set<string>, owner?: object): void;
|
|
59
|
+
getElementSelectors(element: Element | null, additionalElement?: Element): string[] | null;
|
|
60
|
+
get isEnabled(): boolean;
|
|
61
|
+
private _captureEvent;
|
|
62
|
+
isBrowserSupported(): boolean;
|
|
63
|
+
}
|
|
@@ -0,0 +1,533 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_require__ = {};
|
|
3
|
+
(()=>{
|
|
4
|
+
__webpack_require__.n = (module)=>{
|
|
5
|
+
var getter = module && module.__esModule ? ()=>module['default'] : ()=>module;
|
|
6
|
+
__webpack_require__.d(getter, {
|
|
7
|
+
a: getter
|
|
8
|
+
});
|
|
9
|
+
return getter;
|
|
10
|
+
};
|
|
11
|
+
})();
|
|
12
|
+
(()=>{
|
|
13
|
+
__webpack_require__.d = (exports1, getters, values)=>{
|
|
14
|
+
var define = (defs, kind)=>{
|
|
15
|
+
for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
16
|
+
enumerable: true,
|
|
17
|
+
[kind]: defs[key]
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
define(getters, "get");
|
|
21
|
+
define(values, "value");
|
|
22
|
+
};
|
|
23
|
+
})();
|
|
24
|
+
(()=>{
|
|
25
|
+
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
26
|
+
})();
|
|
27
|
+
(()=>{
|
|
28
|
+
__webpack_require__.r = (exports1)=>{
|
|
29
|
+
if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
30
|
+
value: 'Module'
|
|
31
|
+
});
|
|
32
|
+
Object.defineProperty(exports1, '__esModule', {
|
|
33
|
+
value: true
|
|
34
|
+
});
|
|
35
|
+
};
|
|
36
|
+
})();
|
|
37
|
+
var __webpack_exports__ = {};
|
|
38
|
+
__webpack_require__.r(__webpack_exports__);
|
|
39
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
40
|
+
Autocapture: ()=>Autocapture,
|
|
41
|
+
AutocaptureExtension: ()=>AutocaptureExtension,
|
|
42
|
+
autocapturePropertiesForElement: ()=>autocapturePropertiesForElement,
|
|
43
|
+
getAugmentPropertiesFromElement: ()=>getAugmentPropertiesFromElement,
|
|
44
|
+
getDefaultProperties: ()=>getDefaultProperties,
|
|
45
|
+
getPropertiesFromElement: ()=>getPropertiesFromElement,
|
|
46
|
+
previousElementSibling: ()=>previousElementSibling
|
|
47
|
+
});
|
|
48
|
+
const general_utils_js_namespaceObject = require("./utils/general-utils.js");
|
|
49
|
+
const autocapture_utils_js_namespaceObject = require("./utils/autocapture-utils.js");
|
|
50
|
+
const external_rageclick_js_namespaceObject = require("./rageclick.js");
|
|
51
|
+
var external_rageclick_js_default = /*#__PURE__*/ __webpack_require__.n(external_rageclick_js_namespaceObject);
|
|
52
|
+
const external_constants_js_namespaceObject = require("./constants.js");
|
|
53
|
+
const core_namespaceObject = require("@posthog/core");
|
|
54
|
+
const logger_js_namespaceObject = require("./utils/logger.js");
|
|
55
|
+
const convert_to_url_js_namespaceObject = require("./utils/convert-to-url.js");
|
|
56
|
+
const element_utils_js_namespaceObject = require("./utils/element-utils.js");
|
|
57
|
+
const getWindow = ()=>"u" < typeof window ? void 0 : window;
|
|
58
|
+
const getDocument = ()=>"u" < typeof document ? void 0 : document;
|
|
59
|
+
const COPY_AUTOCAPTURE_EVENT = '$copy_autocapture';
|
|
60
|
+
const logger = (0, logger_js_namespaceObject.createLogger)('[AutoCapture]');
|
|
61
|
+
function limitText(length, text) {
|
|
62
|
+
if (text.length > length) return text.slice(0, length) + '...';
|
|
63
|
+
return text;
|
|
64
|
+
}
|
|
65
|
+
function getAugmentPropertiesFromElement(elem) {
|
|
66
|
+
const shouldCaptureEl = (0, autocapture_utils_js_namespaceObject.shouldCaptureElement)(elem);
|
|
67
|
+
if (!shouldCaptureEl) return {};
|
|
68
|
+
const props = {};
|
|
69
|
+
(0, general_utils_js_namespaceObject.each)(elem.attributes, function(attr) {
|
|
70
|
+
if (attr.name && 0 === attr.name.indexOf('data-ph-capture-attribute')) {
|
|
71
|
+
const propertyKey = attr.name.replace('data-ph-capture-attribute-', '');
|
|
72
|
+
const propertyValue = attr.value;
|
|
73
|
+
if (propertyKey && propertyValue && (0, autocapture_utils_js_namespaceObject.shouldCaptureValue)(propertyValue)) props[propertyKey] = propertyValue;
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
return props;
|
|
77
|
+
}
|
|
78
|
+
function previousElementSibling(el) {
|
|
79
|
+
if (el.previousElementSibling) return el.previousElementSibling;
|
|
80
|
+
let _el = el;
|
|
81
|
+
do _el = _el.previousSibling;
|
|
82
|
+
while (_el && !(0, element_utils_js_namespaceObject.isElementNode)(_el));
|
|
83
|
+
return _el;
|
|
84
|
+
}
|
|
85
|
+
function getDefaultProperties(eventType) {
|
|
86
|
+
return {
|
|
87
|
+
$event_type: eventType,
|
|
88
|
+
$ce_version: 1
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
function getPropertiesFromElement(elem, maskAllAttributes, maskText, elementAttributeIgnorelist, disableCaptureUrlHashes = false) {
|
|
92
|
+
const tag_name = elem.tagName.toLowerCase();
|
|
93
|
+
const props = {
|
|
94
|
+
tag_name: tag_name
|
|
95
|
+
};
|
|
96
|
+
if (autocapture_utils_js_namespaceObject.autocaptureCompatibleElements.indexOf(tag_name) > -1 && !maskText) if ('a' === tag_name.toLowerCase() || 'button' === tag_name.toLowerCase()) props['$el_text'] = limitText(1024, (0, autocapture_utils_js_namespaceObject.getDirectAndNestedSpanText)(elem));
|
|
97
|
+
else props['$el_text'] = limitText(1024, (0, autocapture_utils_js_namespaceObject.getSafeText)(elem));
|
|
98
|
+
const classes = (0, autocapture_utils_js_namespaceObject.getClassNames)(elem);
|
|
99
|
+
if (!maskAllAttributes && !elementAttributeIgnorelist?.includes('class') && classes.length > 0) props['classes'] = classes.filter(function(c) {
|
|
100
|
+
return '' !== c;
|
|
101
|
+
});
|
|
102
|
+
(0, general_utils_js_namespaceObject.each)(elem.attributes, function(attr) {
|
|
103
|
+
if ((0, autocapture_utils_js_namespaceObject.isSensitiveElement)(elem) && -1 === [
|
|
104
|
+
'name',
|
|
105
|
+
'id',
|
|
106
|
+
'class',
|
|
107
|
+
'aria-label'
|
|
108
|
+
].indexOf(attr.name)) return;
|
|
109
|
+
if (elementAttributeIgnorelist?.includes(attr.name)) return;
|
|
110
|
+
if (!maskAllAttributes && (0, autocapture_utils_js_namespaceObject.shouldCaptureValue)(attr.value) && !(0, autocapture_utils_js_namespaceObject.isAngularStyleAttr)(attr.name)) {
|
|
111
|
+
let value = attr.value;
|
|
112
|
+
if ('class' === attr.name) value = (0, autocapture_utils_js_namespaceObject.splitClassString)(value).join(' ');
|
|
113
|
+
props['attr__' + attr.name] = limitText(1024, 'href' === attr.name && disableCaptureUrlHashes ? (0, core_namespaceObject.stripUrlHash)(value) : value);
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
let nthChild = 1;
|
|
117
|
+
let nthOfType = 1;
|
|
118
|
+
let currentElem = elem;
|
|
119
|
+
while(currentElem = previousElementSibling(currentElem)){
|
|
120
|
+
nthChild++;
|
|
121
|
+
if (currentElem.tagName === elem.tagName) nthOfType++;
|
|
122
|
+
}
|
|
123
|
+
props['nth_child'] = nthChild;
|
|
124
|
+
props['nth_of_type'] = nthOfType;
|
|
125
|
+
return props;
|
|
126
|
+
}
|
|
127
|
+
function autocapturePropertiesForElement(target, { e, maskAllElementAttributes, maskAllText, elementAttributeIgnoreList, elementsChainAsString, disableCaptureUrlHashes }) {
|
|
128
|
+
if (!(0, element_utils_js_namespaceObject.isElementNode)(target)) return {
|
|
129
|
+
props: {}
|
|
130
|
+
};
|
|
131
|
+
const targetElementList = [
|
|
132
|
+
target
|
|
133
|
+
];
|
|
134
|
+
const seen = new Set([
|
|
135
|
+
target
|
|
136
|
+
]);
|
|
137
|
+
let curEl = target;
|
|
138
|
+
while(curEl.parentNode && !(0, element_utils_js_namespaceObject.isTag)(curEl, 'body')){
|
|
139
|
+
if (targetElementList.length >= autocapture_utils_js_namespaceObject.MAX_DOM_ANCESTOR_DEPTH) break;
|
|
140
|
+
if ((0, element_utils_js_namespaceObject.isShadowRoot)(curEl.parentNode)) {
|
|
141
|
+
const host = curEl.parentNode.host;
|
|
142
|
+
if (seen.has(host)) break;
|
|
143
|
+
seen.add(host);
|
|
144
|
+
targetElementList.push(host);
|
|
145
|
+
curEl = host;
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
if (!(0, element_utils_js_namespaceObject.isElementNode)(curEl.parentNode)) break;
|
|
149
|
+
if (seen.has(curEl.parentNode)) break;
|
|
150
|
+
seen.add(curEl.parentNode);
|
|
151
|
+
targetElementList.push(curEl.parentNode);
|
|
152
|
+
curEl = curEl.parentNode;
|
|
153
|
+
}
|
|
154
|
+
const controlIndex = 'click' === e.type && 'http://www.w3.org/2000/svg' === target.namespaceURI ? targetElementList.findIndex((el)=>(0, element_utils_js_namespaceObject.isTag)(el, 'button') || (0, element_utils_js_namespaceObject.isTag)(el, 'a')) : -1;
|
|
155
|
+
if (controlIndex > 0) maskAllText = maskAllText || targetElementList.slice(0, controlIndex + 1).some((el)=>!(0, autocapture_utils_js_namespaceObject.shouldCaptureElement)(el) || (0, autocapture_utils_js_namespaceObject.isSensitiveElement)(el));
|
|
156
|
+
const elementsJson = [];
|
|
157
|
+
const autocaptureAugmentProperties = {};
|
|
158
|
+
let href = false;
|
|
159
|
+
let explicitNoCapture = false;
|
|
160
|
+
(0, general_utils_js_namespaceObject.each)(targetElementList, (el)=>{
|
|
161
|
+
const shouldCaptureEl = (0, autocapture_utils_js_namespaceObject.shouldCaptureElement)(el);
|
|
162
|
+
if ((0, element_utils_js_namespaceObject.isTag)(el, 'a') && !maskAllElementAttributes && !elementAttributeIgnoreList?.includes('href')) {
|
|
163
|
+
const hrefAttr = el.getAttribute('href');
|
|
164
|
+
href = shouldCaptureEl && !!hrefAttr && (0, autocapture_utils_js_namespaceObject.shouldCaptureValue)(hrefAttr) ? disableCaptureUrlHashes ? (0, core_namespaceObject.stripUrlHash)(hrefAttr) : hrefAttr : false;
|
|
165
|
+
}
|
|
166
|
+
const classes = (0, autocapture_utils_js_namespaceObject.getClassNames)(el);
|
|
167
|
+
if ((0, core_namespaceObject.includes)(classes, 'ph-no-capture')) explicitNoCapture = true;
|
|
168
|
+
elementsJson.push(getPropertiesFromElement(el, maskAllElementAttributes, maskAllText, elementAttributeIgnoreList, disableCaptureUrlHashes));
|
|
169
|
+
const augmentProperties = getAugmentPropertiesFromElement(el);
|
|
170
|
+
(0, general_utils_js_namespaceObject.each)(augmentProperties, (value, key)=>{
|
|
171
|
+
if (!Object.prototype.hasOwnProperty.call(autocaptureAugmentProperties, key)) autocaptureAugmentProperties[key] = value;
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
if (explicitNoCapture) return {
|
|
175
|
+
props: {},
|
|
176
|
+
explicitNoCapture
|
|
177
|
+
};
|
|
178
|
+
if (controlIndex > 0) {
|
|
179
|
+
target = targetElementList[controlIndex];
|
|
180
|
+
elementsJson.splice(0, controlIndex);
|
|
181
|
+
}
|
|
182
|
+
if (!maskAllText) if ((0, element_utils_js_namespaceObject.isTag)(target, 'a') || (0, element_utils_js_namespaceObject.isTag)(target, 'button')) elementsJson[0]['$el_text'] = (0, autocapture_utils_js_namespaceObject.getDirectAndNestedSpanText)(target);
|
|
183
|
+
else elementsJson[0]['$el_text'] = (0, autocapture_utils_js_namespaceObject.getSafeText)(target);
|
|
184
|
+
let externalHref;
|
|
185
|
+
if (href) {
|
|
186
|
+
elementsJson[0]['attr__href'] = href;
|
|
187
|
+
const hrefHost = (0, convert_to_url_js_namespaceObject.convertToURL)(href)?.host;
|
|
188
|
+
const locationHost = getWindow()?.location?.host;
|
|
189
|
+
if (hrefHost && locationHost && hrefHost !== locationHost) externalHref = href;
|
|
190
|
+
}
|
|
191
|
+
const props = (0, general_utils_js_namespaceObject.extend)(getDefaultProperties(e.type), elementsChainAsString ? {} : {
|
|
192
|
+
$elements: elementsJson
|
|
193
|
+
}, {
|
|
194
|
+
$elements_chain: (0, autocapture_utils_js_namespaceObject.getElementsChainString)(elementsJson)
|
|
195
|
+
}, elementsJson[0]?.['$el_text'] ? {
|
|
196
|
+
$el_text: elementsJson[0]?.['$el_text']
|
|
197
|
+
} : {}, externalHref && 'click' === e.type ? {
|
|
198
|
+
$external_click_url: externalHref
|
|
199
|
+
} : {}, autocaptureAugmentProperties);
|
|
200
|
+
return {
|
|
201
|
+
props,
|
|
202
|
+
target
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
const AutocaptureExtension = 'autocapture';
|
|
206
|
+
class Autocapture {
|
|
207
|
+
_clearPointer() {
|
|
208
|
+
this._pointerDown = void 0;
|
|
209
|
+
clearTimeout(this._pointerExpiry);
|
|
210
|
+
this._pointerExpiry = void 0;
|
|
211
|
+
}
|
|
212
|
+
_isExcludedPointerTarget(target) {
|
|
213
|
+
if (!(0, autocapture_utils_js_namespaceObject.shouldCaptureElement)(target)) return true;
|
|
214
|
+
const ignorelist = this._refreshConfig().css_selector_ignorelist ?? autocapture_utils_js_namespaceObject.DEFAULT_AUTOCAPTURE_IGNORE_LIST;
|
|
215
|
+
const seen = new Set();
|
|
216
|
+
let el = target;
|
|
217
|
+
while(el){
|
|
218
|
+
if (seen.size >= autocapture_utils_js_namespaceObject.MAX_DOM_ANCESTOR_DEPTH || seen.has(el)) return true;
|
|
219
|
+
seen.add(el);
|
|
220
|
+
const current = el;
|
|
221
|
+
const classes = (0, autocapture_utils_js_namespaceObject.getClassNames)(current);
|
|
222
|
+
if ((0, core_namespaceObject.includes)(classes, 'ph-no-capture') || (0, core_namespaceObject.includes)(classes, 'ph-sensitive') || (0, autocapture_utils_js_namespaceObject.isSensitiveElement)(current) || ignorelist.some((selector)=>(0, autocapture_utils_js_namespaceObject.elementMatchesCSSSelector)(current, selector))) return true;
|
|
223
|
+
const parent = el.parentNode;
|
|
224
|
+
el = (0, element_utils_js_namespaceObject.isShadowRoot)(parent) ? parent.host : parent && (0, element_utils_js_namespaceObject.isElementNode)(parent) ? parent : null;
|
|
225
|
+
}
|
|
226
|
+
return false;
|
|
227
|
+
}
|
|
228
|
+
_trackPointer(e) {
|
|
229
|
+
if (!this.isEnabled || 'pointercancel' === e.type) return void this._clearPointer();
|
|
230
|
+
if ('pointerdown' === e.type) {
|
|
231
|
+
this._clearPointer();
|
|
232
|
+
const target = (0, autocapture_utils_js_namespaceObject.getEventTarget)(e);
|
|
233
|
+
if (e.isPrimary && 0 === e.button && !e.ctrlKey && target && (0, element_utils_js_namespaceObject.isElementNode)(target)) this._pointerDown = {
|
|
234
|
+
target,
|
|
235
|
+
excluded: this._isExcludedPointerTarget(target),
|
|
236
|
+
id: e.pointerId,
|
|
237
|
+
x: e.clientX,
|
|
238
|
+
y: e.clientY,
|
|
239
|
+
released: false,
|
|
240
|
+
distinctId: this._client?.distinctId
|
|
241
|
+
};
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
const down = this._pointerDown;
|
|
245
|
+
if (!down) return;
|
|
246
|
+
if (e.pointerId !== down.id || Math.abs(e.clientX - down.x) > 5 || Math.abs(e.clientY - down.y) > 5) this._clearPointer();
|
|
247
|
+
else if ('pointerup' === e.type) {
|
|
248
|
+
down.released = true;
|
|
249
|
+
this._pointerExpiry = setTimeout(()=>this._clearPointer(), 0);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
_recoverClickTarget(e) {
|
|
253
|
+
const down = this._pointerDown;
|
|
254
|
+
this._clearPointer();
|
|
255
|
+
const target = (0, autocapture_utils_js_namespaceObject.getEventTarget)(e);
|
|
256
|
+
if (down?.released && down.target.isConnected && down.distinctId === this._client?.distinctId && e.pointerId === down.id && (e.detail > 0 || 'touch' === e.pointerType || 'pen' === e.pointerType) && 0 === e.button && Math.abs(e.clientX - down.x) <= 5 && Math.abs(e.clientY - down.y) <= 5 && target && ((0, element_utils_js_namespaceObject.isTag)(target, 'html') || (0, element_utils_js_namespaceObject.isTag)(target, 'body'))) {
|
|
257
|
+
if (down.excluded) return null;
|
|
258
|
+
const ignorelist = this._refreshConfig().css_selector_ignorelist ?? autocapture_utils_js_namespaceObject.DEFAULT_AUTOCAPTURE_IGNORE_LIST;
|
|
259
|
+
const excludedRoot = [
|
|
260
|
+
target,
|
|
261
|
+
getDocument()?.documentElement,
|
|
262
|
+
getDocument()?.body
|
|
263
|
+
].some((root)=>{
|
|
264
|
+
if (!root) return false;
|
|
265
|
+
const classes = (0, autocapture_utils_js_namespaceObject.getClassNames)(root);
|
|
266
|
+
return (0, core_namespaceObject.includes)(classes, 'ph-no-capture') || (0, core_namespaceObject.includes)(classes, 'ph-sensitive') || !(0, autocapture_utils_js_namespaceObject.shouldCaptureElement)(root) || (0, autocapture_utils_js_namespaceObject.isSensitiveElement)(root) || ignorelist.some((selector)=>(0, autocapture_utils_js_namespaceObject.elementMatchesCSSSelector)(root, selector));
|
|
267
|
+
});
|
|
268
|
+
if (excludedRoot) return null;
|
|
269
|
+
return down.target;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
constructor(_configSource){
|
|
273
|
+
this._configSource = _configSource;
|
|
274
|
+
this.name = AutocaptureExtension;
|
|
275
|
+
this._initialized = false;
|
|
276
|
+
this._isDisabledServerSide = null;
|
|
277
|
+
this._hasReceivedConfigResponse = false;
|
|
278
|
+
this._elementSelectorsByOwner = new Map();
|
|
279
|
+
this._elementsChainAsString = false;
|
|
280
|
+
this._config = {
|
|
281
|
+
enabled: false,
|
|
282
|
+
rageclick: false,
|
|
283
|
+
maskAllElementAttributes: false,
|
|
284
|
+
maskAllText: false,
|
|
285
|
+
disableCaptureUrlHashes: false,
|
|
286
|
+
remoteRequestsDisabled: false
|
|
287
|
+
};
|
|
288
|
+
this._disposed = false;
|
|
289
|
+
this._configSource.refresh(this._config);
|
|
290
|
+
this.rageclicks = new (external_rageclick_js_default())(this._config.rageclick);
|
|
291
|
+
this._elementSelectors = null;
|
|
292
|
+
}
|
|
293
|
+
setup(client) {
|
|
294
|
+
this._compileUrlPatterns();
|
|
295
|
+
this._client = client;
|
|
296
|
+
const subscription = client.onRemoteConfig(this.onRemoteConfig.bind(this));
|
|
297
|
+
if (this._disposed) return void subscription.dispose();
|
|
298
|
+
this._remoteConfigSubscription = subscription;
|
|
299
|
+
this.startIfEnabled();
|
|
300
|
+
}
|
|
301
|
+
dispose() {
|
|
302
|
+
if (this._disposed) return;
|
|
303
|
+
this._disposed = true;
|
|
304
|
+
this._client = void 0;
|
|
305
|
+
this._remoteConfigSubscription?.dispose();
|
|
306
|
+
this._remoteConfigSubscription = void 0;
|
|
307
|
+
this._elementSelectorsByOwner.clear();
|
|
308
|
+
this._elementSelectors = null;
|
|
309
|
+
this._removeDomEventHandlers();
|
|
310
|
+
}
|
|
311
|
+
_refreshConfig() {
|
|
312
|
+
this._configSource.refresh(this._config);
|
|
313
|
+
return this._config;
|
|
314
|
+
}
|
|
315
|
+
_compileUrlPatterns() {
|
|
316
|
+
this._refreshConfig();
|
|
317
|
+
this._config.url_allowlist = this._config.url_allowlist?.map((url)=>new RegExp(url));
|
|
318
|
+
this._config.url_ignorelist = this._config.url_ignorelist?.map((url)=>new RegExp(url));
|
|
319
|
+
return this._config;
|
|
320
|
+
}
|
|
321
|
+
_addDomEventHandlers() {
|
|
322
|
+
const window1 = getWindow();
|
|
323
|
+
const document1 = getDocument();
|
|
324
|
+
if (!this.isBrowserSupported()) return void logger.info('Disabling Automatic Event Collection because this browser is not supported');
|
|
325
|
+
if (!window1 || !document1) return;
|
|
326
|
+
this._listenerWindow = window1;
|
|
327
|
+
this._listenerDocument = document1;
|
|
328
|
+
const handler = this._domEventHandler = (e)=>{
|
|
329
|
+
e = e || window1?.event;
|
|
330
|
+
try {
|
|
331
|
+
if ('blur' === e.type) return void this._clearPointer();
|
|
332
|
+
if (0 === e.type.indexOf('pointer')) return void this._trackPointer(e);
|
|
333
|
+
const target = 'click' === e.type ? this._recoverClickTarget(e) : void 0;
|
|
334
|
+
if ((0, core_namespaceObject.isNull)(target)) return;
|
|
335
|
+
this._captureEvent(e, '$autocapture', target);
|
|
336
|
+
} catch (error) {
|
|
337
|
+
logger.error('Failed to capture event', error);
|
|
338
|
+
}
|
|
339
|
+
};
|
|
340
|
+
(0, general_utils_js_namespaceObject.addEventListener)(window1, 'blur', handler);
|
|
341
|
+
(0, general_utils_js_namespaceObject.addEventListener)(document1, 'submit', handler, {
|
|
342
|
+
capture: true
|
|
343
|
+
});
|
|
344
|
+
(0, general_utils_js_namespaceObject.addEventListener)(document1, 'change', handler, {
|
|
345
|
+
capture: true
|
|
346
|
+
});
|
|
347
|
+
(0, general_utils_js_namespaceObject.addEventListener)(document1, 'click', handler, {
|
|
348
|
+
capture: true
|
|
349
|
+
});
|
|
350
|
+
(0, general_utils_js_namespaceObject.each)([
|
|
351
|
+
'pointerdown',
|
|
352
|
+
'pointermove',
|
|
353
|
+
'pointerup',
|
|
354
|
+
'pointercancel'
|
|
355
|
+
], (type)=>{
|
|
356
|
+
(0, general_utils_js_namespaceObject.addEventListener)(document1, type, handler, {
|
|
357
|
+
capture: true
|
|
358
|
+
});
|
|
359
|
+
});
|
|
360
|
+
if (this._refreshConfig().capture_copied_text) {
|
|
361
|
+
const copiedTextHandler = this._copiedTextHandler = (e)=>{
|
|
362
|
+
e = e || window1?.event;
|
|
363
|
+
try {
|
|
364
|
+
this._captureEvent(e, COPY_AUTOCAPTURE_EVENT);
|
|
365
|
+
} catch (error) {
|
|
366
|
+
logger.error('Failed to capture clipboard event', error);
|
|
367
|
+
}
|
|
368
|
+
};
|
|
369
|
+
(0, general_utils_js_namespaceObject.addEventListener)(document1, 'copy', copiedTextHandler, {
|
|
370
|
+
capture: true
|
|
371
|
+
});
|
|
372
|
+
(0, general_utils_js_namespaceObject.addEventListener)(document1, 'cut', copiedTextHandler, {
|
|
373
|
+
capture: true
|
|
374
|
+
});
|
|
375
|
+
(0, general_utils_js_namespaceObject.addEventListener)(document1, 'paste', copiedTextHandler, {
|
|
376
|
+
capture: true
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
_removeDomEventHandlers() {
|
|
381
|
+
const window1 = this._listenerWindow;
|
|
382
|
+
const document1 = this._listenerDocument;
|
|
383
|
+
this._clearPointer();
|
|
384
|
+
if (this._domEventHandler) {
|
|
385
|
+
window1?.removeEventListener('blur', this._domEventHandler);
|
|
386
|
+
(0, general_utils_js_namespaceObject.each)([
|
|
387
|
+
'pointerdown',
|
|
388
|
+
'pointermove',
|
|
389
|
+
'pointerup',
|
|
390
|
+
'pointercancel'
|
|
391
|
+
], (type)=>{
|
|
392
|
+
document1?.removeEventListener(type, this._domEventHandler, true);
|
|
393
|
+
});
|
|
394
|
+
document1?.removeEventListener('submit', this._domEventHandler, true);
|
|
395
|
+
document1?.removeEventListener('change', this._domEventHandler, true);
|
|
396
|
+
document1?.removeEventListener('click', this._domEventHandler, true);
|
|
397
|
+
this._domEventHandler = void 0;
|
|
398
|
+
}
|
|
399
|
+
if (this._copiedTextHandler) {
|
|
400
|
+
document1?.removeEventListener('copy', this._copiedTextHandler, true);
|
|
401
|
+
document1?.removeEventListener('cut', this._copiedTextHandler, true);
|
|
402
|
+
document1?.removeEventListener('paste', this._copiedTextHandler, true);
|
|
403
|
+
this._copiedTextHandler = void 0;
|
|
404
|
+
}
|
|
405
|
+
this._listenerWindow = void 0;
|
|
406
|
+
this._listenerDocument = void 0;
|
|
407
|
+
this._initialized = false;
|
|
408
|
+
}
|
|
409
|
+
startIfEnabled() {
|
|
410
|
+
if (!this.isEnabled) this._clearPointer();
|
|
411
|
+
if (!this._disposed && this._client && this.isEnabled && !this._initialized) {
|
|
412
|
+
this._addDomEventHandlers();
|
|
413
|
+
this._initialized = true;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
onRemoteConfig(result) {
|
|
417
|
+
if (this._disposed) return;
|
|
418
|
+
this._hasReceivedConfigResponse = true;
|
|
419
|
+
if (!result.ok) return void this.startIfEnabled();
|
|
420
|
+
const response = result.config;
|
|
421
|
+
if (response.elementsChainAsString) this._elementsChainAsString = response.elementsChainAsString;
|
|
422
|
+
const optOut = response['autocapture_opt_out'];
|
|
423
|
+
if ((0, core_namespaceObject.isBoolean)(optOut)) {
|
|
424
|
+
this._client?.kv.set(external_constants_js_namespaceObject.AUTOCAPTURE_DISABLED_SERVER_SIDE, optOut);
|
|
425
|
+
this._isDisabledServerSide = optOut;
|
|
426
|
+
}
|
|
427
|
+
this.startIfEnabled();
|
|
428
|
+
}
|
|
429
|
+
setElementSelectors(selectors, owner = this) {
|
|
430
|
+
if (this._disposed) return;
|
|
431
|
+
if (selectors.size) this._elementSelectorsByOwner.set(owner, new Set(selectors));
|
|
432
|
+
else this._elementSelectorsByOwner.delete(owner);
|
|
433
|
+
const combined = new Set();
|
|
434
|
+
this._elementSelectorsByOwner.forEach((contribution)=>{
|
|
435
|
+
contribution.forEach((selector)=>combined.add(selector));
|
|
436
|
+
});
|
|
437
|
+
this._elementSelectors = combined;
|
|
438
|
+
}
|
|
439
|
+
getElementSelectors(element, additionalElement) {
|
|
440
|
+
const elementSelectors = [];
|
|
441
|
+
this._elementSelectors?.forEach((selector)=>{
|
|
442
|
+
const matchedElements = getDocument()?.querySelectorAll(selector);
|
|
443
|
+
matchedElements?.forEach((matchedElement)=>{
|
|
444
|
+
if ((element === matchedElement || additionalElement === matchedElement) && !(0, core_namespaceObject.includes)(elementSelectors, selector)) elementSelectors.push(selector);
|
|
445
|
+
});
|
|
446
|
+
});
|
|
447
|
+
return elementSelectors;
|
|
448
|
+
}
|
|
449
|
+
get isEnabled() {
|
|
450
|
+
if (this._disposed) return false;
|
|
451
|
+
const persistedServerDisabled = this._client?.kv.get(external_constants_js_namespaceObject.AUTOCAPTURE_DISABLED_SERVER_SIDE);
|
|
452
|
+
const memoryDisabled = this._isDisabledServerSide;
|
|
453
|
+
const config = this._refreshConfig();
|
|
454
|
+
if (!config.remoteRequestsDisabled && !this._hasReceivedConfigResponse) return false;
|
|
455
|
+
const clientConfigOnly = config.remoteRequestsDisabled && !this._hasReceivedConfigResponse;
|
|
456
|
+
if ((0, core_namespaceObject.isNull)(memoryDisabled) && !(0, core_namespaceObject.isBoolean)(persistedServerDisabled) && !clientConfigOnly) return false;
|
|
457
|
+
const disabledServer = this._isDisabledServerSide ?? !!persistedServerDisabled;
|
|
458
|
+
const disabledClient = !config.enabled;
|
|
459
|
+
return !disabledClient && !disabledServer;
|
|
460
|
+
}
|
|
461
|
+
_captureEvent(e, eventName = '$autocapture', targetOverride) {
|
|
462
|
+
if (!this.isEnabled) return void this._clearPointer();
|
|
463
|
+
let target = targetOverride || (0, autocapture_utils_js_namespaceObject.getEventTarget)(e);
|
|
464
|
+
if ((0, element_utils_js_namespaceObject.isTextNode)(target)) target = target.parentNode || null;
|
|
465
|
+
const config = this._compileUrlPatterns();
|
|
466
|
+
if ('$autocapture' === eventName && 'click' === e.type && e instanceof MouseEvent) {
|
|
467
|
+
if (!!config.rageclick && this.rageclicks?.isRageClick(e.clientX, e.clientY, e.timeStamp || new Date().getTime())) {
|
|
468
|
+
if ((0, autocapture_utils_js_namespaceObject.shouldCaptureRageclick)(target, config.rageclick)) this._captureEvent(e, '$rageclick', targetOverride);
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
const isClipboardAutocapture = eventName === COPY_AUTOCAPTURE_EVENT;
|
|
472
|
+
const eventConfig = isClipboardAutocapture ? {
|
|
473
|
+
...config,
|
|
474
|
+
dom_event_allowlist: void 0
|
|
475
|
+
} : config;
|
|
476
|
+
if (target && (0, autocapture_utils_js_namespaceObject.shouldCaptureDomEvent)(target, e, eventConfig, isClipboardAutocapture, isClipboardAutocapture ? [
|
|
477
|
+
'copy',
|
|
478
|
+
'cut',
|
|
479
|
+
'paste'
|
|
480
|
+
] : void 0, {
|
|
481
|
+
config: {
|
|
482
|
+
get_current_url: config.getCurrentUrl
|
|
483
|
+
}
|
|
484
|
+
})) {
|
|
485
|
+
const { props, explicitNoCapture, target: attributedTarget } = autocapturePropertiesForElement(target, {
|
|
486
|
+
e,
|
|
487
|
+
maskAllElementAttributes: config.maskAllElementAttributes,
|
|
488
|
+
maskAllText: config.maskAllText,
|
|
489
|
+
elementAttributeIgnoreList: config.element_attribute_ignorelist,
|
|
490
|
+
elementsChainAsString: this._elementsChainAsString,
|
|
491
|
+
disableCaptureUrlHashes: config.disableCaptureUrlHashes
|
|
492
|
+
});
|
|
493
|
+
if (explicitNoCapture) return false;
|
|
494
|
+
const elementSelectors = this.getElementSelectors(target, attributedTarget);
|
|
495
|
+
if (elementSelectors && elementSelectors.length > 0) props['$element_selectors'] = elementSelectors;
|
|
496
|
+
if (eventName === COPY_AUTOCAPTURE_EVENT) {
|
|
497
|
+
const clipType = e.type || 'clipboard';
|
|
498
|
+
if ('paste' !== clipType) {
|
|
499
|
+
const selectedText = getWindow()?.getSelection()?.toString();
|
|
500
|
+
const selectedContent = (0, autocapture_utils_js_namespaceObject.makeSafeText)(selectedText);
|
|
501
|
+
if (!selectedContent) return false;
|
|
502
|
+
props['$selected_content'] = selectedContent;
|
|
503
|
+
props['$clipboard_text_length'] = selectedText?.length ?? 0;
|
|
504
|
+
}
|
|
505
|
+
props['$copy_type'] = clipType;
|
|
506
|
+
}
|
|
507
|
+
this._client?.capture(eventName, props);
|
|
508
|
+
return true;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
isBrowserSupported() {
|
|
512
|
+
return (0, core_namespaceObject.isFunction)(getDocument()?.querySelectorAll);
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
exports.Autocapture = __webpack_exports__.Autocapture;
|
|
516
|
+
exports.AutocaptureExtension = __webpack_exports__.AutocaptureExtension;
|
|
517
|
+
exports.autocapturePropertiesForElement = __webpack_exports__.autocapturePropertiesForElement;
|
|
518
|
+
exports.getAugmentPropertiesFromElement = __webpack_exports__.getAugmentPropertiesFromElement;
|
|
519
|
+
exports.getDefaultProperties = __webpack_exports__.getDefaultProperties;
|
|
520
|
+
exports.getPropertiesFromElement = __webpack_exports__.getPropertiesFromElement;
|
|
521
|
+
exports.previousElementSibling = __webpack_exports__.previousElementSibling;
|
|
522
|
+
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
523
|
+
"Autocapture",
|
|
524
|
+
"AutocaptureExtension",
|
|
525
|
+
"autocapturePropertiesForElement",
|
|
526
|
+
"getAugmentPropertiesFromElement",
|
|
527
|
+
"getDefaultProperties",
|
|
528
|
+
"getPropertiesFromElement",
|
|
529
|
+
"previousElementSibling"
|
|
530
|
+
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
531
|
+
Object.defineProperty(exports, '__esModule', {
|
|
532
|
+
value: true
|
|
533
|
+
});
|