@adobe/helix-rum-enhancer 2.48.0 → 2.49.0
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/CHANGELOG.md +7 -0
- package/modules/defaults.js +1 -1
- package/modules/dom.js +21 -13
- package/modules/index.js +46 -44
- package/package.json +1 -1
- package/plugins/webcomponent.js +3 -1
- package/src/index.js +66 -55
- package/src/index.md5 +1 -1
- package/src/index.sri +1 -1
- package/src/plugins/a11y.md5 +1 -1
- package/src/plugins/trustarc.md5 +1 -1
- package/src/plugins/usercentrics.md5 +1 -1
- package/src/plugins/video.md5 +1 -1
- package/src/plugins/webcomponent.js +3 -1
- package/src/plugins/webcomponent.map.js +4 -2
- package/src/plugins/webcomponent.md5 +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
# [2.49.0](https://github.com/adobe/helix-rum-enhancer/compare/v2.48.0...v2.49.0) (2026-07-10)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* flag untrusted (synthetic) clicks as bots ([94b2893](https://github.com/adobe/helix-rum-enhancer/commit/94b289333d0c8a33435752c8f48f080b5dfa203d))
|
|
7
|
+
|
|
1
8
|
# [2.48.0](https://github.com/adobe/helix-rum-enhancer/compare/v2.47.3...v2.48.0) (2026-07-08)
|
|
2
9
|
|
|
3
10
|
|
package/modules/defaults.js
CHANGED
|
@@ -11,6 +11,6 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import { fflags } from './fflags.js';
|
|
13
13
|
|
|
14
|
-
export const KNOWN_PROPERTIES = ['weight', 'id', 'referer', 'checkpoint', 't', 'source', 'target', 'cwv', 'CLS', 'FID', 'LCP', 'INP', 'TTFB'];
|
|
14
|
+
export const KNOWN_PROPERTIES = ['weight', 'id', 'referer', 'checkpoint', 't', 'source', 'target', 'cwv', 'CLS', 'FID', 'LCP', 'INP', 'TTFB', 'ua'];
|
|
15
15
|
export const DEFAULT_TRACKING_EVENTS = ['click', 'cwv', 'form', 'viewblock', 'viewmedia', 'loadresource', 'utm', 'paid', 'email', 'consent'];
|
|
16
16
|
fflags.enabled('example', () => DEFAULT_TRACKING_EVENTS.push('example'));
|
package/modules/dom.js
CHANGED
|
@@ -32,12 +32,20 @@ export const targetSelector = (el) => {
|
|
|
32
32
|
}
|
|
33
33
|
};
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
export const untrustedClickPayload = (event) => {
|
|
36
|
+
if (event && event.isTrusted === false) {
|
|
37
|
+
const ua = navigator.userAgent;
|
|
38
|
+
return { ua: ua.includes('+http') ? ua : `${ua} +http://event.untrusted` };
|
|
39
|
+
}
|
|
40
|
+
return {};
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
function walk(el, check) {
|
|
36
44
|
if (!el || el === document.body || el === document.documentElement) {
|
|
37
45
|
return undefined;
|
|
38
46
|
}
|
|
39
47
|
|
|
40
|
-
return
|
|
48
|
+
return check(el) || walk(el.parentElement || (el.parentNode && el.parentNode.host), check);
|
|
41
49
|
}
|
|
42
50
|
|
|
43
51
|
function isDialog(el) {
|
|
@@ -53,19 +61,19 @@ function isButton(el) {
|
|
|
53
61
|
return true;
|
|
54
62
|
}
|
|
55
63
|
if (el.tagName === 'A') {
|
|
56
|
-
return Array.from(el.classList).some((
|
|
64
|
+
return Array.from(el.classList).some((cls) => cls.match(/button|cta/));
|
|
57
65
|
}
|
|
58
66
|
return el.getAttribute('role') === 'button';
|
|
59
67
|
}
|
|
60
68
|
|
|
61
|
-
function
|
|
62
|
-
const
|
|
63
|
-
if (
|
|
64
|
-
const id =
|
|
69
|
+
function srcContext(el) {
|
|
70
|
+
const form = el.closest('form');
|
|
71
|
+
if (form) {
|
|
72
|
+
const id = form.getAttribute('id');
|
|
65
73
|
if (id) {
|
|
66
74
|
return `form#${CSS.escape(id)}`;
|
|
67
75
|
}
|
|
68
|
-
return `form${
|
|
76
|
+
return `form${form.classList.length > 0 ? `.${CSS.escape(form.classList[0])}` : ''}`;
|
|
69
77
|
}
|
|
70
78
|
const block = el.closest('.block[data-block-name]');
|
|
71
79
|
return ((block && `.${block.getAttribute('data-block-name')}`)
|
|
@@ -75,7 +83,7 @@ function getSourceContext(el) {
|
|
|
75
83
|
|| walk(el, (e) => e.id && `#${CSS.escape(e.id)}`));
|
|
76
84
|
}
|
|
77
85
|
|
|
78
|
-
function
|
|
86
|
+
function srcElement(el) {
|
|
79
87
|
const f = el.closest('form');
|
|
80
88
|
if (f && Array.from(f.elements).includes(el)) {
|
|
81
89
|
return (el.tagName.toLowerCase()
|
|
@@ -87,7 +95,7 @@ function getSourceElement(el) {
|
|
|
87
95
|
|| (el.tagName.toLowerCase().match(/^(a|img|video|form)$/) && el.tagName.toLowerCase());
|
|
88
96
|
}
|
|
89
97
|
|
|
90
|
-
function
|
|
98
|
+
function srcId(el) {
|
|
91
99
|
return (el.id && `#${CSS.escape(el.id)}`)
|
|
92
100
|
|| (el.getAttribute('data-block-name') && `.${el.getAttribute('data-block-name')}`)
|
|
93
101
|
|| (el.classList.length > 0 && `.${CSS.escape(el.classList[0])}`);
|
|
@@ -101,9 +109,9 @@ export const sourceSelector = (el) => {
|
|
|
101
109
|
if (el.getAttribute('data-rum-source')) {
|
|
102
110
|
return el.getAttribute('data-rum-source');
|
|
103
111
|
}
|
|
104
|
-
const ctx =
|
|
105
|
-
const name =
|
|
106
|
-
const id =
|
|
112
|
+
const ctx = srcContext(el.parentElement) || '';
|
|
113
|
+
const name = srcElement(el) || '';
|
|
114
|
+
const id = srcId(el) || '';
|
|
107
115
|
return `${ctx} ${name}${id}`.trim() || `"${el.textContent.substring(0, 10)}"`;
|
|
108
116
|
/* c8 ignore next 3 */
|
|
109
117
|
} catch (error) {
|
package/modules/index.js
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
import { KNOWN_PROPERTIES, DEFAULT_TRACKING_EVENTS } from './defaults.js';
|
|
15
15
|
import { urlSanitizers } from './utils.js';
|
|
16
|
-
import { targetSelector, sourceSelector } from './dom.js';
|
|
16
|
+
import { targetSelector, sourceSelector, untrustedClickPayload } from './dom.js';
|
|
17
17
|
import { fflags } from './fflags.js';
|
|
18
18
|
|
|
19
19
|
const { sampleRUM, queue, isSelected } = (window.hlx && window.hlx.rum) ? window.hlx.rum
|
|
@@ -27,19 +27,19 @@ const createMO = (cb) => (window.MutationObserver ? new MutationObserver(cb)
|
|
|
27
27
|
const [blocksMO, mediaMO] = [blocksMCB, mediaMCB].map(createMO);
|
|
28
28
|
|
|
29
29
|
// Check for the presence of a given cookie
|
|
30
|
-
const
|
|
30
|
+
const hasCookie = (key) => document.cookie.split(';').some((c) => c.trim().startsWith(`${key}=`));
|
|
31
31
|
|
|
32
32
|
// Set the base path for the plugins
|
|
33
|
-
const
|
|
33
|
+
const pluginBase = new URL(document.currentScript.src).href.replace(/index(\.map)?\.js/, 'plugins');
|
|
34
34
|
|
|
35
35
|
const CONSENT_PROVIDERS = [
|
|
36
36
|
{
|
|
37
37
|
name: 'onetrust',
|
|
38
|
-
detect: () =>
|
|
38
|
+
detect: () => hasCookie('OptanonAlertBoxClosed') || document.querySelector('#onetrust-banner-sdk, #onetrust-pc-sdk'),
|
|
39
39
|
},
|
|
40
40
|
{
|
|
41
41
|
name: 'trustarc',
|
|
42
|
-
detect: () => ['notice_gdpr_prefs', 'notice_preferences'].some(
|
|
42
|
+
detect: () => ['notice_gdpr_prefs', 'notice_preferences'].some(hasCookie) || document.querySelector('#truste-consent-track'),
|
|
43
43
|
},
|
|
44
44
|
{
|
|
45
45
|
name: 'usercentrics',
|
|
@@ -47,40 +47,40 @@ const CONSENT_PROVIDERS = [
|
|
|
47
47
|
},
|
|
48
48
|
];
|
|
49
49
|
|
|
50
|
-
const
|
|
50
|
+
const getConsent = () => CONSENT_PROVIDERS.find(({ detect }) => detect());
|
|
51
51
|
const bodyChildMO = {
|
|
52
52
|
target: document.body,
|
|
53
53
|
options: { attributes: false, childList: true, subtree: false },
|
|
54
54
|
};
|
|
55
55
|
|
|
56
56
|
const PLUGINS = {
|
|
57
|
-
cwv: `${
|
|
58
|
-
a11y: `${
|
|
57
|
+
cwv: `${pluginBase}/cwv.js`,
|
|
58
|
+
a11y: `${pluginBase}/a11y.js`,
|
|
59
59
|
// Interactive elements
|
|
60
60
|
form: {
|
|
61
|
-
url: `${
|
|
61
|
+
url: `${pluginBase}/form.js`,
|
|
62
62
|
when: () => document.querySelector('form'),
|
|
63
63
|
isBlockDependent: true,
|
|
64
|
-
|
|
64
|
+
moParams: bodyChildMO,
|
|
65
65
|
},
|
|
66
66
|
redirect: {
|
|
67
|
-
url: `${
|
|
67
|
+
url: `${pluginBase}/redirect.js`,
|
|
68
68
|
when: ({ perfEntry: pe, urlParameters: usp }) => (
|
|
69
69
|
pe && (usp.get('redirect_from') || pe.redirectCount > 0 || pe.fetchStart > 50)
|
|
70
70
|
),
|
|
71
71
|
},
|
|
72
|
-
video: { url: `${
|
|
72
|
+
video: { url: `${pluginBase}/video.js`, when: () => document.querySelector('video'), isBlockDependent: true },
|
|
73
73
|
webcomponent: {
|
|
74
|
-
url: `${
|
|
74
|
+
url: `${pluginBase}/webcomponent.js`,
|
|
75
75
|
when: () => [...document.querySelectorAll('*')].some((el) => el.tagName && el.tagName.includes('-')),
|
|
76
76
|
isBlockDependent: true,
|
|
77
77
|
},
|
|
78
78
|
// Martech
|
|
79
|
-
martech: { url: `${
|
|
79
|
+
martech: { url: `${pluginBase}/martech.js`, when: ({ urlParameters }) => urlParameters.size > 0 },
|
|
80
80
|
consent: {
|
|
81
|
-
when: () =>
|
|
81
|
+
when: () => getConsent(),
|
|
82
82
|
isBlockDependent: true,
|
|
83
|
-
|
|
83
|
+
moParams: bodyChildMO,
|
|
84
84
|
},
|
|
85
85
|
// test: broken-plugin
|
|
86
86
|
};
|
|
@@ -94,12 +94,12 @@ function getIntersectionObserver(checkpoint) {
|
|
|
94
94
|
if (!window.IntersectionObserver) {
|
|
95
95
|
return null;
|
|
96
96
|
}
|
|
97
|
-
const
|
|
97
|
+
const obs = new IntersectionObserver((entries) => {
|
|
98
98
|
try {
|
|
99
99
|
entries
|
|
100
100
|
.filter((e) => e.isIntersecting)
|
|
101
101
|
.forEach((e) => {
|
|
102
|
-
|
|
102
|
+
obs.unobserve(e.target); // observe only once
|
|
103
103
|
const target = targetSelector(e.target);
|
|
104
104
|
const source = sourceSelector(e.target);
|
|
105
105
|
if (checkpoint === 'viewmedia') {
|
|
@@ -118,15 +118,16 @@ function getIntersectionObserver(checkpoint) {
|
|
|
118
118
|
// something went wrong
|
|
119
119
|
}
|
|
120
120
|
});
|
|
121
|
-
return
|
|
121
|
+
return obs;
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
-
const
|
|
124
|
+
const PLUGIN_PARAMS = {
|
|
125
125
|
context: document.body,
|
|
126
126
|
fflags,
|
|
127
127
|
sampleRUM,
|
|
128
128
|
sourceSelector,
|
|
129
129
|
targetSelector,
|
|
130
|
+
untrustedClickPayload,
|
|
130
131
|
getIntersectionObserver,
|
|
131
132
|
createMO,
|
|
132
133
|
};
|
|
@@ -137,14 +138,14 @@ function loadPlugin(key, params) {
|
|
|
137
138
|
const plugin = PLUGINS[key];
|
|
138
139
|
const usp = new URLSearchParams(window.location.search);
|
|
139
140
|
if (!pluginCache.has(key) && plugin.when && !plugin.when({ ...params, urlParameters: usp })) {
|
|
140
|
-
if (plugin.
|
|
141
|
+
if (plugin.moParams && !plugin.isBeingObserved) {
|
|
141
142
|
// eslint-disable-next-line no-use-before-define
|
|
142
143
|
createPluginMO(key, params, usp);
|
|
143
144
|
}
|
|
144
145
|
return null;
|
|
145
146
|
}
|
|
146
147
|
if (key === 'consent') {
|
|
147
|
-
plugin.url = `${
|
|
148
|
+
plugin.url = `${pluginBase}/${getConsent().name}.js`;
|
|
148
149
|
}
|
|
149
150
|
|
|
150
151
|
if (!pluginCache.has(key)) {
|
|
@@ -156,7 +157,7 @@ function loadPlugin(key, params) {
|
|
|
156
157
|
.catch(() => { /* silent plugin error catching */ });
|
|
157
158
|
}
|
|
158
159
|
|
|
159
|
-
function loadPlugins(filter = () => true, params =
|
|
160
|
+
function loadPlugins(filter = () => true, params = PLUGIN_PARAMS) {
|
|
160
161
|
Object.entries(PLUGINS)
|
|
161
162
|
.filter(([, plugin]) => filter(plugin))
|
|
162
163
|
.map(([key]) => loadPlugin(key, params));
|
|
@@ -164,19 +165,19 @@ function loadPlugins(filter = () => true, params = PLUGIN_PARAMETERS) {
|
|
|
164
165
|
|
|
165
166
|
function createPluginMO(key, params, usp) {
|
|
166
167
|
const plugin = PLUGINS[key];
|
|
167
|
-
const
|
|
168
|
+
const obs = createMO(() => {
|
|
168
169
|
if (plugin.when({ urlParameters: usp })) {
|
|
169
170
|
plugin.isBeingObserved = false;
|
|
170
|
-
|
|
171
|
+
obs.disconnect();
|
|
171
172
|
loadPlugin(key, params);
|
|
172
173
|
}
|
|
173
174
|
});
|
|
174
175
|
|
|
175
|
-
if (
|
|
176
|
+
if (obs instanceof MutationObserver) {
|
|
176
177
|
plugin.isBeingObserved = true;
|
|
177
|
-
|
|
178
|
-
plugin.
|
|
179
|
-
plugin.
|
|
178
|
+
obs.observe(
|
|
179
|
+
plugin.moParams.target,
|
|
180
|
+
plugin.moParams.options,
|
|
180
181
|
);
|
|
181
182
|
}
|
|
182
183
|
}
|
|
@@ -242,7 +243,7 @@ function addNavigationTracking() {
|
|
|
242
243
|
} else {
|
|
243
244
|
sampleRUM('enter', payload); // enter site
|
|
244
245
|
}
|
|
245
|
-
loadPlugin('redirect', { ...
|
|
246
|
+
loadPlugin('redirect', { ...PLUGIN_PARAMS, perfEntry });
|
|
246
247
|
};
|
|
247
248
|
const processed = new Set(); // avoid processing duplicate types
|
|
248
249
|
new PerformanceObserver((list) => list
|
|
@@ -257,7 +258,7 @@ function addNavigationTracking() {
|
|
|
257
258
|
}
|
|
258
259
|
|
|
259
260
|
function addLoadResourceTracking() {
|
|
260
|
-
const
|
|
261
|
+
const obs = new PerformanceObserver((list) => {
|
|
261
262
|
try {
|
|
262
263
|
const entries = list.getEntries();
|
|
263
264
|
entries
|
|
@@ -265,14 +266,14 @@ function addLoadResourceTracking() {
|
|
|
265
266
|
.filter((e) => window.location.hostname === new URL(e.name).hostname || fflags.has('allresources'))
|
|
266
267
|
.filter((e) => {
|
|
267
268
|
const { pathname, hostname } = new URL(e.name);
|
|
268
|
-
const
|
|
269
|
+
const extMatch = pathname.match(
|
|
269
270
|
hostname !== window.location.hostname
|
|
270
271
|
? '.*(\\.html$|\\.json|\\.js|graphql|api)'
|
|
271
272
|
: '.*(\\.plain\\.html$|\\.json|graphql|api)',
|
|
272
273
|
);
|
|
273
274
|
const isDropIn = fflags.has('allresources') && (pathname.includes('__dropins__/storefront-') || pathname.includes('scripts/dropins/storefront-'));
|
|
274
275
|
const isImage = fflags.has('allresources') && pathname.match(/\.(png|jpe?g|svg)$/i);
|
|
275
|
-
return
|
|
276
|
+
return extMatch || isDropIn || isImage;
|
|
276
277
|
})
|
|
277
278
|
.forEach((e) => {
|
|
278
279
|
sampleRUM('loadresource', { source: e.name, target: Math.round(e.duration) });
|
|
@@ -288,7 +289,7 @@ function addLoadResourceTracking() {
|
|
|
288
289
|
// something went wrong
|
|
289
290
|
}
|
|
290
291
|
});
|
|
291
|
-
|
|
292
|
+
obs.observe({ type: 'resource', buffered: true });
|
|
292
293
|
}
|
|
293
294
|
|
|
294
295
|
// activate blocks mutation observer
|
|
@@ -317,22 +318,22 @@ function activateMediaMO() {
|
|
|
317
318
|
);
|
|
318
319
|
}
|
|
319
320
|
|
|
320
|
-
function addViewBlockTracking(
|
|
321
|
-
const
|
|
322
|
-
if (
|
|
323
|
-
const blocks =
|
|
324
|
-
blocks.forEach((b) =>
|
|
321
|
+
function addViewBlockTracking(el) {
|
|
322
|
+
const blockObs = getIntersectionObserver('viewblock');
|
|
323
|
+
if (blockObs) {
|
|
324
|
+
const blocks = el.getAttribute('data-block-status') ? [el] : el.querySelectorAll('div[data-block-status="loaded"]');
|
|
325
|
+
blocks.forEach((b) => blockObs.observe(b));
|
|
325
326
|
}
|
|
326
327
|
}
|
|
327
328
|
|
|
328
329
|
const observedMedia = new Set();
|
|
329
330
|
function addViewMediaTracking(parent) {
|
|
330
|
-
const
|
|
331
|
-
if (
|
|
331
|
+
const mediaObs = getIntersectionObserver('viewmedia');
|
|
332
|
+
if (mediaObs) {
|
|
332
333
|
parent.querySelectorAll('img, video, audio, iframe').forEach((m) => {
|
|
333
334
|
if (!observedMedia.has(m)) {
|
|
334
335
|
observedMedia.add(m);
|
|
335
|
-
|
|
336
|
+
mediaObs.observe(m);
|
|
336
337
|
}
|
|
337
338
|
});
|
|
338
339
|
}
|
|
@@ -349,7 +350,7 @@ function blocksMCB(mutations) {
|
|
|
349
350
|
.filter((m) => m.type === 'attributes' && m.attributeName === 'data-block-status')
|
|
350
351
|
.filter((m) => m.target.dataset.blockStatus === 'loaded')
|
|
351
352
|
.forEach((m) => {
|
|
352
|
-
addObserver('form', (el) => loadPlugins((p) => p.isBlockDependent, { ...
|
|
353
|
+
addObserver('form', (el) => loadPlugins((p) => p.isBlockDependent, { ...PLUGIN_PARAMS, context: el }), m.target);
|
|
353
354
|
addObserver('viewblock', addViewBlockTracking, m.target);
|
|
354
355
|
});
|
|
355
356
|
}
|
|
@@ -371,7 +372,8 @@ function addTrackingFromConfig() {
|
|
|
371
372
|
if (event.optelHandled) {
|
|
372
373
|
return;
|
|
373
374
|
}
|
|
374
|
-
|
|
375
|
+
// eslint-disable-next-line max-len
|
|
376
|
+
sampleRUM('click', { target: targetSelector(event.target), source: sourceSelector(event.target), ...untrustedClickPayload(event) });
|
|
375
377
|
});
|
|
376
378
|
|
|
377
379
|
// Core tracking
|
package/package.json
CHANGED
package/plugins/webcomponent.js
CHANGED
|
@@ -23,6 +23,7 @@ export default function addWebComponentTracking({
|
|
|
23
23
|
sampleRUM,
|
|
24
24
|
sourceSelector,
|
|
25
25
|
targetSelector,
|
|
26
|
+
untrustedClickPayload,
|
|
26
27
|
createMO,
|
|
27
28
|
}) {
|
|
28
29
|
/**
|
|
@@ -90,7 +91,8 @@ export default function addWebComponentTracking({
|
|
|
90
91
|
}
|
|
91
92
|
// eslint-disable-next-line no-param-reassign
|
|
92
93
|
event.optelHandled = true;
|
|
93
|
-
|
|
94
|
+
// eslint-disable-next-line max-len
|
|
95
|
+
sampleRUM('click', { target: targetSelector(event.target), source: sourceSelector(event.target), ...untrustedClickPayload(event) });
|
|
94
96
|
});
|
|
95
97
|
}
|
|
96
98
|
// look for web components below this element
|
package/src/index.js
CHANGED
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
a11y: [557, 781, 897, 955, 959]
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
-
const KNOWN_PROPERTIES = ['weight', 'id', 'referer', 'checkpoint', 't', 'source', 'target', 'cwv', 'CLS', 'FID', 'LCP', 'INP', 'TTFB'];
|
|
26
|
+
const KNOWN_PROPERTIES = ['weight', 'id', 'referer', 'checkpoint', 't', 'source', 'target', 'cwv', 'CLS', 'FID', 'LCP', 'INP', 'TTFB', 'ua'];
|
|
27
27
|
const DEFAULT_TRACKING_EVENTS = ['click', 'cwv', 'form', 'viewblock', 'viewmedia', 'loadresource', 'utm', 'paid', 'email', 'consent'];
|
|
28
28
|
fflags.enabled('example', () => DEFAULT_TRACKING_EVENTS.push('example'));
|
|
29
29
|
|
|
@@ -57,11 +57,20 @@
|
|
|
57
57
|
return null;
|
|
58
58
|
}
|
|
59
59
|
};
|
|
60
|
-
|
|
60
|
+
const untrustedClickPayload = event => {
|
|
61
|
+
if (event && event.isTrusted === false) {
|
|
62
|
+
const ua = navigator.userAgent;
|
|
63
|
+
return {
|
|
64
|
+
ua: ua.includes('+http') ? ua : `${ua} +http://event.untrusted`
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
return {};
|
|
68
|
+
};
|
|
69
|
+
function walk(el, check) {
|
|
61
70
|
if (!el || el === document.body || el === document.documentElement) {
|
|
62
71
|
return undefined;
|
|
63
72
|
}
|
|
64
|
-
return
|
|
73
|
+
return check(el) || walk(el.parentElement || el.parentNode && el.parentNode.host, check);
|
|
65
74
|
}
|
|
66
75
|
function isDialog(el) {
|
|
67
76
|
const cs = window.getComputedStyle(el);
|
|
@@ -72,30 +81,30 @@
|
|
|
72
81
|
return true;
|
|
73
82
|
}
|
|
74
83
|
if (el.tagName === 'A') {
|
|
75
|
-
return Array.from(el.classList).some(
|
|
84
|
+
return Array.from(el.classList).some(cls => cls.match(/button|cta/));
|
|
76
85
|
}
|
|
77
86
|
return el.getAttribute('role') === 'button';
|
|
78
87
|
}
|
|
79
|
-
function
|
|
80
|
-
const
|
|
81
|
-
if (
|
|
82
|
-
const id =
|
|
88
|
+
function srcContext(el) {
|
|
89
|
+
const form = el.closest('form');
|
|
90
|
+
if (form) {
|
|
91
|
+
const id = form.getAttribute('id');
|
|
83
92
|
if (id) {
|
|
84
93
|
return `form#${CSS.escape(id)}`;
|
|
85
94
|
}
|
|
86
|
-
return `form${
|
|
95
|
+
return `form${form.classList.length > 0 ? `.${CSS.escape(form.classList[0])}` : ''}`;
|
|
87
96
|
}
|
|
88
97
|
const block = el.closest('.block[data-block-name]');
|
|
89
98
|
return block && `.${block.getAttribute('data-block-name')}` || walk(el, isDialog) && 'dialog' || walk(el, e => e.tagName && e.tagName.includes('-') && e.tagName.toLowerCase()) || ['nav', 'header', 'footer', 'aside'].find(t => el.closest(t)) || walk(el, e => e.id && `#${CSS.escape(e.id)}`);
|
|
90
99
|
}
|
|
91
|
-
function
|
|
100
|
+
function srcElement(el) {
|
|
92
101
|
const f = el.closest('form');
|
|
93
102
|
if (f && Array.from(f.elements).includes(el)) {
|
|
94
103
|
return el.tagName.toLowerCase() + (['INPUT', 'BUTTON'].includes(el.tagName) ? `[type='${el.getAttribute('type') || ''}']` : '');
|
|
95
104
|
}
|
|
96
105
|
return walk(el, isButton) && 'button' || el.tagName.toLowerCase().match(/^(a|img|video|form)$/) && el.tagName.toLowerCase();
|
|
97
106
|
}
|
|
98
|
-
function
|
|
107
|
+
function srcId(el) {
|
|
99
108
|
return el.id && `#${CSS.escape(el.id)}` || el.getAttribute('data-block-name') && `.${el.getAttribute('data-block-name')}` || el.classList.length > 0 && `.${CSS.escape(el.classList[0])}`;
|
|
100
109
|
}
|
|
101
110
|
const sourceSelector = el => {
|
|
@@ -106,9 +115,9 @@
|
|
|
106
115
|
if (el.getAttribute('data-rum-source')) {
|
|
107
116
|
return el.getAttribute('data-rum-source');
|
|
108
117
|
}
|
|
109
|
-
const ctx =
|
|
110
|
-
const name =
|
|
111
|
-
const id =
|
|
118
|
+
const ctx = srcContext(el.parentElement) || '';
|
|
119
|
+
const name = srcElement(el) || '';
|
|
120
|
+
const id = srcId(el) || '';
|
|
112
121
|
return `${ctx} ${name}${id}`.trim() || `"${el.textContent.substring(0, 10)}"`;
|
|
113
122
|
} catch (error) {
|
|
114
123
|
return null;
|
|
@@ -122,19 +131,19 @@
|
|
|
122
131
|
} = window.hlx && window.hlx.rum ? window.hlx.rum : {};
|
|
123
132
|
const createMO = cb => window.MutationObserver ? new MutationObserver(cb) : {};
|
|
124
133
|
const [blocksMO, mediaMO] = [blocksMCB, mediaMCB].map(createMO);
|
|
125
|
-
const
|
|
126
|
-
const
|
|
134
|
+
const hasCookie = key => document.cookie.split(';').some(c => c.trim().startsWith(`${key}=`));
|
|
135
|
+
const pluginBase = new URL(document.currentScript.src).href.replace(/index(\.map)?\.js/, 'plugins');
|
|
127
136
|
const CONSENT_PROVIDERS = [{
|
|
128
137
|
name: 'onetrust',
|
|
129
|
-
detect: () =>
|
|
138
|
+
detect: () => hasCookie('OptanonAlertBoxClosed') || document.querySelector('#onetrust-banner-sdk, #onetrust-pc-sdk')
|
|
130
139
|
}, {
|
|
131
140
|
name: 'trustarc',
|
|
132
|
-
detect: () => ['notice_gdpr_prefs', 'notice_preferences'].some(
|
|
141
|
+
detect: () => ['notice_gdpr_prefs', 'notice_preferences'].some(hasCookie) || document.querySelector('#truste-consent-track')
|
|
133
142
|
}, {
|
|
134
143
|
name: 'usercentrics',
|
|
135
144
|
detect: () => window.localStorage.getItem('uc_gcm') || document.querySelector('#usercentrics-root')
|
|
136
145
|
}];
|
|
137
|
-
const
|
|
146
|
+
const getConsent = () => CONSENT_PROVIDERS.find(({
|
|
138
147
|
detect
|
|
139
148
|
}) => detect());
|
|
140
149
|
const bodyChildMO = {
|
|
@@ -146,41 +155,41 @@
|
|
|
146
155
|
}
|
|
147
156
|
};
|
|
148
157
|
const PLUGINS = {
|
|
149
|
-
cwv: `${
|
|
150
|
-
a11y: `${
|
|
158
|
+
cwv: `${pluginBase}/cwv.js`,
|
|
159
|
+
a11y: `${pluginBase}/a11y.js`,
|
|
151
160
|
form: {
|
|
152
|
-
url: `${
|
|
161
|
+
url: `${pluginBase}/form.js`,
|
|
153
162
|
when: () => document.querySelector('form'),
|
|
154
163
|
isBlockDependent: true,
|
|
155
|
-
|
|
164
|
+
moParams: bodyChildMO
|
|
156
165
|
},
|
|
157
166
|
redirect: {
|
|
158
|
-
url: `${
|
|
167
|
+
url: `${pluginBase}/redirect.js`,
|
|
159
168
|
when: ({
|
|
160
169
|
perfEntry: pe,
|
|
161
170
|
urlParameters: usp
|
|
162
171
|
}) => pe && (usp.get('redirect_from') || pe.redirectCount > 0 || pe.fetchStart > 50)
|
|
163
172
|
},
|
|
164
173
|
video: {
|
|
165
|
-
url: `${
|
|
174
|
+
url: `${pluginBase}/video.js`,
|
|
166
175
|
when: () => document.querySelector('video'),
|
|
167
176
|
isBlockDependent: true
|
|
168
177
|
},
|
|
169
178
|
webcomponent: {
|
|
170
|
-
url: `${
|
|
179
|
+
url: `${pluginBase}/webcomponent.js`,
|
|
171
180
|
when: () => [...document.querySelectorAll('*')].some(el => el.tagName && el.tagName.includes('-')),
|
|
172
181
|
isBlockDependent: true
|
|
173
182
|
},
|
|
174
183
|
martech: {
|
|
175
|
-
url: `${
|
|
184
|
+
url: `${pluginBase}/martech.js`,
|
|
176
185
|
when: ({
|
|
177
186
|
urlParameters
|
|
178
187
|
}) => urlParameters.size > 0
|
|
179
188
|
},
|
|
180
189
|
consent: {
|
|
181
|
-
when: () =>
|
|
190
|
+
when: () => getConsent(),
|
|
182
191
|
isBlockDependent: true,
|
|
183
|
-
|
|
192
|
+
moParams: bodyChildMO
|
|
184
193
|
}
|
|
185
194
|
};
|
|
186
195
|
const MAX_EV = 1023;
|
|
@@ -189,10 +198,10 @@
|
|
|
189
198
|
if (!window.IntersectionObserver) {
|
|
190
199
|
return null;
|
|
191
200
|
}
|
|
192
|
-
const
|
|
201
|
+
const obs = new IntersectionObserver(entries => {
|
|
193
202
|
try {
|
|
194
203
|
entries.filter(e => e.isIntersecting).forEach(e => {
|
|
195
|
-
|
|
204
|
+
obs.unobserve(e.target);
|
|
196
205
|
const target = targetSelector(e.target);
|
|
197
206
|
const source = sourceSelector(e.target);
|
|
198
207
|
if (checkpoint === 'viewmedia') {
|
|
@@ -211,14 +220,15 @@
|
|
|
211
220
|
});
|
|
212
221
|
} catch (error) {}
|
|
213
222
|
});
|
|
214
|
-
return
|
|
223
|
+
return obs;
|
|
215
224
|
}
|
|
216
|
-
const
|
|
225
|
+
const PLUGIN_PARAMS = {
|
|
217
226
|
context: document.body,
|
|
218
227
|
fflags,
|
|
219
228
|
sampleRUM,
|
|
220
229
|
sourceSelector,
|
|
221
230
|
targetSelector,
|
|
231
|
+
untrustedClickPayload,
|
|
222
232
|
getIntersectionObserver,
|
|
223
233
|
createMO
|
|
224
234
|
};
|
|
@@ -230,36 +240,36 @@
|
|
|
230
240
|
...params,
|
|
231
241
|
urlParameters: usp
|
|
232
242
|
})) {
|
|
233
|
-
if (plugin.
|
|
243
|
+
if (plugin.moParams && !plugin.isBeingObserved) {
|
|
234
244
|
createPluginMO(key, params, usp);
|
|
235
245
|
}
|
|
236
246
|
return null;
|
|
237
247
|
}
|
|
238
248
|
if (key === 'consent') {
|
|
239
|
-
plugin.url = `${
|
|
249
|
+
plugin.url = `${pluginBase}/${getConsent().name}.js`;
|
|
240
250
|
}
|
|
241
251
|
if (!pluginCache.has(key)) {
|
|
242
252
|
pluginCache.set(key, import(`${plugin.url || plugin}`));
|
|
243
253
|
}
|
|
244
254
|
return pluginCache.get(key).then(p => p.default && p.default(params) || typeof p === 'function' && p(params)).catch(() => {});
|
|
245
255
|
}
|
|
246
|
-
function loadPlugins(filter = () => true, params =
|
|
256
|
+
function loadPlugins(filter = () => true, params = PLUGIN_PARAMS) {
|
|
247
257
|
Object.entries(PLUGINS).filter(([, plugin]) => filter(plugin)).map(([key]) => loadPlugin(key, params));
|
|
248
258
|
}
|
|
249
259
|
function createPluginMO(key, params, usp) {
|
|
250
260
|
const plugin = PLUGINS[key];
|
|
251
|
-
const
|
|
261
|
+
const obs = createMO(() => {
|
|
252
262
|
if (plugin.when({
|
|
253
263
|
urlParameters: usp
|
|
254
264
|
})) {
|
|
255
265
|
plugin.isBeingObserved = false;
|
|
256
|
-
|
|
266
|
+
obs.disconnect();
|
|
257
267
|
loadPlugin(key, params);
|
|
258
268
|
}
|
|
259
269
|
});
|
|
260
|
-
if (
|
|
270
|
+
if (obs instanceof MutationObserver) {
|
|
261
271
|
plugin.isBeingObserved = true;
|
|
262
|
-
|
|
272
|
+
obs.observe(plugin.moParams.target, plugin.moParams.options);
|
|
263
273
|
}
|
|
264
274
|
}
|
|
265
275
|
let maxEvents = MAX_EV;
|
|
@@ -326,7 +336,7 @@
|
|
|
326
336
|
sampleRUM('enter', payload);
|
|
327
337
|
}
|
|
328
338
|
loadPlugin('redirect', {
|
|
329
|
-
...
|
|
339
|
+
...PLUGIN_PARAMS,
|
|
330
340
|
perfEntry
|
|
331
341
|
});
|
|
332
342
|
};
|
|
@@ -339,7 +349,7 @@
|
|
|
339
349
|
});
|
|
340
350
|
}
|
|
341
351
|
function addLoadResourceTracking() {
|
|
342
|
-
const
|
|
352
|
+
const obs = new PerformanceObserver(list => {
|
|
343
353
|
try {
|
|
344
354
|
const entries = list.getEntries();
|
|
345
355
|
entries.filter(e => !e.responseStatus || e.responseStatus < 400).filter(e => window.location.hostname === new URL(e.name).hostname || fflags.has('allresources')).filter(e => {
|
|
@@ -347,10 +357,10 @@
|
|
|
347
357
|
pathname,
|
|
348
358
|
hostname
|
|
349
359
|
} = new URL(e.name);
|
|
350
|
-
const
|
|
360
|
+
const extMatch = pathname.match(hostname !== window.location.hostname ? '.*(\\.html$|\\.json|\\.js|graphql|api)' : '.*(\\.plain\\.html$|\\.json|graphql|api)');
|
|
351
361
|
const isDropIn = fflags.has('allresources') && (pathname.includes('__dropins__/storefront-') || pathname.includes('scripts/dropins/storefront-'));
|
|
352
362
|
const isImage = fflags.has('allresources') && pathname.match(/\.(png|jpe?g|svg)$/i);
|
|
353
|
-
return
|
|
363
|
+
return extMatch || isDropIn || isImage;
|
|
354
364
|
}).forEach(e => {
|
|
355
365
|
sampleRUM('loadresource', {
|
|
356
366
|
source: e.name,
|
|
@@ -365,7 +375,7 @@
|
|
|
365
375
|
});
|
|
366
376
|
} catch (error) {}
|
|
367
377
|
});
|
|
368
|
-
|
|
378
|
+
obs.observe({
|
|
369
379
|
type: 'resource',
|
|
370
380
|
buffered: true
|
|
371
381
|
});
|
|
@@ -392,21 +402,21 @@
|
|
|
392
402
|
childList: true
|
|
393
403
|
});
|
|
394
404
|
}
|
|
395
|
-
function addViewBlockTracking(
|
|
396
|
-
const
|
|
397
|
-
if (
|
|
398
|
-
const blocks =
|
|
399
|
-
blocks.forEach(b =>
|
|
405
|
+
function addViewBlockTracking(el) {
|
|
406
|
+
const blockObs = getIntersectionObserver('viewblock');
|
|
407
|
+
if (blockObs) {
|
|
408
|
+
const blocks = el.getAttribute('data-block-status') ? [el] : el.querySelectorAll('div[data-block-status="loaded"]');
|
|
409
|
+
blocks.forEach(b => blockObs.observe(b));
|
|
400
410
|
}
|
|
401
411
|
}
|
|
402
412
|
const observedMedia = new Set();
|
|
403
413
|
function addViewMediaTracking(parent) {
|
|
404
|
-
const
|
|
405
|
-
if (
|
|
414
|
+
const mediaObs = getIntersectionObserver('viewmedia');
|
|
415
|
+
if (mediaObs) {
|
|
406
416
|
parent.querySelectorAll('img, video, audio, iframe').forEach(m => {
|
|
407
417
|
if (!observedMedia.has(m)) {
|
|
408
418
|
observedMedia.add(m);
|
|
409
|
-
|
|
419
|
+
mediaObs.observe(m);
|
|
410
420
|
}
|
|
411
421
|
});
|
|
412
422
|
}
|
|
@@ -417,7 +427,7 @@
|
|
|
417
427
|
function blocksMCB(mutations) {
|
|
418
428
|
mutations.filter(m => m.type === 'attributes' && m.attributeName === 'data-block-status').filter(m => m.target.dataset.blockStatus === 'loaded').forEach(m => {
|
|
419
429
|
addObserver('form', el => loadPlugins(p => p.isBlockDependent, {
|
|
420
|
-
...
|
|
430
|
+
...PLUGIN_PARAMS,
|
|
421
431
|
context: el
|
|
422
432
|
}), m.target);
|
|
423
433
|
addObserver('viewblock', addViewBlockTracking, m.target);
|
|
@@ -437,7 +447,8 @@
|
|
|
437
447
|
}
|
|
438
448
|
sampleRUM('click', {
|
|
439
449
|
target: targetSelector(event.target),
|
|
440
|
-
source: sourceSelector(event.target)
|
|
450
|
+
source: sourceSelector(event.target),
|
|
451
|
+
...untrustedClickPayload(event)
|
|
441
452
|
});
|
|
442
453
|
});
|
|
443
454
|
addNavigationTracking();
|
package/src/index.md5
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
7b41a36b2c1fe6f67ae750a38cc144db
|
package/src/index.sri
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
sha384-
|
|
1
|
+
sha384-Bj6YB2m5ENO7H/0f3agpgLqday7DeSX2gyCAHRh0eRjrkzsEKXSIWq6eadByRqut
|
package/src/plugins/a11y.md5
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
83098edb2dc04573f9aac3987a7f1bae
|
package/src/plugins/trustarc.md5
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
907a29e9b683d52ab45c0fc02038916e
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
ebe320b3bc258db22786d472559793c1
|
package/src/plugins/video.md5
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
90fa0790108137f0cb4c44345d2e577f
|
|
@@ -17,6 +17,7 @@ function addWebComponentTracking({
|
|
|
17
17
|
sampleRUM,
|
|
18
18
|
sourceSelector,
|
|
19
19
|
targetSelector,
|
|
20
|
+
untrustedClickPayload,
|
|
20
21
|
createMO
|
|
21
22
|
}) {
|
|
22
23
|
function activateMutationObserver(mo, root = document.body) {
|
|
@@ -65,7 +66,8 @@ function addWebComponentTracking({
|
|
|
65
66
|
event.optelHandled = true;
|
|
66
67
|
sampleRUM('click', {
|
|
67
68
|
target: targetSelector(event.target),
|
|
68
|
-
source: sourceSelector(event.target)
|
|
69
|
+
source: sourceSelector(event.target),
|
|
70
|
+
...untrustedClickPayload(event)
|
|
69
71
|
});
|
|
70
72
|
});
|
|
71
73
|
}
|
|
@@ -17,6 +17,7 @@ function addWebComponentTracking({
|
|
|
17
17
|
sampleRUM,
|
|
18
18
|
sourceSelector,
|
|
19
19
|
targetSelector,
|
|
20
|
+
untrustedClickPayload,
|
|
20
21
|
createMO
|
|
21
22
|
}) {
|
|
22
23
|
function activateMutationObserver(mo, root = document.body) {
|
|
@@ -65,7 +66,8 @@ function addWebComponentTracking({
|
|
|
65
66
|
event.optelHandled = true;
|
|
66
67
|
sampleRUM('click', {
|
|
67
68
|
target: targetSelector(event.target),
|
|
68
|
-
source: sourceSelector(event.target)
|
|
69
|
+
source: sourceSelector(event.target),
|
|
70
|
+
...untrustedClickPayload(event)
|
|
69
71
|
});
|
|
70
72
|
});
|
|
71
73
|
}
|
|
@@ -82,4 +84,4 @@ function addWebComponentTracking({
|
|
|
82
84
|
}
|
|
83
85
|
|
|
84
86
|
export { addWebComponentTracking as default };
|
|
85
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2ViY29tcG9uZW50Lm1hcC5qcyIsInNvdXJjZXMiOlsiLi4vLi4vcGx1Z2lucy93ZWJjb21wb25lbnQuanMiXSwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAyMDI1IEFkb2JlLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuICogVGhpcyBmaWxlIGlzIGxpY2Vuc2VkIHRvIHlvdSB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLiBZb3UgbWF5IG9idGFpbiBhIGNvcHlcbiAqIG9mIHRoZSBMaWNlbnNlIGF0IGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmUgZGlzdHJpYnV0ZWQgdW5kZXJcbiAqIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUywgV0lUSE9VVCBXQVJSQU5USUVTIE9SIFJFUFJFU0VOVEFUSU9OU1xuICogT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlXG4gKiBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbi8qKiBAdHlwZSB7V2Vha01hcDxIVE1MRWxlbWVudCwgYm9vbGVhbj59ICovXG5jb25zdCBvYnNlcnZlZFdDID0gbmV3IFdlYWtNYXAoKTtcblxuLyoqIEB0eXBlIHtNdXRhdGlvbk9ic2VydmVyJnthY3RpdmU/OmJvb2xlYW59fHVuZGVmaW5lZH0gKi9cbmxldCByb290TU87XG5cbmNvbnN0IGlzVmFsaWRUYWdOYW1lID0gKHRhZ05hbWUpID0+
|
|
87
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2ViY29tcG9uZW50Lm1hcC5qcyIsInNvdXJjZXMiOlsiLi4vLi4vcGx1Z2lucy93ZWJjb21wb25lbnQuanMiXSwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAyMDI1IEFkb2JlLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuICogVGhpcyBmaWxlIGlzIGxpY2Vuc2VkIHRvIHlvdSB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLiBZb3UgbWF5IG9idGFpbiBhIGNvcHlcbiAqIG9mIHRoZSBMaWNlbnNlIGF0IGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmUgZGlzdHJpYnV0ZWQgdW5kZXJcbiAqIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUywgV0lUSE9VVCBXQVJSQU5USUVTIE9SIFJFUFJFU0VOVEFUSU9OU1xuICogT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlXG4gKiBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbi8qKiBAdHlwZSB7V2Vha01hcDxIVE1MRWxlbWVudCwgYm9vbGVhbj59ICovXG5jb25zdCBvYnNlcnZlZFdDID0gbmV3IFdlYWtNYXAoKTtcblxuLyoqIEB0eXBlIHtNdXRhdGlvbk9ic2VydmVyJnthY3RpdmU/OmJvb2xlYW59fHVuZGVmaW5lZH0gKi9cbmxldCByb290TU87XG5cbmNvbnN0IGlzVmFsaWRUYWdOYW1lID0gKHRhZ05hbWUpID0+IC9eW2Etel1bYS16MC05XSooPzotW2EtejAtOV0rKSokLy50ZXN0KHRhZ05hbWUudG9Mb3dlckNhc2UoKSk7XG5cbmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uIGFkZFdlYkNvbXBvbmVudFRyYWNraW5nKHtcbiAgY29udGV4dCxcbiAgc2FtcGxlUlVNLFxuICBzb3VyY2VTZWxlY3RvcixcbiAgdGFyZ2V0U2VsZWN0b3IsXG4gIHVudHJ1c3RlZENsaWNrUGF5bG9hZCxcbiAgY3JlYXRlTU8sXG59KSB7XG4gIC8qKlxuICAgKiBhY3RpdmF0ZSBtdXRhdGlvbiBvYnNlcnZlclxuICAgKiBAcGFyYW0ge011dGF0aW9uT2JzZXJ2ZXIme2FjdGl2ZT86Ym9vbGVhbn19IG1vXG4gICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IFtyb290PWRvY3VtZW50LmJvZHldXG4gICAqIEByZXR1cm5zIHt2b2lkfVxuICAgKi9cbiAgZnVuY3Rpb24gYWN0aXZhdGVNdXRhdGlvbk9ic2VydmVyKG1vLCByb290ID0gZG9jdW1lbnQuYm9keSkge1xuICAgIC8qIGM4IGlnbm9yZSBuZXh0IDMgKi9cbiAgICBpZiAoIW1vIHx8IG1vLmFjdGl2ZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tcGFyYW0tcmVhc3NpZ25cbiAgICBtby5hY3RpdmUgPSB0cnVlO1xuICAgIG1vLm9ic2VydmUoXG4gICAgICByb290LFxuICAgICAgeyBzdWJ0cmVlOiB0cnVlLCBhdHRyaWJ1dGVzOiBmYWxzZSwgY2hpbGRMaXN0OiB0cnVlIH0sXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAY2FsbGJhY2sgTXV0YXRpb25DYWxsYmFja1xuICAgKiBAcGFyYW0ge011dGF0aW9uUmVjb3JkW119IG11dGF0aW9uc1xuICAgKiBAcGFyYW0ge011dGF0aW9uT2JzZXJ2ZXJ9IG9ic2VydmVyXG4gICAqL1xuICBmdW5jdGlvbiBtdXRhdGlvbkNCKG11dGF0aW9ucykge1xuICAgIG11dGF0aW9uc1xuICAgICAgLmZvckVhY2goKG0pID0+IHtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXVzZS1iZWZvcmUtZGVmaW5lXG4gICAgICAgIF9hZGRXZWJDb21wb25lbnRUcmFja2luZyhtLnRhcmdldCk7XG4gICAgICB9KTtcbiAgfVxuXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby11bmRlcnNjb3JlLWRhbmdsZVxuICBmdW5jdGlvbiBfYWRkV2ViQ29tcG9uZW50VHJhY2tpbmcob2JqKSB7XG4gICAgLyogYzggaWdub3JlIG5leHQgMyAqL1xuICAgIGlmICghb2JqKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgeyB0YWdOYW1lIH0gPSBvYmo7XG4gICAgaWYgKHRhZ05hbWUgJiYgdGFnTmFtZS5pbmNsdWRlcygnLScpICYmIGlzVmFsaWRUYWdOYW1lKHRhZ05hbWUpKSB7XG4gICAgICB3aW5kb3cuY3VzdG9tRWxlbWVudHMud2hlbkRlZmluZWQodGFnTmFtZS50b0xvd2VyQ2FzZSgpKVxuICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgaWYgKG9iai5zaGFkb3dSb290ICYmICFvYnNlcnZlZFdDLmhhcyhvYmopKSB7XG4gICAgICAgICAgICBvYnNlcnZlZFdDLnNldChvYmosIHRydWUpO1xuICAgICAgICAgICAgY29uc3QgbW8gPSBjcmVhdGVNTyhtdXRhdGlvbkNCKTtcbiAgICAgICAgICAgIGFjdGl2YXRlTXV0YXRpb25PYnNlcnZlcihtbywgb2JqLnNoYWRvd1Jvb3QpO1xuICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXVuZGVyc2NvcmUtZGFuZ2xlLCBuby1wYXJhbS1yZWFzc2lnblxuICAgICAgICAgICAgb2JqLl9fb3B0ZWxNTyA9IG1vO1xuICAgICAgICAgICAgX2FkZFdlYkNvbXBvbmVudFRyYWNraW5nKG9iai5zaGFkb3dSb290KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgaGFzU2hhZG93Um9vdCA9IGZhbHNlO1xuICAgICAgdHJ5IHtcbiAgICAgICAgaGFzU2hhZG93Um9vdCA9IE9iamVjdC5nZXRQcm90b3R5cGVPZihvYmopLnRvU3RyaW5nKCkuaW5jbHVkZXMoJ1NoYWRvd1Jvb3QnKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHsgLyogZG8gbm90aGluZyAqLyB9XG4gICAgICBpZiAoaGFzU2hhZG93Um9vdCkge1xuICAgICAgICAvLyBvYmogaXMgYSBzaGFkb3dSb290LCBhZGQgY2xpY2sgdHJhY2tpbmdcbiAgICAgICAgb2JqLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgKGV2ZW50KSA9PiB7XG4gICAgICAgICAgaWYgKGV2ZW50Lm9wdGVsSGFuZGxlZCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tcGFyYW0tcmVhc3NpZ25cbiAgICAgICAgICBldmVudC5vcHRlbEhhbmRsZWQgPSB0cnVlO1xuICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBtYXgtbGVuXG4gICAgICAgICAgc2FtcGxlUlVNKCdjbGljaycsIHsgdGFyZ2V0OiB0YXJnZXRTZWxlY3RvcihldmVudC50YXJnZXQpLCBzb3VyY2U6IHNvdXJjZVNlbGVjdG9yKGV2ZW50LnRhcmdldCksIC4uLnVudHJ1c3RlZENsaWNrUGF5bG9hZChldmVudCkgfSk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgLy8gbG9vayBmb3Igd2ViIGNvbXBvbmVudHMgYmVsb3cgdGhpcyBlbGVtZW50XG4gICAgICBbLi4ub2JqLnF1ZXJ5U2VsZWN0b3JBbGwoJyonKV1cbiAgICAgICAgLmZpbHRlcigoZWwpID0+IGVsLnRhZ05hbWUgJiYgZWwudGFnTmFtZS5pbmNsdWRlcygnLScpICYmICFvYnNlcnZlZFdDLmhhcyhlbCkpXG4gICAgICAgIC5mb3JFYWNoKChlbCkgPT4ge1xuICAgICAgICAgIF9hZGRXZWJDb21wb25lbnRUcmFja2luZyhlbCk7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIGlmICghcm9vdE1PKSB7XG4gICAgcm9vdE1PID0gY3JlYXRlTU8obXV0YXRpb25DQik7XG4gICAgYWN0aXZhdGVNdXRhdGlvbk9ic2VydmVyKHJvb3RNTyk7XG4gIH1cbiAgX2FkZFdlYkNvbXBvbmVudFRyYWNraW5nKGNvbnRleHQpO1xufVxuIl0sIm5hbWVzIjpbIm9ic2VydmVkV0MiLCJXZWFrTWFwIiwicm9vdE1PIiwiaXNWYWxpZFRhZ05hbWUiLCJ0YWdOYW1lIiwidGVzdCIsInRvTG93ZXJDYXNlIiwiYWRkV2ViQ29tcG9uZW50VHJhY2tpbmciLCJjb250ZXh0Iiwic2FtcGxlUlVNIiwic291cmNlU2VsZWN0b3IiLCJ0YXJnZXRTZWxlY3RvciIsInVudHJ1c3RlZENsaWNrUGF5bG9hZCIsImNyZWF0ZU1PIiwiYWN0aXZhdGVNdXRhdGlvbk9ic2VydmVyIiwibW8iLCJyb290IiwiZG9jdW1lbnQiLCJib2R5IiwiYWN0aXZlIiwib2JzZXJ2ZSIsInN1YnRyZWUiLCJhdHRyaWJ1dGVzIiwiY2hpbGRMaXN0IiwibXV0YXRpb25DQiIsIm11dGF0aW9ucyIsImZvckVhY2giLCJtIiwiX2FkZFdlYkNvbXBvbmVudFRyYWNraW5nIiwidGFyZ2V0Iiwib2JqIiwiaW5jbHVkZXMiLCJ3aW5kb3ciLCJjdXN0b21FbGVtZW50cyIsIndoZW5EZWZpbmVkIiwidGhlbiIsInNoYWRvd1Jvb3QiLCJoYXMiLCJzZXQiLCJfX29wdGVsTU8iLCJoYXNTaGFkb3dSb290IiwiT2JqZWN0IiwiZ2V0UHJvdG90eXBlT2YiLCJ0b1N0cmluZyIsImUiLCJhZGRFdmVudExpc3RlbmVyIiwiZXZlbnQiLCJvcHRlbEhhbmRsZWQiLCJzb3VyY2UiLCJxdWVyeVNlbGVjdG9yQWxsIiwiZmlsdGVyIiwiZWwiXSwibWFwcGluZ3MiOiI7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
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
1971ead6d6bc23d0eee1ff5705b6fc48
|