govuk_publishing_components 39.2.4 → 39.2.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cdf41c9c036ffe0122a00d9cda5483c76b1a98d717abfe645eb40e2c6daea9e1
4
- data.tar.gz: bf83fabdd5e6a86b9fb74489e3dfdffc03afd231109f3a8f4451a9c32900174d
3
+ metadata.gz: 58b7f11016cf45ea3d59c0a1dbc3f8c059869a37a82925845e803d3a060074ec
4
+ data.tar.gz: 2115ba949c309a7482fb08748d2abfdca8b01f2adb01557d45083cf812d30073
5
5
  SHA512:
6
- metadata.gz: cdf4614dd7fdb99ff54416adbcb34624f377c3520ac529c5d705e5057f95fda145d4177d327fb91f7e55b9230e062ef1dc42339c09bb3510825d9b1cb2eb08e9
7
- data.tar.gz: f47eca08480dc0d75a1be133d23eebf8d29edf0c68e31d9609b098b94e18731f38165bff89e697fa4d405c25b940e9b8d1f696e8b9cb7bed9fedfc17c93fb918
6
+ metadata.gz: 313d31ab1ab2882e1d684357c40f95fcb73e8ac020f9e056aba9f8e46e25ab87cfb4df2414bfe19fef62717c7a028b00a5e2fc5616be12c0ef7356eb311c621d
7
+ data.tar.gz: c532deea8617bef61052a66fdc7501ebaed45a7040db52c5bd8150415385abc2e6c03972a6a9fee30622753aec2308b7440103cda8e923dd1d6d5be4838f43de
@@ -22,6 +22,48 @@
22
22
  (function () {
23
23
  'use strict';
24
24
 
25
+ var Flags = {
26
+ InitCalled: 1 << 0,
27
+ NavTimingNotSupported: 1 << 1,
28
+ UserTimingNotSupported: 1 << 2,
29
+ VisibilityStateNotVisible: 1 << 3,
30
+ BeaconSentFromUnloadHandler: 1 << 4,
31
+ BeaconSentAfterTimeout: 1 << 5,
32
+ PageLabelFromDocumentTitle: 1 << 6,
33
+ PageLabelFromLabelProp: 1 << 7,
34
+ PageLabelFromGlobalVariable: 1 << 8,
35
+ PageLabelFromUrlPattern: 1 << 9,
36
+ PageWasPrerendered: 1 << 10,
37
+ PageWasBfCacheRestored: 1 << 11,
38
+ BeaconBlockedByCsp: 1 << 12,
39
+ };
40
+ function addFlag(flags, flag) {
41
+ return flags | flag;
42
+ }
43
+
44
+ // Wrapper to support older browsers (<= IE8)
45
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
46
+ function addListener(type, callback, useCapture) {
47
+ if (useCapture === void 0) { useCapture = false; }
48
+ if (addEventListener) {
49
+ addEventListener(type, callback, useCapture);
50
+ }
51
+ else if (window.attachEvent && true) {
52
+ window.attachEvent("on" + type, callback);
53
+ }
54
+ }
55
+ // Wrapper to support older browsers (<= IE8)
56
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
57
+ function removeListener(type, callback, useCapture) {
58
+ if (useCapture === void 0) { useCapture = false; }
59
+ if (removeEventListener) {
60
+ removeEventListener(type, callback, useCapture);
61
+ }
62
+ else if (window.detachEvent && true) {
63
+ window.detachEvent("on" + type, callback);
64
+ }
65
+ }
66
+
25
67
  function now() {
26
68
  return Date.now ? Date.now() : +new Date();
27
69
  }
@@ -74,6 +116,7 @@
74
116
  PostBeaconMetricRejected: 87,
75
117
  PostBeaconDisabled: 88,
76
118
  PostBeaconSendFailed: 89,
119
+ PostBeaconCSPViolation: 90,
77
120
  };
78
121
  var Logger = /** @class */ (function () {
79
122
  function Logger() {
@@ -240,7 +283,7 @@
240
283
  return str;
241
284
  }
242
285
 
243
- var VERSION = "4.0.20";
286
+ var VERSION = "4.0.23";
244
287
  /**
245
288
  * Returns the version of the script as a float to be stored in legacy systems that do not support
246
289
  * string versions.
@@ -256,6 +299,7 @@
256
299
  xhr.open("POST", url, true);
257
300
  xhr.setRequestHeader("content-type", "application/json");
258
301
  xhr.send(String(data));
302
+ return true;
259
303
  };
260
304
  var sendBeacon = "sendBeacon" in navigator ? navigator.sendBeacon.bind(navigator) : sendBeaconFallback;
261
305
  /**
@@ -279,7 +323,9 @@
279
323
  var _this = this;
280
324
  this.isRecording = true;
281
325
  this.isSent = false;
326
+ this.sendRetries = 0;
282
327
  this.maxMeasureTimeout = 0;
328
+ this.flags = 0;
283
329
  this.onBeforeSendCbs = [];
284
330
  this.startTime = opts.startTime || getZeroTime();
285
331
  this.config = opts.config;
@@ -293,6 +339,33 @@
293
339
  _this.stopRecording();
294
340
  _this.send();
295
341
  }, this.config.maxMeasureTime);
342
+ addListener("securitypolicyviolation", function (e) {
343
+ if (e.disposition !== "report" && e.blockedURI === _this.config.beaconUrlV2 && "URL" in self) {
344
+ // Some websites might have CSP rules that allow the GET beacon, but not the POST beacon.
345
+ // We can detect this here and attempt to send the beacon to a fallback endpoint.
346
+ //
347
+ // If the fallback endpoint has not been provided in the config, we will fall back to using
348
+ // the POST beacon pathname on the GET beacon origin.
349
+ if (!_this.config.beaconUrlFallback) {
350
+ var getOrigin = new URL(_this.config.beaconUrl).origin;
351
+ var postPathname = new URL(_this.config.beaconUrlV2).pathname;
352
+ _this.config.beaconUrlFallback = getOrigin + postPathname;
353
+ }
354
+ // Update the V2 beacon URL
355
+ _this.config.beaconUrlV2 = _this.config.beaconUrlFallback;
356
+ _this.logger.logEvent(LogEvent.PostBeaconCSPViolation, [_this.config.beaconUrlV2]);
357
+ _this.addFlag(Flags.BeaconBlockedByCsp);
358
+ // Not all browsers return false if sendBeacon fails. In this case, `this.isSent` will be
359
+ // true, even though the beacon wasn't sent. We need to reset this flag to ensure we can
360
+ // retry sending the beacon.
361
+ _this.isSent = false;
362
+ // Try to send the beacon again
363
+ if (_this.sendRetries < 1) {
364
+ _this.sendRetries++;
365
+ _this.send();
366
+ }
367
+ }
368
+ });
296
369
  this.logger.logEvent(LogEvent.PostBeaconInitialised);
297
370
  }
298
371
  Beacon.prototype.isBeingSampled = function () {
@@ -310,6 +383,9 @@
310
383
  }
311
384
  this.metricData[metric] = data;
312
385
  };
386
+ Beacon.prototype.addFlag = function (flag) {
387
+ this.flags = addFlag(this.flags, flag);
388
+ };
313
389
  Beacon.prototype.hasMetricData = function () {
314
390
  return Object.keys(this.metricData).length > 0;
315
391
  };
@@ -347,6 +423,7 @@
347
423
  var beaconUrl = this.beaconUrl();
348
424
  var payload = Object.assign({
349
425
  customerId: this.customerId,
426
+ flags: this.flags,
350
427
  measureDuration: msSincePageInit(),
351
428
  pageId: this.pageId,
352
429
  scriptVersion: VERSION,
@@ -354,40 +431,21 @@
354
431
  startTime: this.startTime,
355
432
  }, this.metricData);
356
433
  try {
357
- sendBeacon(beaconUrl, JSON.stringify(payload));
358
- this.isSent = true;
359
- this.logger.logEvent(LogEvent.PostBeaconSent, [beaconUrl, payload]);
434
+ if (sendBeacon(beaconUrl, JSON.stringify(payload))) {
435
+ this.isSent = true;
436
+ this.logger.logEvent(LogEvent.PostBeaconSent, [beaconUrl, payload]);
437
+ }
360
438
  }
361
439
  catch (e) {
362
- this.logger.logEvent(LogEvent.PostBeaconSendFailed, [e]);
440
+ // Intentionally empty; handled below
441
+ }
442
+ if (!this.isSent) {
443
+ this.logger.logEvent(LogEvent.PostBeaconSendFailed, [beaconUrl, payload]);
363
444
  }
364
445
  };
365
446
  return Beacon;
366
447
  }());
367
448
 
368
- // Wrapper to support older browsers (<= IE8)
369
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
370
- function addListener(type, callback, useCapture) {
371
- if (useCapture === void 0) { useCapture = false; }
372
- if (addEventListener) {
373
- addEventListener(type, callback, useCapture);
374
- }
375
- else if (window.attachEvent && true) {
376
- window.attachEvent("on" + type, callback);
377
- }
378
- }
379
- // Wrapper to support older browsers (<= IE8)
380
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
381
- function removeListener(type, callback, useCapture) {
382
- if (useCapture === void 0) { useCapture = false; }
383
- if (removeEventListener) {
384
- removeEventListener(type, callback, useCapture);
385
- }
386
- else if (window.detachEvent && true) {
387
- window.detachEvent("on" + type, callback);
388
- }
389
- }
390
-
391
449
  function onPageLoad(callback) {
392
450
  if (document.readyState === "complete") {
393
451
  // The onload event has already fired
@@ -408,6 +466,7 @@
408
466
  allowEmptyPostBeacon: getProperty(obj, "allowEmptyPostBeacon", false),
409
467
  auto: autoMode,
410
468
  beaconUrl: getProperty(obj, "beaconUrl", luxOrigin + "/lux/"),
469
+ beaconUrlFallback: getProperty(obj, "beaconUrlFallback"),
411
470
  beaconUrlV2: getProperty(obj, "beaconUrlV2", "https://beacon.speedcurve.com/store"),
412
471
  conversions: getProperty(obj, "conversions"),
413
472
  cookieDomain: getProperty(obj, "cookieDomain"),
@@ -543,39 +602,38 @@
543
602
  var MAX_SELECTOR_LENGTH = 100;
544
603
  function getNodeSelector(node, selector) {
545
604
  if (selector === void 0) { selector = ""; }
546
- try {
547
- if (selector &&
548
- (node.nodeType === 9 || selector.length > MAX_SELECTOR_LENGTH || !node.parentNode)) {
549
- // Final selector.
550
- return selector;
551
- }
552
- var el = node;
553
- // Our first preference is to use the data-sctrack attribute from anywhere in the tree
554
- var trackId = getClosestScTrackAttribute(el);
555
- if (trackId) {
556
- return trackId;
557
- }
558
- if (el.id) {
559
- // Once we've found an element with ID we return the selector.
560
- return "#" + el.id + (selector ? ">" + selector : "");
561
- }
562
- else if (el) {
563
- // Otherwise attempt to get parent elements recursively
564
- var name_1 = el.nodeType === 1 ? el.nodeName.toLowerCase() : el.nodeName.toUpperCase();
565
- var classes = el.className ? "." + el.className.replace(/\s+/g, ".") : "";
566
- // Remove classes until the selector is short enough
567
- while ((name_1 + classes).length > MAX_SELECTOR_LENGTH) {
568
- classes = classes.split(".").slice(0, -1).join(".");
569
- }
570
- var currentSelector = name_1 + classes + (selector ? ">" + selector : "");
571
- if (el.parentNode) {
572
- var selectorWithParent = getNodeSelector(el.parentNode, currentSelector);
573
- if (selectorWithParent.length < MAX_SELECTOR_LENGTH) {
574
- return selectorWithParent;
575
- }
605
+ try {
606
+ if (selector && (node.nodeType === 9 || selector.length > MAX_SELECTOR_LENGTH || !node.parentNode)) {
607
+ // Final selector.
608
+ return selector;
609
+ }
610
+ var el = node;
611
+ // Our first preference is to use the data-sctrack attribute from anywhere in the tree
612
+ var trackId = getClosestScTrackAttribute(el);
613
+ if (trackId) {
614
+ return trackId;
615
+ }
616
+ if (el.id) {
617
+ // Once we've found an element with ID we return the selector.
618
+ return "#" + el.id + (selector ? ">" + selector : "");
619
+ }
620
+ else if (el) {
621
+ // Otherwise attempt to get parent elements recursively
622
+ var name_1 = el.nodeType === 1 ? el.nodeName.toLowerCase() : el.nodeName.toUpperCase();
623
+ var classes = el.className ? "." + el.className.replace(/\s+/g, ".") : "";
624
+ // Remove classes until the selector is short enough
625
+ while ((name_1 + classes).length > MAX_SELECTOR_LENGTH) {
626
+ classes = classes.split(".").slice(0, -1).join(".");
627
+ }
628
+ var currentSelector = name_1 + classes + (selector ? ">" + selector : "");
629
+ if (el.parentNode) {
630
+ var selectorWithParent = getNodeSelector(el.parentNode, currentSelector);
631
+ if (selectorWithParent.length < MAX_SELECTOR_LENGTH) {
632
+ return selectorWithParent;
576
633
  }
577
- return currentSelector;
578
634
  }
635
+ return currentSelector;
636
+ }
579
637
  }
580
638
  catch (error) {
581
639
  // Do nothing.
@@ -583,24 +641,6 @@
583
641
  return selector;
584
642
  }
585
643
 
586
- var Flags = {
587
- InitCalled: 1 << 0,
588
- NavTimingNotSupported: 1 << 1,
589
- UserTimingNotSupported: 1 << 2,
590
- VisibilityStateNotVisible: 1 << 3,
591
- BeaconSentFromUnloadHandler: 1 << 4,
592
- BeaconSentAfterTimeout: 1 << 5,
593
- PageLabelFromDocumentTitle: 1 << 6,
594
- PageLabelFromLabelProp: 1 << 7,
595
- PageLabelFromGlobalVariable: 1 << 8,
596
- PageLabelFromUrlPattern: 1 << 9,
597
- PageWasPrerendered: 1 << 10,
598
- PageWasBfCacheRestored: 1 << 11,
599
- };
600
- function addFlag(flags, flag) {
601
- return flags | flag;
602
- }
603
-
604
644
  var sessionValue = 0;
605
645
  var sessionEntries = [];
606
646
  var sessionAttributions = [];
@@ -620,23 +660,23 @@
620
660
  elementType: source.node.nodeName,
621
661
  }); })
622
662
  : [];
623
- if (sessionEntries.length &&
624
- (entry.startTime - latestEntry.startTime >= 1000 ||
625
- entry.startTime - firstEntry.startTime >= 5000)) {
626
- sessionValue = entry.value;
627
- sessionEntries = [entry];
628
- sessionAttributions = sources;
629
- largestEntry = entry;
630
- }
631
- else {
632
- sessionValue += entry.value;
633
- sessionEntries.push(entry);
634
- sessionAttributions = sessionAttributions.concat(sources);
635
- if (!largestEntry || entry.value > largestEntry.value) {
663
+ if (sessionEntries.length &&
664
+ (entry.startTime - latestEntry.startTime >= 1000 ||
665
+ entry.startTime - firstEntry.startTime >= 5000)) {
666
+ sessionValue = entry.value;
667
+ sessionEntries = [entry];
668
+ sessionAttributions = sources;
636
669
  largestEntry = entry;
637
- }
670
+ }
671
+ else {
672
+ sessionValue += entry.value;
673
+ sessionEntries.push(entry);
674
+ sessionAttributions = sessionAttributions.concat(sources);
675
+ if (!largestEntry || entry.value > largestEntry.value) {
676
+ largestEntry = entry;
638
677
  }
639
- maximumSessionValue = max(maximumSessionValue, sessionValue);
678
+ }
679
+ maximumSessionValue = max(maximumSessionValue, sessionValue);
640
680
  }
641
681
  }
642
682
  function reset$1() {
@@ -1060,6 +1100,7 @@
1060
1100
  if (!performance.timing) {
1061
1101
  logger.logEvent(LogEvent.NavTimingNotSupported);
1062
1102
  gFlags = addFlag(gFlags, Flags.NavTimingNotSupported);
1103
+ beacon.addFlag(Flags.NavTimingNotSupported);
1063
1104
  }
1064
1105
  logger.logEvent(LogEvent.NavigationStart, [timing.navigationStart]);
1065
1106
  ////////////////////// FID BEGIN
@@ -1165,6 +1206,7 @@
1165
1206
  };
1166
1207
  gaMarks.push(entry);
1167
1208
  gFlags = addFlag(gFlags, Flags.UserTimingNotSupported);
1209
+ beacon.addFlag(Flags.UserTimingNotSupported);
1168
1210
  return entry;
1169
1211
  }
1170
1212
  }
@@ -1267,6 +1309,7 @@
1267
1309
  };
1268
1310
  gaMeasures.push(entry);
1269
1311
  gFlags = addFlag(gFlags, Flags.UserTimingNotSupported);
1312
+ beacon.addFlag(Flags.UserTimingNotSupported);
1270
1313
  return entry;
1271
1314
  }
1272
1315
  }
@@ -1610,6 +1653,7 @@
1610
1653
  if (clearFlags) {
1611
1654
  gFlags = 0;
1612
1655
  gFlags = addFlag(gFlags, Flags.InitCalled);
1656
+ beacon.addFlag(Flags.InitCalled);
1613
1657
  }
1614
1658
  // Reset the maximum measure timeout
1615
1659
  createMaxMeasureTimeout();
@@ -1653,7 +1697,7 @@
1653
1697
  "style" === e.as ||
1654
1698
  (typeof e.onload === "function" && e.media === "all")) ;
1655
1699
  else {
1656
- nBlocking++;
1700
+ nBlocking++;
1657
1701
  }
1658
1702
  }
1659
1703
  }
@@ -2024,6 +2068,7 @@
2024
2068
  clearMaxMeasureTimeout();
2025
2069
  gMaxMeasureTimeout = setTimeout(function () {
2026
2070
  gFlags = addFlag(gFlags, Flags.BeaconSentAfterTimeout);
2071
+ beacon.addFlag(Flags.BeaconSentAfterTimeout);
2027
2072
  _sendLux();
2028
2073
  }, globalConfig.maxMeasureTime - msSincePageInit());
2029
2074
  }
@@ -2094,9 +2139,11 @@
2094
2139
  var sLuxjs = selfLoading();
2095
2140
  if (!isVisible()) {
2096
2141
  gFlags = addFlag(gFlags, Flags.VisibilityStateNotVisible);
2142
+ beacon.addFlag(Flags.VisibilityStateNotVisible);
2097
2143
  }
2098
2144
  if (wasPrerendered()) {
2099
2145
  gFlags = addFlag(gFlags, Flags.PageWasPrerendered);
2146
+ beacon.addFlag(Flags.PageWasPrerendered);
2100
2147
  }
2101
2148
  if (globalConfig.serverTiming) {
2102
2149
  var navEntry = getNavigationEntry();
@@ -2310,6 +2357,7 @@
2310
2357
  function _addUnloadHandlers() {
2311
2358
  var onunload = function () {
2312
2359
  gFlags = addFlag(gFlags, Flags.BeaconSentFromUnloadHandler);
2360
+ beacon.addFlag(Flags.BeaconSentFromUnloadHandler);
2313
2361
  logger.logEvent(LogEvent.UnloadHandlerTriggered);
2314
2362
  _sendLux();
2315
2363
  _sendIx();
@@ -2387,12 +2435,14 @@
2387
2435
  function _getPageLabel() {
2388
2436
  if (LUX.label) {
2389
2437
  gFlags = addFlag(gFlags, Flags.PageLabelFromLabelProp);
2438
+ beacon.addFlag(Flags.PageLabelFromLabelProp);
2390
2439
  return LUX.label;
2391
2440
  }
2392
2441
  if (typeof LUX.pagegroups !== "undefined") {
2393
2442
  var label = getMatchesFromPatternMap(LUX.pagegroups, location.hostname, location.pathname, true);
2394
2443
  if (label) {
2395
2444
  gFlags = addFlag(gFlags, Flags.PageLabelFromUrlPattern);
2445
+ beacon.addFlag(Flags.PageLabelFromUrlPattern);
2396
2446
  return label;
2397
2447
  }
2398
2448
  }
@@ -2402,6 +2452,7 @@
2402
2452
  var label = evaluateJsPageLabel();
2403
2453
  if (label) {
2404
2454
  gFlags = addFlag(gFlags, Flags.PageLabelFromGlobalVariable);
2455
+ beacon.addFlag(Flags.PageLabelFromGlobalVariable);
2405
2456
  return label;
2406
2457
  }
2407
2458
  }
@@ -2411,6 +2462,7 @@
2411
2462
  }
2412
2463
  // default to document.title
2413
2464
  gFlags = addFlag(gFlags, Flags.PageLabelFromDocumentTitle);
2465
+ beacon.addFlag(Flags.PageLabelFromDocumentTitle);
2414
2466
  return document.title;
2415
2467
  }
2416
2468
  function _getCookie(name) {
@@ -2495,6 +2547,7 @@
2495
2547
  }
2496
2548
  // Flag the current page as a bfcache restore
2497
2549
  gFlags = addFlag(gFlags, Flags.PageWasBfCacheRestored);
2550
+ beacon.addFlag(Flags.PageWasBfCacheRestored);
2498
2551
  }, 0);
2499
2552
  }
2500
2553
  });
@@ -1,3 +1,3 @@
1
1
  module GovukPublishingComponents
2
- VERSION = "39.2.4".freeze
2
+ VERSION = "39.2.5".freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: govuk_publishing_components
3
3
  version: !ruby/object:Gem::Version
4
- version: 39.2.4
4
+ version: 39.2.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - GOV.UK Dev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-07-11 00:00:00.000000000 Z
11
+ date: 2024-07-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: govuk_app_config