@posthog/browser-common 0.1.0 → 0.2.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 (78) hide show
  1. package/README.md +23 -8
  2. package/dist/config.d.ts +9 -0
  3. package/dist/config.js +43 -0
  4. package/dist/config.mjs +9 -0
  5. package/dist/constants.d.ts +3 -0
  6. package/dist/constants.js +44 -0
  7. package/dist/constants.mjs +4 -0
  8. package/dist/token.d.ts +13 -12
  9. package/dist/utils/array-at-polyfill.d.ts +1 -0
  10. package/dist/utils/array-at-polyfill.js +16 -0
  11. package/dist/utils/array-at-polyfill.mjs +11 -0
  12. package/dist/utils/autocapture-utils.d.ts +23 -0
  13. package/dist/utils/autocapture-utils.js +479 -0
  14. package/dist/utils/autocapture-utils.mjs +385 -0
  15. package/dist/utils/blocked-uas.d.ts +17 -0
  16. package/dist/utils/blocked-uas.js +54 -0
  17. package/dist/utils/blocked-uas.mjs +14 -0
  18. package/dist/utils/cookie-utils.d.ts +1 -0
  19. package/dist/utils/cookie-utils.js +49 -0
  20. package/dist/utils/cookie-utils.mjs +15 -0
  21. package/dist/utils/device-model-utils.d.ts +8 -0
  22. package/dist/utils/device-model-utils.js +52 -0
  23. package/dist/utils/device-model-utils.mjs +18 -0
  24. package/dist/utils/element-utils.d.ts +5 -0
  25. package/dist/utils/element-utils.js +67 -0
  26. package/dist/utils/element-utils.mjs +21 -0
  27. package/dist/utils/elements-chain-utils.d.ts +4 -0
  28. package/dist/utils/elements-chain-utils.js +79 -0
  29. package/dist/utils/elements-chain-utils.mjs +36 -0
  30. package/dist/utils/encode-utils.d.ts +8 -0
  31. package/dist/utils/encode-utils.js +39 -0
  32. package/dist/utils/encode-utils.mjs +5 -0
  33. package/dist/utils/event-utils.d.ts +24 -0
  34. package/dist/utils/event-utils.js +344 -0
  35. package/dist/utils/event-utils.mjs +246 -0
  36. package/dist/utils/general-utils.d.ts +30 -0
  37. package/dist/utils/general-utils.js +191 -0
  38. package/dist/utils/general-utils.mjs +118 -0
  39. package/dist/utils/globals.d.ts +25 -0
  40. package/dist/utils/globals.js +75 -0
  41. package/dist/utils/globals.mjs +14 -0
  42. package/dist/utils/logger.d.ts +16 -0
  43. package/dist/utils/logger.js +83 -0
  44. package/dist/utils/logger.mjs +36 -0
  45. package/dist/utils/matcher-utils.d.ts +3 -0
  46. package/dist/utils/matcher-utils.js +63 -0
  47. package/dist/utils/matcher-utils.mjs +26 -0
  48. package/dist/utils/property-utils.d.ts +23 -0
  49. package/dist/utils/property-utils.js +108 -0
  50. package/dist/utils/property-utils.mjs +65 -0
  51. package/dist/utils/prototype-utils.d.ts +7 -0
  52. package/dist/utils/prototype-utils.js +64 -0
  53. package/dist/utils/prototype-utils.mjs +27 -0
  54. package/dist/utils/regex-utils.d.ts +2 -0
  55. package/dist/utils/regex-utils.js +54 -0
  56. package/dist/utils/regex-utils.mjs +17 -0
  57. package/dist/utils/request-utils.d.ts +15 -0
  58. package/dist/utils/request-utils.js +153 -0
  59. package/dist/utils/request-utils.mjs +95 -0
  60. package/dist/utils/simple-event-emitter.d.ts +5 -0
  61. package/dist/utils/simple-event-emitter.js +51 -0
  62. package/dist/utils/simple-event-emitter.mjs +17 -0
  63. package/dist/utils/stylesheet-loader.d.ts +7 -0
  64. package/dist/utils/stylesheet-loader.js +53 -0
  65. package/dist/utils/stylesheet-loader.mjs +19 -0
  66. package/dist/utils/type-utils.d.ts +2 -0
  67. package/dist/utils/type-utils.js +41 -0
  68. package/dist/utils/type-utils.mjs +4 -0
  69. package/dist/utils/url-targeting-utils.d.ts +28 -0
  70. package/dist/utils/url-targeting-utils.js +56 -0
  71. package/dist/utils/url-targeting-utils.mjs +19 -0
  72. package/dist/utils/uuidv7.d.ts +43 -0
  73. package/dist/utils/uuidv7.js +172 -0
  74. package/dist/utils/uuidv7.js.LICENSE.txt +9 -0
  75. package/dist/utils/uuidv7.mjs +132 -0
  76. package/dist/utils/uuidv7.mjs.LICENSE.txt +9 -0
  77. package/package.json +37 -3
  78. package/LICENSE +0 -353
@@ -0,0 +1,385 @@
1
+ import { each, entries } from "./general-utils.mjs";
2
+ import { includes, isArray, isBoolean, isNullish, isString, isUndefined, trim } from "@posthog/core";
3
+ import { logger } from "./logger.mjs";
4
+ import { window as external_globals_mjs_window } from "./globals.mjs";
5
+ import { getTargetingUrl } from "./url-targeting-utils.mjs";
6
+ import { isElementNode, isShadowRoot, isTag, isTextNode } from "./element-utils.mjs";
7
+ const MAX_DOM_ANCESTOR_DEPTH = 1000;
8
+ function splitClassString(s) {
9
+ return s ? trim(s).split(/\s+/) : [];
10
+ }
11
+ function checkForURLMatches(urlsList, instance) {
12
+ const url = getTargetingUrl(instance);
13
+ return !!(url && urlsList && urlsList.some((regex)=>url.match(regex)));
14
+ }
15
+ function getClassNames(el) {
16
+ let className = '';
17
+ switch(typeof el.className){
18
+ case 'string':
19
+ className = el.className;
20
+ break;
21
+ case 'object':
22
+ className = (el.className && 'baseVal' in el.className ? el.className.baseVal : null) || el.getAttribute('class') || '';
23
+ break;
24
+ default:
25
+ className = '';
26
+ }
27
+ return splitClassString(className);
28
+ }
29
+ function makeSafeText(s) {
30
+ if (isNullish(s)) return null;
31
+ return trim(s).split(/(\s+)/).filter((s)=>shouldCaptureValue(s)).join('').replace(/[\r\n]/g, ' ').replace(/[ ]+/g, ' ').substring(0, 255);
32
+ }
33
+ function getSafeText(el) {
34
+ let elText = '';
35
+ if (shouldCaptureElement(el) && !isSensitiveElement(el) && el.childNodes && el.childNodes.length) each(el.childNodes, function(child) {
36
+ if (isTextNode(child) && child.textContent) elText += makeSafeText(child.textContent) ?? '';
37
+ });
38
+ return trim(elText);
39
+ }
40
+ function getEventTarget(e) {
41
+ if (isUndefined(e.target)) return e.srcElement || null;
42
+ if (e.target?.shadowRoot) return e.composedPath()[0] || null;
43
+ return e.target || null;
44
+ }
45
+ const autocaptureCompatibleElements = [
46
+ 'a',
47
+ 'button',
48
+ 'form',
49
+ 'input',
50
+ 'select',
51
+ 'textarea',
52
+ 'label'
53
+ ];
54
+ function checkIfElementTreePassesElementAllowList(elements, autocaptureConfig) {
55
+ const allowlist = autocaptureConfig?.element_allowlist;
56
+ if (isUndefined(allowlist)) return true;
57
+ for (const el of elements)if (allowlist.some((elementType)=>el.tagName.toLowerCase() === elementType)) return true;
58
+ return false;
59
+ }
60
+ function elementMatchesCSSSelector(el, selector) {
61
+ const matches = el.matches || el.matchesSelector || el.msMatchesSelector || el.mozMatchesSelector || el.webkitMatchesSelector || el.oMatchesSelector;
62
+ try {
63
+ return matches ? matches.call(el, selector) : false;
64
+ } catch {
65
+ return false;
66
+ }
67
+ }
68
+ function checkIfElementsMatchCSSSelector(elements, selectorList) {
69
+ if (isUndefined(selectorList)) return true;
70
+ for (const el of elements)if (selectorList.some((selector)=>elementMatchesCSSSelector(el, selector))) return true;
71
+ return false;
72
+ }
73
+ function getParentElement(curEl) {
74
+ const parentNode = curEl.parentNode;
75
+ if (!parentNode || !isElementNode(parentNode)) return false;
76
+ return parentNode;
77
+ }
78
+ const DEFAULT_AUTOCAPTURE_IGNORE_LIST = [
79
+ '.ph-no-autocapture',
80
+ '[data-ph-no-autocapture]'
81
+ ];
82
+ const DEFAULT_CONTENT_IGNORELIST = [
83
+ 'next',
84
+ 'previous',
85
+ 'prev',
86
+ '>',
87
+ '<'
88
+ ];
89
+ const DEFAULT_CONTENT_IGNORELIST_WITH_STEPPERS = [
90
+ ...DEFAULT_CONTENT_IGNORELIST,
91
+ '+',
92
+ '-',
93
+ "\u2212",
94
+ "\u2013"
95
+ ];
96
+ const MAX_CONTENT_IGNORELIST_ENTRIES = 10;
97
+ const matchesContentKeyword = (text, keyword)=>/[a-z0-9]/i.test(keyword) ? text.includes(keyword) : text === keyword;
98
+ function shouldIgnoreByContent(contentIgnorelist, elementsWithText) {
99
+ if (false === contentIgnorelist || isUndefined(contentIgnorelist)) return false;
100
+ let keywords;
101
+ if (true === contentIgnorelist) keywords = DEFAULT_CONTENT_IGNORELIST;
102
+ else {
103
+ if (!isArray(contentIgnorelist)) return false;
104
+ if (contentIgnorelist.length > MAX_CONTENT_IGNORELIST_ENTRIES) {
105
+ logger.error(`[PostHog] content_ignorelist array cannot exceed ${MAX_CONTENT_IGNORELIST_ENTRIES} items. Use css_selector_ignorelist for more complex matching.`);
106
+ return false;
107
+ }
108
+ keywords = contentIgnorelist.map((k)=>k.toLowerCase());
109
+ }
110
+ return elementsWithText.some(({ safeText, ariaLabel })=>keywords.some((keyword)=>matchesContentKeyword(safeText, keyword) || matchesContentKeyword(ariaLabel, keyword)));
111
+ }
112
+ const DEFAULT_DEAD_CLICK_IGNORE_LIST = [
113
+ '.ph-no-deadclick',
114
+ '.ph-no-capture'
115
+ ];
116
+ function shouldCaptureDeadClick(el, _config) {
117
+ if (!external_globals_mjs_window || cannotCheckForAutocapture(el)) return false;
118
+ const selectorIgnoreList = isBoolean(_config) ? DEFAULT_DEAD_CLICK_IGNORE_LIST : _config?.css_selector_ignorelist ?? DEFAULT_DEAD_CLICK_IGNORE_LIST;
119
+ const { targetElementList } = getElementAndParentsForElement(el, false);
120
+ return !checkIfElementsMatchCSSSelector(targetElementList, selectorIgnoreList);
121
+ }
122
+ const DEFAULT_RAGE_CLICK_IGNORE_LIST = [
123
+ '.ph-no-rageclick',
124
+ '.ph-no-capture'
125
+ ];
126
+ const TEXT_SELECTION_INPUT_TYPES = [
127
+ '',
128
+ 'text',
129
+ 'search',
130
+ 'email',
131
+ 'password',
132
+ 'url',
133
+ 'tel',
134
+ 'number'
135
+ ];
136
+ function isContentEditableTarget(el) {
137
+ if (el.isContentEditable) return true;
138
+ const contentEditable = el.getAttribute?.('contenteditable');
139
+ return 'true' === contentEditable || '' === contentEditable;
140
+ }
141
+ function isTextSelectionTarget(el) {
142
+ if (!el || !isElementNode(el)) return false;
143
+ if (isTag(el, 'textarea')) return true;
144
+ if (isTag(el, 'input')) return includes(TEXT_SELECTION_INPUT_TYPES, (el.getAttribute('type') || '').toLowerCase());
145
+ return isContentEditableTarget(el);
146
+ }
147
+ function shouldCaptureRageclick(el, _config) {
148
+ if (!external_globals_mjs_window || cannotCheckForAutocapture(el)) return false;
149
+ let selectorIgnoreList;
150
+ let contentIgnorelist;
151
+ let ignoreTextSelection;
152
+ if (isBoolean(_config)) {
153
+ selectorIgnoreList = _config ? DEFAULT_RAGE_CLICK_IGNORE_LIST : false;
154
+ contentIgnorelist = void 0;
155
+ ignoreTextSelection = false;
156
+ } else {
157
+ selectorIgnoreList = _config?.css_selector_ignorelist ?? DEFAULT_RAGE_CLICK_IGNORE_LIST;
158
+ contentIgnorelist = _config?.content_ignorelist;
159
+ ignoreTextSelection = _config?.ignore_text_selection ?? false;
160
+ }
161
+ if (false === selectorIgnoreList) return false;
162
+ if (ignoreTextSelection && isTextSelectionTarget(el)) return false;
163
+ const { targetElementList } = getElementAndParentsForElement(el, false);
164
+ const elementsWithText = targetElementList.map((element)=>({
165
+ safeText: getSafeText(element).toLowerCase(),
166
+ ariaLabel: element.getAttribute('aria-label')?.toLowerCase().trim() || ''
167
+ }));
168
+ if (shouldIgnoreByContent(contentIgnorelist, elementsWithText)) return false;
169
+ return !checkIfElementsMatchCSSSelector(targetElementList, selectorIgnoreList);
170
+ }
171
+ const cannotCheckForAutocapture = (el)=>!el || isTag(el, 'html') || !isElementNode(el);
172
+ const getElementAndParentsForElement = (el, captureOnAnyElement)=>{
173
+ if (!external_globals_mjs_window || cannotCheckForAutocapture(el)) return {
174
+ parentIsUsefulElement: false,
175
+ targetElementList: []
176
+ };
177
+ let parentIsUsefulElement = false;
178
+ const targetElementList = [
179
+ el
180
+ ];
181
+ let curEl = el;
182
+ while(curEl.parentNode && !isTag(curEl, 'body')){
183
+ if (isShadowRoot(curEl.parentNode)) {
184
+ targetElementList.push(curEl.parentNode.host);
185
+ curEl = curEl.parentNode.host;
186
+ continue;
187
+ }
188
+ const parentNode = getParentElement(curEl);
189
+ if (!parentNode) break;
190
+ if (captureOnAnyElement || autocaptureCompatibleElements.indexOf(parentNode.tagName.toLowerCase()) > -1) parentIsUsefulElement = true;
191
+ else try {
192
+ const compStyles = external_globals_mjs_window.getComputedStyle(parentNode);
193
+ if (compStyles && 'pointer' === compStyles.getPropertyValue('cursor')) parentIsUsefulElement = true;
194
+ } catch {}
195
+ targetElementList.push(parentNode);
196
+ curEl = parentNode;
197
+ }
198
+ return {
199
+ parentIsUsefulElement,
200
+ targetElementList
201
+ };
202
+ };
203
+ function shouldSkipDeadClick(el) {
204
+ if (!external_globals_mjs_window || cannotCheckForAutocapture(el)) return false;
205
+ const { targetElementList } = getElementAndParentsForElement(el, false);
206
+ return targetElementList.some((node)=>isTag(node, 'a'));
207
+ }
208
+ function shouldCaptureDomEvent(el, event, autocaptureConfig, captureOnAnyElement, allowedEventTypes, instance) {
209
+ if (!external_globals_mjs_window || cannotCheckForAutocapture(el)) return false;
210
+ if (autocaptureConfig?.url_allowlist) {
211
+ if (!checkForURLMatches(autocaptureConfig.url_allowlist, instance)) return false;
212
+ }
213
+ if (autocaptureConfig?.url_ignorelist) {
214
+ if (checkForURLMatches(autocaptureConfig.url_ignorelist, instance)) return false;
215
+ }
216
+ if (autocaptureConfig?.dom_event_allowlist) {
217
+ const allowlist = autocaptureConfig.dom_event_allowlist;
218
+ if (allowlist && !allowlist.some((eventType)=>event.type === eventType)) return false;
219
+ }
220
+ const { parentIsUsefulElement, targetElementList } = getElementAndParentsForElement(el, captureOnAnyElement);
221
+ if (!checkIfElementTreePassesElementAllowList(targetElementList, autocaptureConfig)) return false;
222
+ if (!checkIfElementsMatchCSSSelector(targetElementList, autocaptureConfig?.css_selector_allowlist)) return false;
223
+ const selectorIgnoreList = autocaptureConfig?.css_selector_ignorelist ?? DEFAULT_AUTOCAPTURE_IGNORE_LIST;
224
+ if (checkIfElementsMatchCSSSelector(targetElementList, selectorIgnoreList)) return false;
225
+ try {
226
+ const compStyles = external_globals_mjs_window.getComputedStyle(el);
227
+ if (compStyles && 'pointer' === compStyles.getPropertyValue('cursor') && 'click' === event.type) return true;
228
+ } catch {}
229
+ const tag = el.tagName.toLowerCase();
230
+ switch(tag){
231
+ case 'html':
232
+ return false;
233
+ case 'form':
234
+ return (allowedEventTypes || [
235
+ 'submit'
236
+ ]).indexOf(event.type) >= 0;
237
+ case 'input':
238
+ case 'select':
239
+ case 'textarea':
240
+ return (allowedEventTypes || [
241
+ 'change',
242
+ 'click'
243
+ ]).indexOf(event.type) >= 0;
244
+ default:
245
+ if (parentIsUsefulElement) return (allowedEventTypes || [
246
+ 'click'
247
+ ]).indexOf(event.type) >= 0;
248
+ return (allowedEventTypes || [
249
+ 'click'
250
+ ]).indexOf(event.type) >= 0 && (autocaptureCompatibleElements.indexOf(tag) > -1 || 'true' === el.getAttribute('contenteditable'));
251
+ }
252
+ }
253
+ function shouldCaptureElement(el) {
254
+ const seen = new Set();
255
+ let depth = 0;
256
+ for(let curEl = el; curEl.parentNode && !isTag(curEl, 'body'); curEl = curEl.parentNode){
257
+ if (depth++ >= MAX_DOM_ANCESTOR_DEPTH || seen.has(curEl)) return false;
258
+ seen.add(curEl);
259
+ const classes = getClassNames(curEl);
260
+ if (includes(classes, 'ph-sensitive') || includes(classes, 'ph-no-capture')) return false;
261
+ }
262
+ if (includes(getClassNames(el), 'ph-include')) return true;
263
+ const type = el.type || '';
264
+ if (isString(type)) switch(type.toLowerCase()){
265
+ case 'hidden':
266
+ return false;
267
+ case 'password':
268
+ return false;
269
+ }
270
+ const name = el.name || el.id || '';
271
+ if (isString(name)) {
272
+ const sensitiveNameRegex = /^cc|cardnum|ccnum|creditcard|csc|cvc|cvv|exp|pass|pwd|routing|seccode|securitycode|securitynum|socialsec|socsec|ssn/i;
273
+ if (sensitiveNameRegex.test(name.replace(/[^a-zA-Z0-9]/g, ''))) return false;
274
+ }
275
+ return true;
276
+ }
277
+ function isSensitiveElement(el) {
278
+ const allowedInputTypes = [
279
+ 'button',
280
+ 'checkbox',
281
+ 'submit',
282
+ 'reset'
283
+ ];
284
+ if (isTag(el, 'input') && !allowedInputTypes.includes(el.type) || isTag(el, 'select') || isTag(el, 'textarea') || 'true' === el.getAttribute('contenteditable')) return true;
285
+ return false;
286
+ }
287
+ const coreCCPattern = "(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})";
288
+ const anchoredCCRegex = new RegExp(`^(?:${coreCCPattern})$`);
289
+ const unanchoredCCRegex = new RegExp(coreCCPattern);
290
+ const coreSSNPattern = "\\d{3}-?\\d{2}-?\\d{4}";
291
+ const anchoredSSNRegex = new RegExp(`^(${coreSSNPattern})$`);
292
+ const unanchoredSSNRegex = new RegExp(`(${coreSSNPattern})`);
293
+ function shouldCaptureValue(value, anchorRegexes = true) {
294
+ if (isNullish(value)) return false;
295
+ if (isString(value)) {
296
+ value = trim(value);
297
+ const ccRegex = anchorRegexes ? anchoredCCRegex : unanchoredCCRegex;
298
+ if (ccRegex.test((value || '').replace(/[- ]/g, ''))) return false;
299
+ const ssnRegex = anchorRegexes ? anchoredSSNRegex : unanchoredSSNRegex;
300
+ if (ssnRegex.test(value)) return false;
301
+ }
302
+ return true;
303
+ }
304
+ function isAngularStyleAttr(attributeName) {
305
+ if (isString(attributeName)) return '_ngcontent' === attributeName.substring(0, 10) || '_nghost' === attributeName.substring(0, 7);
306
+ return false;
307
+ }
308
+ function getDirectAndNestedSpanText(target) {
309
+ let text = getSafeText(target);
310
+ text = `${text} ${getNestedSpanText(target)}`.trim();
311
+ return shouldCaptureValue(text) ? text : '';
312
+ }
313
+ function getNestedSpanText(target) {
314
+ let text = '';
315
+ if (target && target.childNodes && target.childNodes.length) each(target.childNodes, function(child) {
316
+ if (child && child.tagName?.toLowerCase() === 'span') try {
317
+ const spanText = getSafeText(child);
318
+ text = `${text} ${spanText}`.trim();
319
+ if (child.childNodes && child.childNodes.length) text = `${text} ${getNestedSpanText(child)}`.trim();
320
+ } catch (e) {
321
+ logger.error('[AutoCapture]', e);
322
+ }
323
+ });
324
+ return text;
325
+ }
326
+ function getElementsChainString(elements) {
327
+ return elementsToString(extractElements(elements));
328
+ }
329
+ function escapeQuotes(input) {
330
+ return input.replace(/"|\\"/g, '\\"');
331
+ }
332
+ function elementsToString(elements) {
333
+ const ret = elements.map((element)=>{
334
+ let el_string = '';
335
+ if (element.tag_name) el_string += element.tag_name;
336
+ if (element.attr_class) {
337
+ element.attr_class.sort();
338
+ for (const single_class of element.attr_class)el_string += `.${single_class.replace(/"/g, '')}`;
339
+ }
340
+ const attributes = {
341
+ ...element.text ? {
342
+ text: element.text
343
+ } : {},
344
+ 'nth-child': element.nth_child ?? 0,
345
+ 'nth-of-type': element.nth_of_type ?? 0,
346
+ ...element.href ? {
347
+ href: element.href
348
+ } : {},
349
+ ...element.attr_id ? {
350
+ attr_id: element.attr_id
351
+ } : {},
352
+ ...element.attributes
353
+ };
354
+ const sortedAttributes = {};
355
+ entries(attributes).sort(([a], [b])=>a.localeCompare(b)).forEach(([key, value])=>sortedAttributes[escapeQuotes(key.toString())] = escapeQuotes(value.toString()));
356
+ el_string += ':';
357
+ el_string += entries(sortedAttributes).map(([key, value])=>`${key}="${value}"`).join('');
358
+ return el_string;
359
+ });
360
+ return ret.join(';');
361
+ }
362
+ function extractElements(elements) {
363
+ return elements.map((el)=>{
364
+ const attributes = {};
365
+ const response = {
366
+ text: el['$el_text']?.slice(0, 400),
367
+ tag_name: el['tag_name'],
368
+ href: el['attr__href']?.slice(0, 2048),
369
+ attr_class: extractAttrClass(el),
370
+ attr_id: el['attr__id'],
371
+ nth_child: el['nth_child'],
372
+ nth_of_type: el['nth_of_type'],
373
+ attributes
374
+ };
375
+ entries(el).filter(([key])=>0 === key.indexOf('attr__')).forEach(([key, value])=>response.attributes[key] = value);
376
+ return response;
377
+ });
378
+ }
379
+ function extractAttrClass(el) {
380
+ const attr_class = el['attr__class'];
381
+ if (!attr_class) return;
382
+ if (isArray(attr_class)) return attr_class;
383
+ return splitClassString(attr_class);
384
+ }
385
+ export { DEFAULT_CONTENT_IGNORELIST_WITH_STEPPERS, MAX_DOM_ANCESTOR_DEPTH, autocaptureCompatibleElements, getClassNames, getDirectAndNestedSpanText, getElementsChainString, getEventTarget, getNestedSpanText, getParentElement, getSafeText, isAngularStyleAttr, isSensitiveElement, isTextSelectionTarget, makeSafeText, shouldCaptureDeadClick, shouldCaptureDomEvent, shouldCaptureElement, shouldCaptureRageclick, shouldCaptureValue, shouldSkipDeadClick, splitClassString };
@@ -0,0 +1,17 @@
1
+ export { DEFAULT_BLOCKED_UA_STRS, isBlockedUA } from '@posthog/core';
2
+ export interface NavigatorUAData {
3
+ brands?: {
4
+ brand: string;
5
+ version: string;
6
+ }[];
7
+ platform?: string;
8
+ getHighEntropyValues?: (hints: string[]) => Promise<{
9
+ model?: string;
10
+ }>;
11
+ }
12
+ declare global {
13
+ interface Navigator {
14
+ userAgentData?: NavigatorUAData;
15
+ }
16
+ }
17
+ export declare const isLikelyBot: (navigator: Navigator | undefined, customBlockedUserAgents: string[]) => boolean;
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.d = (exports1, definition)=>{
5
+ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
6
+ enumerable: true,
7
+ get: definition[key]
8
+ });
9
+ };
10
+ })();
11
+ (()=>{
12
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
13
+ })();
14
+ (()=>{
15
+ __webpack_require__.r = (exports1)=>{
16
+ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
17
+ value: 'Module'
18
+ });
19
+ Object.defineProperty(exports1, '__esModule', {
20
+ value: true
21
+ });
22
+ };
23
+ })();
24
+ var __webpack_exports__ = {};
25
+ __webpack_require__.r(__webpack_exports__);
26
+ __webpack_require__.d(__webpack_exports__, {
27
+ DEFAULT_BLOCKED_UA_STRS: ()=>core_namespaceObject.DEFAULT_BLOCKED_UA_STRS,
28
+ isBlockedUA: ()=>core_namespaceObject.isBlockedUA,
29
+ isLikelyBot: ()=>isLikelyBot
30
+ });
31
+ const core_namespaceObject = require("@posthog/core");
32
+ const isLikelyBot = function(navigator, customBlockedUserAgents) {
33
+ if (!navigator) return false;
34
+ const ua = navigator.userAgent;
35
+ if (ua) {
36
+ if ((0, core_namespaceObject.isBlockedUA)(ua, customBlockedUserAgents)) return true;
37
+ }
38
+ try {
39
+ const uaData = navigator?.userAgentData;
40
+ if (uaData?.brands && uaData.brands.some((brandObj)=>(0, core_namespaceObject.isBlockedUA)(brandObj?.brand, customBlockedUserAgents))) return true;
41
+ } catch {}
42
+ return !!navigator.webdriver;
43
+ };
44
+ exports.DEFAULT_BLOCKED_UA_STRS = __webpack_exports__.DEFAULT_BLOCKED_UA_STRS;
45
+ exports.isBlockedUA = __webpack_exports__.isBlockedUA;
46
+ exports.isLikelyBot = __webpack_exports__.isLikelyBot;
47
+ for(var __webpack_i__ in __webpack_exports__)if (-1 === [
48
+ "DEFAULT_BLOCKED_UA_STRS",
49
+ "isBlockedUA",
50
+ "isLikelyBot"
51
+ ].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
52
+ Object.defineProperty(exports, '__esModule', {
53
+ value: true
54
+ });
@@ -0,0 +1,14 @@
1
+ import { DEFAULT_BLOCKED_UA_STRS, isBlockedUA } from "@posthog/core";
2
+ const isLikelyBot = function(navigator, customBlockedUserAgents) {
3
+ if (!navigator) return false;
4
+ const ua = navigator.userAgent;
5
+ if (ua) {
6
+ if (isBlockedUA(ua, customBlockedUserAgents)) return true;
7
+ }
8
+ try {
9
+ const uaData = navigator?.userAgentData;
10
+ if (uaData?.brands && uaData.brands.some((brandObj)=>isBlockedUA(brandObj?.brand, customBlockedUserAgents))) return true;
11
+ } catch {}
12
+ return !!navigator.webdriver;
13
+ };
14
+ export { DEFAULT_BLOCKED_UA_STRS, isBlockedUA, isLikelyBot };
@@ -0,0 +1 @@
1
+ export declare const getCookieValue: (name: string) => string | null | undefined;
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.d = (exports1, definition)=>{
5
+ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
6
+ enumerable: true,
7
+ get: definition[key]
8
+ });
9
+ };
10
+ })();
11
+ (()=>{
12
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
13
+ })();
14
+ (()=>{
15
+ __webpack_require__.r = (exports1)=>{
16
+ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
17
+ value: 'Module'
18
+ });
19
+ Object.defineProperty(exports1, '__esModule', {
20
+ value: true
21
+ });
22
+ };
23
+ })();
24
+ var __webpack_exports__ = {};
25
+ __webpack_require__.r(__webpack_exports__);
26
+ __webpack_require__.d(__webpack_exports__, {
27
+ getCookieValue: ()=>getCookieValue
28
+ });
29
+ const external_globals_js_namespaceObject = require("./globals.js");
30
+ const getCookieValue = (name)=>{
31
+ if (!external_globals_js_namespaceObject.document) return;
32
+ try {
33
+ const nameEQ = name + '=';
34
+ const cookies = external_globals_js_namespaceObject.document.cookie.split(';').filter((cookie)=>cookie.length);
35
+ for(let i = 0; i < cookies.length; i++){
36
+ let cookie = cookies[i];
37
+ while(' ' == cookie.charAt(0))cookie = cookie.substring(1, cookie.length);
38
+ if (0 === cookie.indexOf(nameEQ)) return decodeURIComponent(cookie.substring(nameEQ.length, cookie.length));
39
+ }
40
+ } catch {}
41
+ return null;
42
+ };
43
+ exports.getCookieValue = __webpack_exports__.getCookieValue;
44
+ for(var __webpack_i__ in __webpack_exports__)if (-1 === [
45
+ "getCookieValue"
46
+ ].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
47
+ Object.defineProperty(exports, '__esModule', {
48
+ value: true
49
+ });
@@ -0,0 +1,15 @@
1
+ import { document as external_globals_mjs_document } from "./globals.mjs";
2
+ const getCookieValue = (name)=>{
3
+ if (!external_globals_mjs_document) return;
4
+ try {
5
+ const nameEQ = name + '=';
6
+ const cookies = external_globals_mjs_document.cookie.split(';').filter((cookie)=>cookie.length);
7
+ for(let i = 0; i < cookies.length; i++){
8
+ let cookie = cookies[i];
9
+ while(' ' == cookie.charAt(0))cookie = cookie.substring(1, cookie.length);
10
+ if (0 === cookie.indexOf(nameEQ)) return decodeURIComponent(cookie.substring(nameEQ.length, cookie.length));
11
+ }
12
+ } catch {}
13
+ return null;
14
+ };
15
+ export { getCookieValue };
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Reads the hardware model from `navigator.userAgentData.getHighEntropyValues(['model'])`.
3
+ *
4
+ * Only meaningful on Android Chromium — `undefined` on Safari/Firefox and an empty string on desktop
5
+ * (both treated as absent). A Permissions-Policy block rejects with `NotAllowedError`, which we catch
6
+ * and return `undefined`.
7
+ */
8
+ export declare function getDeviceModel(): Promise<string | undefined>;
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.d = (exports1, definition)=>{
5
+ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
6
+ enumerable: true,
7
+ get: definition[key]
8
+ });
9
+ };
10
+ })();
11
+ (()=>{
12
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
13
+ })();
14
+ (()=>{
15
+ __webpack_require__.r = (exports1)=>{
16
+ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
17
+ value: 'Module'
18
+ });
19
+ Object.defineProperty(exports1, '__esModule', {
20
+ value: true
21
+ });
22
+ };
23
+ })();
24
+ var __webpack_exports__ = {};
25
+ __webpack_require__.r(__webpack_exports__);
26
+ __webpack_require__.d(__webpack_exports__, {
27
+ getDeviceModel: ()=>getDeviceModel
28
+ });
29
+ const core_namespaceObject = require("@posthog/core");
30
+ const external_globals_js_namespaceObject = require("./globals.js");
31
+ const external_logger_js_namespaceObject = require("./logger.js");
32
+ async function getDeviceModel() {
33
+ const uaData = external_globals_js_namespaceObject.navigator?.userAgentData;
34
+ if (!uaData?.getHighEntropyValues) return;
35
+ try {
36
+ const hints = await uaData.getHighEntropyValues([
37
+ 'model'
38
+ ]);
39
+ const model = hints?.model;
40
+ return (0, core_namespaceObject.isString)(model) && model.length > 0 ? model : void 0;
41
+ } catch (e) {
42
+ external_logger_js_namespaceObject.logger.info('Unable to resolve $device_model from userAgentData.getHighEntropyValues', e);
43
+ return;
44
+ }
45
+ }
46
+ exports.getDeviceModel = __webpack_exports__.getDeviceModel;
47
+ for(var __webpack_i__ in __webpack_exports__)if (-1 === [
48
+ "getDeviceModel"
49
+ ].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
50
+ Object.defineProperty(exports, '__esModule', {
51
+ value: true
52
+ });
@@ -0,0 +1,18 @@
1
+ import { isString } from "@posthog/core";
2
+ import { navigator as external_globals_mjs_navigator } from "./globals.mjs";
3
+ import { logger } from "./logger.mjs";
4
+ async function getDeviceModel() {
5
+ const uaData = external_globals_mjs_navigator?.userAgentData;
6
+ if (!uaData?.getHighEntropyValues) return;
7
+ try {
8
+ const hints = await uaData.getHighEntropyValues([
9
+ 'model'
10
+ ]);
11
+ const model = hints?.model;
12
+ return isString(model) && model.length > 0 ? model : void 0;
13
+ } catch (e) {
14
+ logger.info('Unable to resolve $device_model from userAgentData.getHighEntropyValues', e);
15
+ return;
16
+ }
17
+ }
18
+ export { getDeviceModel };
@@ -0,0 +1,5 @@
1
+ export declare function isElementInToolbar(el: EventTarget | null): boolean;
2
+ export declare function isElementNode(el: Node | Element | undefined | null): el is Element;
3
+ export declare function isTag(el: Element | undefined | null, tag: string): el is HTMLElement;
4
+ export declare function isTextNode(el: Element | undefined | null): el is HTMLElement;
5
+ export declare function isShadowRoot(el: Node | ParentNode | undefined | null): el is ShadowRoot;