@absmartly/sdk-plugins 1.1.1 → 1.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.
- package/README.md +34 -33
- package/dist/absmartly-cookie.min.js +1 -1
- package/dist/absmartly-dom-changes-core.min.js +1 -1
- package/dist/absmartly-dom-changes-lite.min.js +1 -1
- package/dist/absmartly-overrides-full.min.js +1 -1
- package/dist/absmartly-overrides-lite.min.js +1 -1
- package/dist/absmartly-sdk-plugins.min.js +1 -1
- package/dist/absmartly-vitals.min.js +1 -1
- package/es/cookies/CookiePlugin.js +10 -8
- package/es/cookies/CookiePlugin.js.map +1 -1
- package/es/core/DOMChangesPluginLite.js +226 -248
- package/es/core/DOMChangesPluginLite.js.map +1 -1
- package/es/core/DOMManipulatorLite.js +68 -10
- package/es/core/DOMManipulatorLite.js.map +1 -1
- package/es/core/ExposureTracker.js +136 -11
- package/es/core/ExposureTracker.js.map +1 -1
- package/es/entries/dom-with-overrides-lite.js +3 -0
- package/es/entries/dom-with-overrides-lite.js.map +1 -1
- package/es/index.js +9 -2
- package/es/index.js.map +1 -1
- package/es/overrides/OverridesPlugin.js +2 -2
- package/es/overrides/OverridesPlugin.js.map +1 -1
- package/es/overrides/OverridesPluginLite.js +29 -1
- package/es/overrides/OverridesPluginLite.js.map +1 -1
- package/es/overrides/overridesUtils.js +27 -18
- package/es/overrides/overridesUtils.js.map +1 -1
- package/es/parsers/VariantExtractor.js +80 -67
- package/es/parsers/VariantExtractor.js.map +1 -1
- package/es/url-redirect/URLRedirectExtractor.js +185 -0
- package/es/url-redirect/URLRedirectExtractor.js.map +1 -0
- package/es/url-redirect/URLRedirectMatcher.js +115 -0
- package/es/url-redirect/URLRedirectMatcher.js.map +1 -0
- package/es/url-redirect/URLRedirectPlugin.js +350 -0
- package/es/url-redirect/URLRedirectPlugin.js.map +1 -0
- package/es/url-redirect/index.js +5 -0
- package/es/url-redirect/index.js.map +1 -0
- package/es/url-redirect/types.js +2 -0
- package/es/url-redirect/types.js.map +1 -0
- package/es/utils/persistence.js +278 -0
- package/es/utils/persistence.js.map +1 -0
- package/es/utils/plugin-registry.js +47 -0
- package/es/utils/plugin-registry.js.map +1 -0
- package/es/vitals/WebVitalsPlugin.js +19 -4
- package/es/vitals/WebVitalsPlugin.js.map +1 -1
- package/lib/cookies/CookiePlugin.d.ts +2 -1
- package/lib/cookies/CookiePlugin.js +10 -8
- package/lib/cookies/CookiePlugin.js.map +1 -1
- package/lib/core/DOMChangesPluginLite.d.ts +13 -9
- package/lib/core/DOMChangesPluginLite.js +226 -248
- package/lib/core/DOMChangesPluginLite.js.map +1 -1
- package/lib/core/DOMManipulatorLite.js +68 -10
- package/lib/core/DOMManipulatorLite.js.map +1 -1
- package/lib/core/ExposureTracker.d.ts +6 -0
- package/lib/core/ExposureTracker.js +136 -11
- package/lib/core/ExposureTracker.js.map +1 -1
- package/lib/entries/dom-with-overrides-lite.d.ts +2 -0
- package/lib/entries/dom-with-overrides-lite.js +3 -1
- package/lib/entries/dom-with-overrides-lite.js.map +1 -1
- package/lib/index.d.ts +8 -2
- package/lib/index.js +17 -1
- package/lib/index.js.map +1 -1
- package/lib/overrides/OverridesPlugin.js +2 -2
- package/lib/overrides/OverridesPlugin.js.map +1 -1
- package/lib/overrides/OverridesPluginLite.d.ts +8 -0
- package/lib/overrides/OverridesPluginLite.js +29 -1
- package/lib/overrides/OverridesPluginLite.js.map +1 -1
- package/lib/overrides/overridesUtils.d.ts +10 -5
- package/lib/overrides/overridesUtils.js +28 -18
- package/lib/overrides/overridesUtils.js.map +1 -1
- package/lib/parsers/VariantExtractor.d.ts +4 -5
- package/lib/parsers/VariantExtractor.js +80 -67
- package/lib/parsers/VariantExtractor.js.map +1 -1
- package/lib/types/index.d.ts +5 -12
- package/lib/url-redirect/URLRedirectExtractor.d.ts +16 -0
- package/lib/url-redirect/URLRedirectExtractor.js +188 -0
- package/lib/url-redirect/URLRedirectExtractor.js.map +1 -0
- package/lib/url-redirect/URLRedirectMatcher.d.ts +8 -0
- package/lib/url-redirect/URLRedirectMatcher.js +118 -0
- package/lib/url-redirect/URLRedirectMatcher.js.map +1 -0
- package/lib/url-redirect/URLRedirectPlugin.d.ts +21 -0
- package/lib/url-redirect/URLRedirectPlugin.js +353 -0
- package/lib/url-redirect/URLRedirectPlugin.js.map +1 -0
- package/lib/url-redirect/index.d.ts +4 -0
- package/lib/url-redirect/index.js +25 -0
- package/lib/url-redirect/index.js.map +1 -0
- package/lib/url-redirect/types.d.ts +29 -0
- package/lib/url-redirect/types.js +3 -0
- package/lib/url-redirect/types.js.map +1 -0
- package/lib/utils/persistence.d.ts +23 -0
- package/lib/utils/persistence.js +281 -0
- package/lib/utils/persistence.js.map +1 -0
- package/lib/utils/plugin-registry.d.ts +40 -0
- package/lib/utils/plugin-registry.js +53 -0
- package/lib/utils/plugin-registry.js.map +1 -0
- package/lib/vitals/WebVitalsPlugin.d.ts +2 -0
- package/lib/vitals/WebVitalsPlugin.js +19 -4
- package/lib/vitals/WebVitalsPlugin.js.map +1 -1
- package/package.json +59 -3
- package/types/cookies/CookiePlugin.d.ts +2 -1
- package/types/core/DOMChangesPluginLite.d.ts +13 -9
- package/types/core/ExposureTracker.d.ts +6 -0
- package/types/entries/dom-with-overrides-lite.d.ts +2 -0
- package/types/index.d.ts +8 -2
- package/types/overrides/OverridesPluginLite.d.ts +8 -0
- package/types/overrides/overridesUtils.d.ts +10 -5
- package/types/parsers/VariantExtractor.d.ts +4 -5
- package/types/types/index.d.ts +5 -12
- package/types/url-redirect/URLRedirectExtractor.d.ts +16 -0
- package/types/url-redirect/URLRedirectMatcher.d.ts +8 -0
- package/types/url-redirect/URLRedirectPlugin.d.ts +21 -0
- package/types/url-redirect/index.d.ts +4 -0
- package/types/url-redirect/types.d.ts +29 -0
- package/types/utils/persistence.d.ts +23 -0
- package/types/utils/plugin-registry.d.ts +40 -0
- package/types/vitals/WebVitalsPlugin.d.ts +2 -0
|
@@ -79,19 +79,18 @@ import { ExposureTracker } from './ExposureTracker';
|
|
|
79
79
|
import { HTMLInjector } from './HTMLInjector';
|
|
80
80
|
import { logDebug, logExperimentSummary, logPerformance, DEBUG } from '../utils/debug';
|
|
81
81
|
import { URLMatcher } from '../utils/URLMatcher';
|
|
82
|
+
import { DOMPersistenceManager } from '../utils/persistence';
|
|
83
|
+
import { registerPlugin, unregisterPlugin } from '../utils/plugin-registry';
|
|
82
84
|
var DOMChangesPluginLite = /** @class */ (function () {
|
|
83
85
|
function DOMChangesPluginLite(config) {
|
|
84
|
-
var
|
|
86
|
+
var _this = this;
|
|
87
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
85
88
|
this.mutationObserver = null;
|
|
86
89
|
this.exposedExperiments = new Set();
|
|
87
90
|
this.eventListeners = new Map();
|
|
88
91
|
this.styleManagers = new Map();
|
|
89
92
|
this.initialized = false;
|
|
90
|
-
this.
|
|
91
|
-
this.persistenceObserver = null;
|
|
92
|
-
this.reapplyingElements = new Set();
|
|
93
|
-
this.reapplyLogThrottle = new Map();
|
|
94
|
-
this.appliedChanges = new Map();
|
|
93
|
+
this.persistenceManager = null;
|
|
95
94
|
this.antiFlickerTimeout = null;
|
|
96
95
|
this.antiFlickerStyleId = 'absmartly-antiflicker';
|
|
97
96
|
this.config = {
|
|
@@ -99,28 +98,54 @@ var DOMChangesPluginLite = /** @class */ (function () {
|
|
|
99
98
|
autoApply: (_a = config.autoApply) !== null && _a !== void 0 ? _a : true,
|
|
100
99
|
spa: (_b = config.spa) !== null && _b !== void 0 ? _b : true,
|
|
101
100
|
visibilityTracking: (_c = config.visibilityTracking) !== null && _c !== void 0 ? _c : true,
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
hideTimeout: (_h = config.hideTimeout) !== null && _h !== void 0 ? _h : 3000,
|
|
108
|
-
hideSelector: (_j = config.hideSelector) !== null && _j !== void 0 ? _j : '[data-absmartly-hide]',
|
|
109
|
-
hideTransition: (_k = config.hideTransition) !== null && _k !== void 0 ? _k : false,
|
|
101
|
+
variableName: (_d = config.variableName) !== null && _d !== void 0 ? _d : '__dom_changes',
|
|
102
|
+
debug: (_e = config.debug) !== null && _e !== void 0 ? _e : false,
|
|
103
|
+
hideUntilReady: (_f = config.hideUntilReady) !== null && _f !== void 0 ? _f : false,
|
|
104
|
+
hideTimeout: (_g = config.hideTimeout) !== null && _g !== void 0 ? _g : 3000,
|
|
105
|
+
hideTransition: (_h = config.hideTransition) !== null && _h !== void 0 ? _h : false,
|
|
110
106
|
};
|
|
111
107
|
if (!this.config.context) {
|
|
112
108
|
throw new Error('[ABsmartly] Context is required');
|
|
113
109
|
}
|
|
114
|
-
|
|
110
|
+
console.log("[ABsmartly] DOMChangesPluginLite v".concat(DOMChangesPluginLite.VERSION, " initialized"));
|
|
115
111
|
if (this.config.hideUntilReady) {
|
|
116
112
|
this.hideContent();
|
|
117
113
|
}
|
|
118
114
|
this.domManipulator = new DOMManipulatorLite(this.config.debug, this);
|
|
119
|
-
this.variantExtractor = new VariantExtractor(this.config.context, this.config.
|
|
115
|
+
this.variantExtractor = new VariantExtractor(this.config.context, this.config.variableName, this.config.debug);
|
|
120
116
|
this.exposureTracker = new ExposureTracker(this.config.context, this.config.debug);
|
|
121
117
|
this.htmlInjector = new HTMLInjector(this.config.debug);
|
|
118
|
+
this.persistenceManager = new DOMPersistenceManager({
|
|
119
|
+
debug: this.config.debug,
|
|
120
|
+
onReapply: function (change, experimentName) {
|
|
121
|
+
logDebug('[DOMChangesPluginLite] Re-applying change due to mutation', {
|
|
122
|
+
experimentName: experimentName,
|
|
123
|
+
selector: change.selector,
|
|
124
|
+
type: change.type,
|
|
125
|
+
});
|
|
126
|
+
_this.domManipulator.applyChange(change, experimentName);
|
|
127
|
+
},
|
|
128
|
+
});
|
|
129
|
+
// Auto-initialize when context is ready
|
|
130
|
+
this.readyPromise = this.config.context
|
|
131
|
+
.ready()
|
|
132
|
+
.then(function () {
|
|
133
|
+
logDebug('[DOMChangesPluginLite] Context is ready, starting initialization');
|
|
134
|
+
return _this.initialize();
|
|
135
|
+
})
|
|
136
|
+
.catch(function (error) {
|
|
137
|
+
logDebug('[DOMChangesPluginLite] ERROR during initialization:', error);
|
|
138
|
+
throw error;
|
|
139
|
+
});
|
|
122
140
|
}
|
|
123
141
|
DOMChangesPluginLite.prototype.ready = function () {
|
|
142
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
143
|
+
return __generator(this, function (_a) {
|
|
144
|
+
return [2 /*return*/, this.readyPromise];
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
};
|
|
148
|
+
DOMChangesPluginLite.prototype.initialize = function () {
|
|
124
149
|
return __awaiter(this, void 0, void 0, function () {
|
|
125
150
|
var startTime, duration, error_1;
|
|
126
151
|
return __generator(this, function (_a) {
|
|
@@ -137,7 +162,6 @@ var DOMChangesPluginLite = /** @class */ (function () {
|
|
|
137
162
|
autoApply: this.config.autoApply,
|
|
138
163
|
spa: this.config.spa,
|
|
139
164
|
visibilityTracking: this.config.visibilityTracking,
|
|
140
|
-
dataSource: this.config.dataSource,
|
|
141
165
|
DEBUG: DEBUG,
|
|
142
166
|
},
|
|
143
167
|
});
|
|
@@ -145,9 +169,14 @@ var DOMChangesPluginLite = /** @class */ (function () {
|
|
|
145
169
|
case 1:
|
|
146
170
|
_a.trys.push([1, 4, , 5]);
|
|
147
171
|
if (this.config.spa) {
|
|
172
|
+
// SPA mode: observe body for React/Vue hydration recovery
|
|
173
|
+
// and listen for URL changes to re-apply changes on navigation
|
|
148
174
|
this.setupMutationObserver();
|
|
149
175
|
this.setupURLChangeListener();
|
|
150
176
|
}
|
|
177
|
+
else {
|
|
178
|
+
logDebug('[DOMChangesPluginLite] SPA mode disabled - skipping body observer');
|
|
179
|
+
}
|
|
151
180
|
if (!this.config.autoApply) return [3 /*break*/, 3];
|
|
152
181
|
// Apply HTML injections and DOM changes in parallel to minimize flickering
|
|
153
182
|
return [4 /*yield*/, this.applyInjectionsAndChanges()];
|
|
@@ -158,6 +187,7 @@ var DOMChangesPluginLite = /** @class */ (function () {
|
|
|
158
187
|
case 3:
|
|
159
188
|
this.initialized = true;
|
|
160
189
|
this.registerWithContext();
|
|
190
|
+
this.registerGlobally();
|
|
161
191
|
this.emit('initialized');
|
|
162
192
|
duration = performance.now() - startTime;
|
|
163
193
|
logPerformance('Plugin initialization', duration);
|
|
@@ -175,13 +205,6 @@ var DOMChangesPluginLite = /** @class */ (function () {
|
|
|
175
205
|
});
|
|
176
206
|
});
|
|
177
207
|
};
|
|
178
|
-
DOMChangesPluginLite.prototype.initialize = function () {
|
|
179
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
180
|
-
return __generator(this, function (_a) {
|
|
181
|
-
return [2 /*return*/, this.ready()];
|
|
182
|
-
});
|
|
183
|
-
});
|
|
184
|
-
};
|
|
185
208
|
DOMChangesPluginLite.prototype.setupMutationObserver = function () {
|
|
186
209
|
var _this = this;
|
|
187
210
|
var observer = new MutationObserver(function (mutations) {
|
|
@@ -190,10 +213,12 @@ var DOMChangesPluginLite = /** @class */ (function () {
|
|
|
190
213
|
if (mutation.type === 'childList') {
|
|
191
214
|
// Check if any added nodes match our applied change selectors
|
|
192
215
|
mutation.addedNodes.forEach(function (node) {
|
|
216
|
+
var _a;
|
|
193
217
|
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
194
218
|
var element_1 = node;
|
|
195
219
|
// Check all experiments with applied changes (not just style changes)
|
|
196
|
-
_this.
|
|
220
|
+
var appliedChanges = ((_a = _this.persistenceManager) === null || _a === void 0 ? void 0 : _a.getAppliedChanges()) || new Map();
|
|
221
|
+
appliedChanges.forEach(function (changes, experimentName) {
|
|
197
222
|
changes.forEach(function (change) {
|
|
198
223
|
try {
|
|
199
224
|
// Check if this new element or any of its descendants match the selector
|
|
@@ -223,11 +248,30 @@ var DOMChangesPluginLite = /** @class */ (function () {
|
|
|
223
248
|
}
|
|
224
249
|
});
|
|
225
250
|
});
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
251
|
+
// Wait for document.body to exist before observing
|
|
252
|
+
// This prevents "parameter 1 is not of type 'Node'" errors when SDK loads in <head>
|
|
253
|
+
var startObserving = function () {
|
|
254
|
+
observer.observe(document.body, {
|
|
255
|
+
childList: true,
|
|
256
|
+
subtree: true,
|
|
257
|
+
});
|
|
258
|
+
_this.mutationObserver = observer;
|
|
259
|
+
logDebug('[DOMChangesPluginLite] MutationObserver started on document.body');
|
|
260
|
+
};
|
|
261
|
+
if (document.body) {
|
|
262
|
+
startObserving();
|
|
263
|
+
}
|
|
264
|
+
else {
|
|
265
|
+
// Use MutationObserver on documentElement to detect when body is added
|
|
266
|
+
var bodyObserver = new MutationObserver(function (_mutations, obs) {
|
|
267
|
+
if (document.body) {
|
|
268
|
+
obs.disconnect();
|
|
269
|
+
startObserving();
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
bodyObserver.observe(document.documentElement, { childList: true });
|
|
273
|
+
logDebug('[DOMChangesPluginLite] Waiting for document.body...');
|
|
274
|
+
}
|
|
231
275
|
};
|
|
232
276
|
/**
|
|
233
277
|
* Set up URL change listener for SPA mode
|
|
@@ -294,7 +338,9 @@ var DOMChangesPluginLite = /** @class */ (function () {
|
|
|
294
338
|
// The stylesheets will be reused or cleared on next applyChanges
|
|
295
339
|
this.styleManagers.clear();
|
|
296
340
|
// Clear applied changes
|
|
297
|
-
this.
|
|
341
|
+
if (this.persistenceManager) {
|
|
342
|
+
this.persistenceManager.clearAll();
|
|
343
|
+
}
|
|
298
344
|
// Clear HTML injections
|
|
299
345
|
this.htmlInjector.destroy();
|
|
300
346
|
// Clear variant extractor cache to force re-extraction
|
|
@@ -411,22 +457,46 @@ var DOMChangesPluginLite = /** @class */ (function () {
|
|
|
411
457
|
allExperiments = this.getAllExperimentsData();
|
|
412
458
|
totalApplied = 0;
|
|
413
459
|
experimentStats = new Map();
|
|
414
|
-
logDebug('[
|
|
415
|
-
|
|
460
|
+
logDebug('[APPLY-CHANGES] Experiments found with DOM changes:', {
|
|
461
|
+
experimentNames: Array.from(allExperiments.keys()),
|
|
462
|
+
totalCount: allExperiments.size,
|
|
463
|
+
currentURL: currentURL,
|
|
464
|
+
});
|
|
465
|
+
if (allExperiments.size === 0) {
|
|
466
|
+
logDebug('[APPLY-CHANGES] ⚠️ No experiments found with DOM changes - nothing to process');
|
|
467
|
+
}
|
|
416
468
|
try {
|
|
417
469
|
for (allExperiments_1 = __values(allExperiments), allExperiments_1_1 = allExperiments_1.next(); !allExperiments_1_1.done; allExperiments_1_1 = allExperiments_1.next()) {
|
|
418
470
|
_a = __read(allExperiments_1_1.value, 2), expName = _a[0], experimentData = _a[1];
|
|
471
|
+
logDebug("[APPLY-CHANGES] [".concat(expName, "] Starting to process experiment"), {
|
|
472
|
+
experimentName: expName,
|
|
473
|
+
currentURL: currentURL,
|
|
474
|
+
});
|
|
419
475
|
// Skip if filtering by specific experiment
|
|
420
476
|
if (experimentName && expName !== experimentName) {
|
|
477
|
+
logDebug("[APPLY-CHANGES] [".concat(expName, "] \u23ED\uFE0F Skipping - filtering for different experiment"), {
|
|
478
|
+
filteringFor: experimentName,
|
|
479
|
+
});
|
|
421
480
|
continue;
|
|
422
481
|
}
|
|
423
482
|
currentVariant = this.config.context.peek(expName);
|
|
483
|
+
if (currentVariant === undefined || currentVariant === null) {
|
|
484
|
+
logDebug("[APPLY-CHANGES] [".concat(expName, "] \u23ED\uFE0F Skipping - no variant assigned (peek returned ").concat(currentVariant, ")"), {
|
|
485
|
+
experimentName: expName,
|
|
486
|
+
});
|
|
487
|
+
continue;
|
|
488
|
+
}
|
|
489
|
+
logDebug("[APPLY-CHANGES] [".concat(expName, "] User assigned to variant ").concat(currentVariant));
|
|
424
490
|
variantData = experimentData.variantData, urlFilter = experimentData.urlFilter, globalDefaults = experimentData.globalDefaults;
|
|
425
491
|
anyVariantMatchesURL = this.variantExtractor.anyVariantMatchesURL(expName, currentURL);
|
|
426
492
|
if (!anyVariantMatchesURL) {
|
|
427
|
-
logDebug("[
|
|
493
|
+
logDebug("[APPLY-CHANGES] [".concat(expName, "] \u23ED\uFE0F Skipping - no variant matches URL: ").concat(currentURL), {
|
|
494
|
+
experimentName: expName,
|
|
495
|
+
currentURL: currentURL,
|
|
496
|
+
});
|
|
428
497
|
continue;
|
|
429
498
|
}
|
|
499
|
+
logDebug("[APPLY-CHANGES] [".concat(expName, "] \u2713 At least one variant matches current URL"));
|
|
430
500
|
shouldApplyVisualChanges = this.shouldApplyVisualChanges(variantData, urlFilter, currentURL);
|
|
431
501
|
changes = this.extractChangesFromData(variantData, globalDefaults);
|
|
432
502
|
allVariantChanges = this.extractAllVariantChanges(expName);
|
|
@@ -440,7 +510,9 @@ var DOMChangesPluginLite = /** @class */ (function () {
|
|
|
440
510
|
}
|
|
441
511
|
stats = { total: (changes === null || changes === void 0 ? void 0 : changes.length) || 0, success: 0, pending: 0 };
|
|
442
512
|
if (this.config.debug) {
|
|
443
|
-
logDebug("[ABsmartly] Processing experiment '".concat(expName, "'
|
|
513
|
+
logDebug("[ABsmartly] Processing experiment '".concat(expName, "' - User is in variant ").concat(currentVariant, ":"), {
|
|
514
|
+
experimentName: expName,
|
|
515
|
+
userVariant: currentVariant,
|
|
444
516
|
urlMatches: shouldApplyVisualChanges,
|
|
445
517
|
changeCount: (changes === null || changes === void 0 ? void 0 : changes.length) || 0,
|
|
446
518
|
userVariantHasChanges: ((changes === null || changes === void 0 ? void 0 : changes.length) || 0) > 0,
|
|
@@ -451,11 +523,28 @@ var DOMChangesPluginLite = /** @class */ (function () {
|
|
|
451
523
|
}); })) || [],
|
|
452
524
|
});
|
|
453
525
|
}
|
|
526
|
+
// Log if user is in control variant (no changes)
|
|
527
|
+
if (!changes || changes.length === 0) {
|
|
528
|
+
if (this.config.debug) {
|
|
529
|
+
logDebug("[ABsmartly] User is in control variant ".concat(currentVariant, " with no changes, but will still track for SRM prevention"), {
|
|
530
|
+
experimentName: expName,
|
|
531
|
+
currentVariant: currentVariant,
|
|
532
|
+
});
|
|
533
|
+
}
|
|
534
|
+
}
|
|
454
535
|
// Apply visual changes only if URL matches for user's variant AND user has changes
|
|
455
536
|
if (shouldApplyVisualChanges && changes && changes.length > 0) {
|
|
456
537
|
try {
|
|
457
538
|
for (changes_1 = (e_2 = void 0, __values(changes)), changes_1_1 = changes_1.next(); !changes_1_1.done; changes_1_1 = changes_1.next()) {
|
|
458
539
|
change = changes_1_1.value;
|
|
540
|
+
// Skip delete changes with viewport triggers - they must be applied AFTER exposure
|
|
541
|
+
// Otherwise the element is removed before it can be observed
|
|
542
|
+
if (change.type === 'delete' && change.trigger_on_view) {
|
|
543
|
+
if (this.config.debug) {
|
|
544
|
+
logDebug("[ABsmartly] Deferring delete change until after viewport trigger for '".concat(expName, "'"), { selector: change.selector });
|
|
545
|
+
}
|
|
546
|
+
continue;
|
|
547
|
+
}
|
|
459
548
|
success = this.domManipulator.applyChange(change, expName);
|
|
460
549
|
if (success) {
|
|
461
550
|
totalApplied++;
|
|
@@ -573,14 +662,41 @@ var DOMChangesPluginLite = /** @class */ (function () {
|
|
|
573
662
|
finally { if (e_3) throw e_3.error; }
|
|
574
663
|
}
|
|
575
664
|
if (this.config.debug) {
|
|
576
|
-
logDebug("[
|
|
665
|
+
logDebug("[TRIGGER-DETECTION] [".concat(expName, "] Final trigger decision for '").concat(expName, "':"), {
|
|
666
|
+
experimentName: expName,
|
|
667
|
+
userVariant: currentVariant,
|
|
668
|
+
hasImmediateTrigger: hasAnyImmediateTriggerInAnyVariant,
|
|
669
|
+
hasViewportTrigger: hasAnyViewportTriggerInAnyVariant,
|
|
670
|
+
willRegisterExperiment: hasAnyViewportTriggerInAnyVariant || hasAnyImmediateTriggerInAnyVariant,
|
|
671
|
+
userChangesCount: (changes === null || changes === void 0 ? void 0 : changes.length) || 0,
|
|
672
|
+
allVariantsChangesCount: allVariantChanges.map(function (vc) { return vc.length; }),
|
|
673
|
+
});
|
|
577
674
|
}
|
|
578
675
|
// CRITICAL: Always register experiment for tracking if ANY variant has ANY trigger type
|
|
579
676
|
// This prevents SRM even when user's variant doesn't match URL filter
|
|
580
677
|
// Pass the URL-filtered trigger flags to ExposureTracker
|
|
581
678
|
if (hasAnyViewportTriggerInAnyVariant || hasAnyImmediateTriggerInAnyVariant) {
|
|
679
|
+
logDebug("[TRIGGER-DETECTION] [".concat(expName, "] \u2713 REGISTERING EXPERIMENT - Calling exposureTracker.registerExperiment()"), {
|
|
680
|
+
experimentName: expName,
|
|
681
|
+
userVariant: currentVariant,
|
|
682
|
+
hasImmediateTrigger: hasAnyImmediateTriggerInAnyVariant,
|
|
683
|
+
hasViewportTrigger: hasAnyViewportTriggerInAnyVariant,
|
|
684
|
+
changesForUser: (changes === null || changes === void 0 ? void 0 : changes.length) || 0,
|
|
685
|
+
allVariantCounts: allVariantChanges.map(function (vc, idx) { return ({
|
|
686
|
+
variant: idx,
|
|
687
|
+
count: vc.length,
|
|
688
|
+
}); }),
|
|
689
|
+
});
|
|
582
690
|
this.exposureTracker.registerExperiment(expName, currentVariant || 0, changes || [], allVariantChanges, hasAnyImmediateTriggerInAnyVariant, hasAnyViewportTriggerInAnyVariant);
|
|
583
691
|
}
|
|
692
|
+
else {
|
|
693
|
+
logDebug("[TRIGGER-DETECTION] [".concat(expName, "] \u26A0\uFE0F No triggers detected - experiment will NOT be registered!"), {
|
|
694
|
+
experimentName: expName,
|
|
695
|
+
userVariant: currentVariant,
|
|
696
|
+
hasAnyChangesInAnyVariant: hasAnyChangesInAnyVariant,
|
|
697
|
+
allVariantsChangesCount: allVariantChanges.map(function (vc) { return vc.length; }),
|
|
698
|
+
});
|
|
699
|
+
}
|
|
584
700
|
// Note: We do NOT call treatment() here anymore to avoid duplicate calls.
|
|
585
701
|
// The ExposureTracker.registerExperiment() will call triggerExposure() internally
|
|
586
702
|
// when hasImmediateTrigger is true (see ExposureTracker line 169-174).
|
|
@@ -636,18 +752,43 @@ var DOMChangesPluginLite = /** @class */ (function () {
|
|
|
636
752
|
var e_5, _a;
|
|
637
753
|
var experiments = new Map();
|
|
638
754
|
var allVariants = this.variantExtractor.extractAllChanges();
|
|
755
|
+
logDebug('[GET-EXPERIMENTS] Extracting experiment data from context', {
|
|
756
|
+
experimentsWithChanges: Array.from(allVariants.keys()),
|
|
757
|
+
totalCount: allVariants.size,
|
|
758
|
+
});
|
|
639
759
|
try {
|
|
640
760
|
for (var allVariants_1 = __values(allVariants), allVariants_1_1 = allVariants_1.next(); !allVariants_1_1.done; allVariants_1_1 = allVariants_1.next()) {
|
|
641
761
|
var _b = __read(allVariants_1_1.value, 1), expName = _b[0];
|
|
642
762
|
var currentVariant = this.config.context.peek(expName);
|
|
763
|
+
logDebug("[GET-EXPERIMENTS] [".concat(expName, "] Checking experiment"), {
|
|
764
|
+
experimentName: expName,
|
|
765
|
+
currentVariant: currentVariant,
|
|
766
|
+
variantIsValid: currentVariant !== undefined && currentVariant !== null,
|
|
767
|
+
});
|
|
643
768
|
if (currentVariant === undefined || currentVariant === null) {
|
|
769
|
+
logDebug("[GET-EXPERIMENTS] [".concat(expName, "] \u23ED\uFE0F Skipping - context.peek() returned ").concat(currentVariant));
|
|
644
770
|
continue;
|
|
645
771
|
}
|
|
646
772
|
var variantsData = this.variantExtractor.getAllVariantsData(expName);
|
|
647
773
|
var variantData = variantsData.get(currentVariant);
|
|
774
|
+
if (this.config.debug) {
|
|
775
|
+
logDebug("[GET-EXPERIMENTS] [".concat(expName, "] Variant data lookup:"), {
|
|
776
|
+
experimentName: expName,
|
|
777
|
+
userVariant: currentVariant,
|
|
778
|
+
variantDataExists: !!variantData,
|
|
779
|
+
allVariantsInMap: Array.from(variantsData.keys()),
|
|
780
|
+
userVariantInMap: variantsData.has(currentVariant),
|
|
781
|
+
});
|
|
782
|
+
}
|
|
648
783
|
if (!variantData) {
|
|
649
|
-
|
|
784
|
+
logDebug("[GET-EXPERIMENTS] [".concat(expName, "] \u26A0\uFE0F User's variant ").concat(currentVariant, " has no DOM changes (control variant)"), {
|
|
785
|
+
availableVariants: Array.from(variantsData.keys()),
|
|
786
|
+
note: 'Will still track for SRM prevention',
|
|
787
|
+
});
|
|
788
|
+
// Don't skip! Include experiments even if user's variant has no changes
|
|
789
|
+
// This is critical for SRM prevention - we need to track ALL experiments
|
|
650
790
|
}
|
|
791
|
+
logDebug("[GET-EXPERIMENTS] [".concat(expName, "] \u2713 Including experiment (variant ").concat(currentVariant, ")"));
|
|
651
792
|
// Extract URL filter and global defaults if using wrapped format
|
|
652
793
|
var urlFilter = null;
|
|
653
794
|
var globalDefaults = {};
|
|
@@ -680,12 +821,15 @@ var DOMChangesPluginLite = /** @class */ (function () {
|
|
|
680
821
|
* Extract changes from DOMChangesData and apply global defaults
|
|
681
822
|
*/
|
|
682
823
|
DOMChangesPluginLite.prototype.extractChangesFromData = function (data, globalDefaults) {
|
|
824
|
+
if (!data) {
|
|
825
|
+
return null;
|
|
826
|
+
}
|
|
683
827
|
var changes = null;
|
|
684
828
|
// Extract changes array
|
|
685
829
|
if (Array.isArray(data)) {
|
|
686
830
|
changes = data;
|
|
687
831
|
}
|
|
688
|
-
else if (
|
|
832
|
+
else if (typeof data === 'object' && 'changes' in data) {
|
|
689
833
|
changes = data.changes;
|
|
690
834
|
}
|
|
691
835
|
if (!changes || changes.length === 0) {
|
|
@@ -742,6 +886,10 @@ var DOMChangesPluginLite = /** @class */ (function () {
|
|
|
742
886
|
* Determine if visual changes should be applied based on URL filter
|
|
743
887
|
*/
|
|
744
888
|
DOMChangesPluginLite.prototype.shouldApplyVisualChanges = function (variantData, urlFilter, url) {
|
|
889
|
+
// No data for this variant - no changes to apply
|
|
890
|
+
if (!variantData) {
|
|
891
|
+
return false;
|
|
892
|
+
}
|
|
745
893
|
// Legacy array format has no URL filter - always apply
|
|
746
894
|
if (Array.isArray(variantData)) {
|
|
747
895
|
return true;
|
|
@@ -875,9 +1023,9 @@ var DOMChangesPluginLite = /** @class */ (function () {
|
|
|
875
1023
|
this.mutationObserver.disconnect();
|
|
876
1024
|
this.mutationObserver = null;
|
|
877
1025
|
}
|
|
878
|
-
if (this.
|
|
879
|
-
this.
|
|
880
|
-
this.
|
|
1026
|
+
if (this.persistenceManager) {
|
|
1027
|
+
this.persistenceManager.destroy();
|
|
1028
|
+
this.persistenceManager = null;
|
|
881
1029
|
}
|
|
882
1030
|
// Clean up anti-flicker timeout and style
|
|
883
1031
|
if (this.antiFlickerTimeout !== null) {
|
|
@@ -890,11 +1038,8 @@ var DOMChangesPluginLite = /** @class */ (function () {
|
|
|
890
1038
|
}
|
|
891
1039
|
this.eventListeners.clear();
|
|
892
1040
|
this.exposedExperiments.clear();
|
|
893
|
-
this.watchedElements = new WeakMap();
|
|
894
|
-
this.appliedChanges.clear();
|
|
895
|
-
this.reapplyingElements.clear();
|
|
896
|
-
this.reapplyLogThrottle.clear();
|
|
897
1041
|
this.unregisterFromContext();
|
|
1042
|
+
this.unregisterGlobally();
|
|
898
1043
|
this.initialized = false;
|
|
899
1044
|
if (this.config.debug) {
|
|
900
1045
|
logDebug('[ABsmartly] DOM Changes Plugin Lite destroyed');
|
|
@@ -933,13 +1078,38 @@ var DOMChangesPluginLite = /** @class */ (function () {
|
|
|
933
1078
|
}
|
|
934
1079
|
}
|
|
935
1080
|
};
|
|
1081
|
+
/**
|
|
1082
|
+
* Register plugin in global registry for detection
|
|
1083
|
+
*/
|
|
1084
|
+
DOMChangesPluginLite.prototype.registerGlobally = function () {
|
|
1085
|
+
registerPlugin('dom', {
|
|
1086
|
+
name: 'DOMChangesPluginLite',
|
|
1087
|
+
version: DOMChangesPluginLite.VERSION,
|
|
1088
|
+
initialized: true,
|
|
1089
|
+
timestamp: Date.now(),
|
|
1090
|
+
capabilities: ['spa', 'visibility', 'auto-apply'],
|
|
1091
|
+
instance: this,
|
|
1092
|
+
});
|
|
1093
|
+
if (this.config.debug) {
|
|
1094
|
+
logDebug('[ABsmartly] DOMChangesPluginLite registered in global window.__ABSMARTLY_PLUGINS__');
|
|
1095
|
+
}
|
|
1096
|
+
};
|
|
1097
|
+
/**
|
|
1098
|
+
* Unregister plugin from global registry
|
|
1099
|
+
*/
|
|
1100
|
+
DOMChangesPluginLite.prototype.unregisterGlobally = function () {
|
|
1101
|
+
unregisterPlugin('dom');
|
|
1102
|
+
if (this.config.debug) {
|
|
1103
|
+
logDebug('[ABsmartly] DOMChangesPluginLite unregistered from global registry');
|
|
1104
|
+
}
|
|
1105
|
+
};
|
|
936
1106
|
/**
|
|
937
1107
|
* Hide content to prevent flicker before experiments are applied
|
|
938
1108
|
*/
|
|
939
1109
|
DOMChangesPluginLite.prototype.hideContent = function () {
|
|
940
1110
|
var _this = this;
|
|
941
|
-
var
|
|
942
|
-
if (!
|
|
1111
|
+
var selector = this.config.hideUntilReady;
|
|
1112
|
+
if (!selector)
|
|
943
1113
|
return;
|
|
944
1114
|
// Check if style already exists (prevent duplicate injection)
|
|
945
1115
|
if (document.getElementById(this.antiFlickerStyleId)) {
|
|
@@ -948,7 +1118,6 @@ var DOMChangesPluginLite = /** @class */ (function () {
|
|
|
948
1118
|
var style = document.createElement('style');
|
|
949
1119
|
style.id = this.antiFlickerStyleId;
|
|
950
1120
|
var hasTransition = this.config.hideTransition !== false;
|
|
951
|
-
var selector = mode === 'body' ? 'body' : this.config.hideSelector || '[data-absmartly-hide]';
|
|
952
1121
|
if (hasTransition) {
|
|
953
1122
|
// Use both visibility:hidden and opacity:0 for smooth transition
|
|
954
1123
|
style.textContent = "\n ".concat(selector, " {\n visibility: hidden !important;\n opacity: 0 !important;\n }\n ");
|
|
@@ -958,7 +1127,7 @@ var DOMChangesPluginLite = /** @class */ (function () {
|
|
|
958
1127
|
style.textContent = "\n ".concat(selector, " {\n visibility: hidden !important;\n }\n ");
|
|
959
1128
|
}
|
|
960
1129
|
document.head.appendChild(style);
|
|
961
|
-
// Set timeout to show content even if experiments fail to load
|
|
1130
|
+
// Set timeout to show content even if experiments fail to load or timeout expires
|
|
962
1131
|
this.antiFlickerTimeout = window.setTimeout(function () {
|
|
963
1132
|
if (_this.config.debug) {
|
|
964
1133
|
logDebug("[ABsmartly] Anti-flicker timeout reached (".concat(_this.config.hideTimeout, "ms), showing content"));
|
|
@@ -966,11 +1135,11 @@ var DOMChangesPluginLite = /** @class */ (function () {
|
|
|
966
1135
|
_this.showContent();
|
|
967
1136
|
}, this.config.hideTimeout);
|
|
968
1137
|
if (this.config.debug) {
|
|
969
|
-
logDebug("[ABsmartly] Anti-flicker enabled (
|
|
1138
|
+
logDebug("[ABsmartly] Anti-flicker enabled (selector: '".concat(selector, "', transition: ").concat(hasTransition ? this.config.hideTransition : 'none', ", timeout: ").concat(this.config.hideTimeout, "ms)"));
|
|
970
1139
|
}
|
|
971
1140
|
};
|
|
972
1141
|
/**
|
|
973
|
-
* Show hidden content after experiments are applied
|
|
1142
|
+
* Show hidden content after experiments are applied or timeout expires
|
|
974
1143
|
*/
|
|
975
1144
|
DOMChangesPluginLite.prototype.showContent = function () {
|
|
976
1145
|
var _this = this;
|
|
@@ -985,8 +1154,7 @@ var DOMChangesPluginLite = /** @class */ (function () {
|
|
|
985
1154
|
var hasTransition = this.config.hideTransition !== false;
|
|
986
1155
|
if (hasTransition) {
|
|
987
1156
|
// Smooth fade-in: remove visibility, add transition, then animate opacity
|
|
988
|
-
var
|
|
989
|
-
var selector = mode === 'body' ? 'body' : this.config.hideSelector || '[data-absmartly-hide]';
|
|
1157
|
+
var selector = this.config.hideUntilReady;
|
|
990
1158
|
// Step 1: Remove visibility:hidden, keep opacity:0, add transition
|
|
991
1159
|
style.textContent = "\n ".concat(selector, " {\n opacity: 0 !important;\n transition: opacity ").concat(this.config.hideTransition, " !important;\n }\n ");
|
|
992
1160
|
// Step 2: Force reflow to ensure transition applies
|
|
@@ -1014,206 +1182,16 @@ var DOMChangesPluginLite = /** @class */ (function () {
|
|
|
1014
1182
|
}
|
|
1015
1183
|
};
|
|
1016
1184
|
DOMChangesPluginLite.prototype.watchElement = function (element, experimentName, change) {
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
experiments = new Set();
|
|
1020
|
-
this.watchedElements.set(element, experiments);
|
|
1021
|
-
}
|
|
1022
|
-
experiments.add(experimentName);
|
|
1023
|
-
// Store the applied change for this experiment (ALL types: style, class, attribute, html, text, etc.)
|
|
1024
|
-
if (!this.appliedChanges.has(experimentName)) {
|
|
1025
|
-
this.appliedChanges.set(experimentName, []);
|
|
1026
|
-
}
|
|
1027
|
-
var changes = this.appliedChanges.get(experimentName);
|
|
1028
|
-
var isNewWatch = !changes.includes(change);
|
|
1029
|
-
if (isNewWatch) {
|
|
1030
|
-
changes.push(change);
|
|
1031
|
-
// Only log when actually adding a new watch, not on every reapply
|
|
1032
|
-
if (this.config.debug) {
|
|
1033
|
-
var currentStyles_1 = {};
|
|
1034
|
-
if (change.value && typeof change.value === 'object') {
|
|
1035
|
-
Object.keys(change.value).forEach(function (prop) {
|
|
1036
|
-
var cssProp = prop.replace(/([A-Z])/g, '-$1').toLowerCase();
|
|
1037
|
-
currentStyles_1[cssProp] = element.style.getPropertyValue(cssProp);
|
|
1038
|
-
});
|
|
1039
|
-
}
|
|
1040
|
-
logDebug('[WATCH-ELEMENT] Started watching element for persistence/hydration recovery', {
|
|
1041
|
-
experimentName: experimentName,
|
|
1042
|
-
selector: change.selector,
|
|
1043
|
-
element: element.tagName,
|
|
1044
|
-
changeType: change.type,
|
|
1045
|
-
value: change.value,
|
|
1046
|
-
currentStyles: change.type === 'style' ? currentStyles_1 : undefined,
|
|
1047
|
-
timestamp: Date.now(),
|
|
1048
|
-
});
|
|
1049
|
-
}
|
|
1050
|
-
}
|
|
1051
|
-
if (!this.persistenceObserver) {
|
|
1052
|
-
this.setupPersistenceObserver();
|
|
1185
|
+
if (this.persistenceManager) {
|
|
1186
|
+
this.persistenceManager.watchElement(element, experimentName, change);
|
|
1053
1187
|
}
|
|
1054
1188
|
};
|
|
1055
1189
|
DOMChangesPluginLite.prototype.unwatchElement = function (element, experimentName) {
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
experiments.delete(experimentName);
|
|
1059
|
-
if (experiments.size === 0) {
|
|
1060
|
-
this.watchedElements.delete(element);
|
|
1061
|
-
}
|
|
1062
|
-
}
|
|
1063
|
-
};
|
|
1064
|
-
DOMChangesPluginLite.prototype.setupPersistenceObserver = function () {
|
|
1065
|
-
var _this = this;
|
|
1066
|
-
if (this.persistenceObserver)
|
|
1067
|
-
return;
|
|
1068
|
-
if (this.config.debug) {
|
|
1069
|
-
logDebug('[PERSISTENCE-OBSERVER] Setting up persistence observer', {
|
|
1070
|
-
timestamp: Date.now(),
|
|
1071
|
-
watchedElementsCount: this.watchedElements ? 'has WeakMap' : 'no WeakMap',
|
|
1072
|
-
});
|
|
1073
|
-
}
|
|
1074
|
-
this.persistenceObserver = new MutationObserver(function (mutations) {
|
|
1075
|
-
if (_this.config.debug) {
|
|
1076
|
-
logDebug('[MUTATION-DETECTED] Persistence observer detected mutations', {
|
|
1077
|
-
mutationCount: mutations.length,
|
|
1078
|
-
timestamp: Date.now(),
|
|
1079
|
-
mutations: mutations.map(function (m) {
|
|
1080
|
-
var _a;
|
|
1081
|
-
return ({
|
|
1082
|
-
target: m.target.tagName,
|
|
1083
|
-
oldValue: (_a = m.oldValue) === null || _a === void 0 ? void 0 : _a.substring(0, 100),
|
|
1084
|
-
});
|
|
1085
|
-
}),
|
|
1086
|
-
});
|
|
1087
|
-
}
|
|
1088
|
-
mutations.forEach(function (mutation) {
|
|
1089
|
-
var element = mutation.target;
|
|
1090
|
-
if (_this.reapplyingElements.has(element)) {
|
|
1091
|
-
if (_this.config.debug) {
|
|
1092
|
-
logDebug('[MUTATION-SKIP] Skipping mutation - currently reapplying', {
|
|
1093
|
-
element: element.tagName,
|
|
1094
|
-
});
|
|
1095
|
-
}
|
|
1096
|
-
return;
|
|
1097
|
-
}
|
|
1098
|
-
var experiments = _this.watchedElements.get(element);
|
|
1099
|
-
if (experiments) {
|
|
1100
|
-
// Throttle mutation detection logs to once per 5 seconds per element
|
|
1101
|
-
if (_this.config.debug) {
|
|
1102
|
-
var elementKey = "mutation:".concat(element.tagName, ":").concat(element.getAttribute('name') || element.className);
|
|
1103
|
-
var now = Date.now();
|
|
1104
|
-
var lastLogged = _this.reapplyLogThrottle.get(elementKey) || 0;
|
|
1105
|
-
if (now - lastLogged > 5000) {
|
|
1106
|
-
logDebug('[MUTATION-ON-WATCHED] Style mutation detected on watched element', {
|
|
1107
|
-
element: element.tagName,
|
|
1108
|
-
selector: element.getAttribute('name') || element.className,
|
|
1109
|
-
oldValue: mutation.oldValue,
|
|
1110
|
-
newValue: element.getAttribute('style'),
|
|
1111
|
-
experiments: Array.from(experiments),
|
|
1112
|
-
});
|
|
1113
|
-
_this.reapplyLogThrottle.set(elementKey, now);
|
|
1114
|
-
}
|
|
1115
|
-
}
|
|
1116
|
-
experiments.forEach(function (experimentName) {
|
|
1117
|
-
var appliedChanges = _this.appliedChanges.get(experimentName);
|
|
1118
|
-
if (appliedChanges) {
|
|
1119
|
-
appliedChanges.forEach(function (change) {
|
|
1120
|
-
var e_7, _a;
|
|
1121
|
-
// Skip the .matches() check - we already know this element should have this change
|
|
1122
|
-
// because we added it to watchedElements when we applied it successfully.
|
|
1123
|
-
// The .matches() check fails for complex selectors with parent relationships (e.g., "div > p")
|
|
1124
|
-
if (change.type === 'style') {
|
|
1125
|
-
var needsReapply = _this.checkStyleOverwritten(element, change.value);
|
|
1126
|
-
if (needsReapply) {
|
|
1127
|
-
_this.reapplyingElements.add(element);
|
|
1128
|
-
var logKey = "".concat(experimentName, "-").concat(change.selector);
|
|
1129
|
-
var now = Date.now();
|
|
1130
|
-
var lastLogged = _this.reapplyLogThrottle.get(logKey) || 0;
|
|
1131
|
-
if (_this.config.debug && now - lastLogged > 5000) {
|
|
1132
|
-
logDebug('[REAPPLY-TRIGGERED] Reapplying style after mutation (React/framework conflict detected)', {
|
|
1133
|
-
experimentName: experimentName,
|
|
1134
|
-
selector: change.selector,
|
|
1135
|
-
element: element.tagName,
|
|
1136
|
-
timestamp: now,
|
|
1137
|
-
note: 'This happens when the page framework (React/Vue/etc) fights with DOM changes',
|
|
1138
|
-
});
|
|
1139
|
-
_this.reapplyLogThrottle.set(logKey, now);
|
|
1140
|
-
// Cleanup old throttle entries to prevent memory leak
|
|
1141
|
-
if (_this.reapplyLogThrottle.size > 100) {
|
|
1142
|
-
var oldestAllowed = now - 60000; // 1 minute
|
|
1143
|
-
try {
|
|
1144
|
-
for (var _b = __values(_this.reapplyLogThrottle.entries()), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
1145
|
-
var _d = __read(_c.value, 2), key = _d[0], time = _d[1];
|
|
1146
|
-
if (time < oldestAllowed) {
|
|
1147
|
-
_this.reapplyLogThrottle.delete(key);
|
|
1148
|
-
}
|
|
1149
|
-
}
|
|
1150
|
-
}
|
|
1151
|
-
catch (e_7_1) { e_7 = { error: e_7_1 }; }
|
|
1152
|
-
finally {
|
|
1153
|
-
try {
|
|
1154
|
-
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
1155
|
-
}
|
|
1156
|
-
finally { if (e_7) throw e_7.error; }
|
|
1157
|
-
}
|
|
1158
|
-
}
|
|
1159
|
-
}
|
|
1160
|
-
_this.domManipulator.applyChange(change, experimentName);
|
|
1161
|
-
setTimeout(function () {
|
|
1162
|
-
_this.reapplyingElements.delete(element);
|
|
1163
|
-
}, 0);
|
|
1164
|
-
}
|
|
1165
|
-
else if (_this.config.debug) {
|
|
1166
|
-
logDebug('[MUTATION-NO-REAPPLY] Style mutation detected but no reapply needed', {
|
|
1167
|
-
experimentName: experimentName,
|
|
1168
|
-
selector: change.selector,
|
|
1169
|
-
});
|
|
1170
|
-
}
|
|
1171
|
-
}
|
|
1172
|
-
});
|
|
1173
|
-
}
|
|
1174
|
-
});
|
|
1175
|
-
}
|
|
1176
|
-
});
|
|
1177
|
-
});
|
|
1178
|
-
this.persistenceObserver.observe(document.body, {
|
|
1179
|
-
attributes: true,
|
|
1180
|
-
attributeFilter: ['style'],
|
|
1181
|
-
subtree: true,
|
|
1182
|
-
attributeOldValue: true,
|
|
1183
|
-
});
|
|
1184
|
-
if (this.config.debug) {
|
|
1185
|
-
logDebug('[PERSISTENCE-OBSERVER] Setup complete - now observing style mutations', {
|
|
1186
|
-
target: 'document.body',
|
|
1187
|
-
attributeFilter: ['style'],
|
|
1188
|
-
subtree: true,
|
|
1189
|
-
attributeOldValue: true,
|
|
1190
|
-
timestamp: Date.now(),
|
|
1191
|
-
});
|
|
1192
|
-
}
|
|
1193
|
-
};
|
|
1194
|
-
DOMChangesPluginLite.prototype.checkStyleOverwritten = function (element, expectedStyles) {
|
|
1195
|
-
var e_8, _a;
|
|
1196
|
-
try {
|
|
1197
|
-
for (var _b = __values(Object.entries(expectedStyles)), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
1198
|
-
var _d = __read(_c.value, 2), prop = _d[0], value = _d[1];
|
|
1199
|
-
var cssProp = prop.replace(/([A-Z])/g, '-$1').toLowerCase();
|
|
1200
|
-
var currentValue = element.style.getPropertyValue(cssProp);
|
|
1201
|
-
var currentPriority = element.style.getPropertyPriority(cssProp);
|
|
1202
|
-
if (currentValue !== value || (value.includes('!important') && !currentPriority)) {
|
|
1203
|
-
return true;
|
|
1204
|
-
}
|
|
1205
|
-
}
|
|
1206
|
-
}
|
|
1207
|
-
catch (e_8_1) { e_8 = { error: e_8_1 }; }
|
|
1208
|
-
finally {
|
|
1209
|
-
try {
|
|
1210
|
-
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
1211
|
-
}
|
|
1212
|
-
finally { if (e_8) throw e_8.error; }
|
|
1190
|
+
if (this.persistenceManager) {
|
|
1191
|
+
this.persistenceManager.unwatchElement(element, experimentName);
|
|
1213
1192
|
}
|
|
1214
|
-
return false;
|
|
1215
1193
|
};
|
|
1216
|
-
DOMChangesPluginLite.VERSION = '1.
|
|
1194
|
+
DOMChangesPluginLite.VERSION = typeof __VERSION__ !== 'undefined' ? __VERSION__ : '1.1.2';
|
|
1217
1195
|
return DOMChangesPluginLite;
|
|
1218
1196
|
}());
|
|
1219
1197
|
export { DOMChangesPluginLite };
|