govuk_publishing_components 35.15.0 → 35.15.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 999c5822c246101234a2c8d42828e3ee8b17df824b0472c12b55df5c2d81c4be
4
- data.tar.gz: e6d08b1e863e2ded1152342176e3e7c506f3a89baf06a1c3b2b45c7c73c46ce0
3
+ metadata.gz: 5edbe2c7a347d6bc8069704f3434dc4c41de45b3286f7640893f7ff8f62c25a8
4
+ data.tar.gz: d17f853fdf1a5598b808a69fdec621da35aa8662bc911d5c951715cc53bfb6a0
5
5
  SHA512:
6
- metadata.gz: 6fe723d3ea44de844e2228dbbbcfa815148df3b96b94edb58acba736815ab6f92142bf5f3853d0da0d2bca8f730f765414ea7d1c05db738d18c830bfadc88235
7
- data.tar.gz: c06d8fbd16d112658797943def5f8b817f5c2c7e0424381cf16e8fb5c920d47a4ed8e88411be7509793da277f0f2d2f609765b6eb37d49550352b19be310d10b
6
+ metadata.gz: 0f5f8a3a9706d98e11ce756987eb9dc442dce2c3701eeb2dbfe8ff2ad48c6c48d27c0c8f056b9e3f851d53d4c6cfb1712c042f9699a658fad94618d679b6c974
7
+ data.tar.gz: fc1469502870ba2a479cde17f7d8edc652270a3ce98efd2aa6128797634e484bf6448cb54712f4c12c116a4f9275d345cb39ffdf13901bde137fc80321769657
@@ -21,33 +21,34 @@
21
21
 
22
22
  (function () {
23
23
  'use strict';
24
+
24
25
  /**
25
- * Fit an array of user timing delimited strings into a URL and return both the entries that fit and
26
- * the remaining entries that didn't fit.
27
- */
26
+ * Fit an array of user timing delimited strings into a URL and return both the entries that fit and
27
+ * the remaining entries that didn't fit.
28
+ */
28
29
  function fitUserTimingEntries(utValues, config, url) {
29
30
  // Start with the maximum allowed UT entries per beacon
30
31
  var beaconUtValues = utValues.slice(0, config.maxBeaconUTEntries);
31
32
  var remainingUtValues = utValues.slice(config.maxBeaconUTEntries);
32
33
  // Trim UT entries until they fit within the maximum URL length, ensuring at least one UT entry
33
34
  // is included.
34
- while ((url + "&UT=" + beaconUtValues.join(",")).length > config.maxBeaconUrlLength &&
35
- beaconUtValues.length > 1) {
35
+ while ((url + "&UT=" + beaconUtValues.join(",")).length > config.maxBeaconUrlLength && beaconUtValues.length > 1) {
36
36
  remainingUtValues.unshift(beaconUtValues.pop());
37
37
  }
38
38
  return [beaconUtValues, remainingUtValues];
39
39
  }
40
40
 
41
+ var luxOrigin = "https://lux.speedcurve.com";
41
42
  function fromObject(obj) {
42
43
  var autoMode = getProperty(obj, "auto", true);
43
44
  return {
44
45
  auto: autoMode,
45
- beaconUrl: getProperty(obj, "beaconUrl", "https://lux.speedcurve.com/lux/"),
46
- conversions: getProperty(obj, "conversions", undefined),
47
- customerid: getProperty(obj, "customerid", undefined),
48
- errorBeaconUrl: getProperty(obj, "errorBeaconUrl", "https://lux.speedcurve.com/error/"),
49
- jspagelabel: getProperty(obj, "jspagelabel", undefined),
50
- label: getProperty(obj, "label", undefined),
46
+ beaconUrl: getProperty(obj, "beaconUrl", luxOrigin + "/lux/"),
47
+ conversions: getProperty(obj, "conversions"),
48
+ customerid: getProperty(obj, "customerid"),
49
+ errorBeaconUrl: getProperty(obj, "errorBeaconUrl", luxOrigin + "/error/"),
50
+ jspagelabel: getProperty(obj, "jspagelabel"),
51
+ label: getProperty(obj, "label"),
51
52
  maxBeaconUrlLength: getProperty(obj, "maxBeaconUrlLength", 8190),
52
53
  maxBeaconUTEntries: getProperty(obj, "maxBeaconUTEntries", 20),
53
54
  maxErrors: getProperty(obj, "maxErrors", 5),
@@ -56,10 +57,10 @@
56
57
  newBeaconOnPageShow: getProperty(obj, "newBeaconOnPageShow", false),
57
58
  samplerate: getProperty(obj, "samplerate", 100),
58
59
  sendBeaconOnPageHidden: getProperty(obj, "sendBeaconOnPageHidden", autoMode),
59
- serverTiming: getProperty(obj, "serverTiming", undefined),
60
+ serverTiming: getProperty(obj, "serverTiming"),
60
61
  trackErrors: getProperty(obj, "trackErrors", true),
61
62
  trackHiddenPages: getProperty(obj, "trackHiddenPages", false),
62
- pagegroups: getProperty(obj, "pagegroups", undefined),
63
+ pagegroups: getProperty(obj, "pagegroups"),
63
64
  };
64
65
  }
65
66
  function getProperty(obj, key, defaultValue) {
@@ -99,8 +100,8 @@
99
100
  updatedCustomData = {};
100
101
  }
101
102
  /**
102
- * Convert a set of custom data values to the string format expected by the backend.
103
- */
103
+ * Convert a set of custom data values to the string format expected by the backend.
104
+ */
104
105
  function valuesToString(values) {
105
106
  var strings = [];
106
107
  for (var key in values) {
@@ -119,11 +120,14 @@
119
120
  }
120
121
  var max = Math.max;
121
122
  /**
122
- * Clamp a number so that it is never less than 0
123
- */
123
+ * Clamp a number so that it is never less than 0
124
+ */
124
125
  function clamp(x) {
125
126
  return max(0, x);
126
127
  }
128
+ function sortNumeric(a, b) {
129
+ return a - b;
130
+ }
127
131
 
128
132
  function now() {
129
133
  return Date.now ? Date.now() : +new Date();
@@ -173,7 +177,7 @@
173
177
  startTime: 0,
174
178
  type: navType == 2 ? "back_forward" : navType === 1 ? "reload" : "navigate",
175
179
  };
176
- if (__ENABLE_POLYFILLS) {
180
+ {
177
181
  for (var key in timing) {
178
182
  if (typeof timing[key] === "number" && key !== "navigationStart") {
179
183
  entry[key] = floor(timing[key] - timing.navigationStart);
@@ -183,10 +187,10 @@
183
187
  return entry;
184
188
  }
185
189
  /**
186
- * Simple wrapper around performance.getEntriesByType to provide fallbacks for
187
- * legacy browsers, and work around edge cases where undefined is returned instead
188
- * of an empty PerformanceEntryList.
189
- */
190
+ * Simple wrapper around performance.getEntriesByType to provide fallbacks for
191
+ * legacy browsers, and work around edge cases where undefined is returned instead
192
+ * of an empty PerformanceEntryList.
193
+ */
190
194
  function getEntriesByType(type) {
191
195
  if (typeof performance.getEntriesByType === "function") {
192
196
  var entries = performance.getEntriesByType(type);
@@ -245,7 +249,7 @@
245
249
  PageLabelFromDocumentTitle: 1 << 6,
246
250
  PageLabelFromLabelProp: 1 << 7,
247
251
  PageLabelFromGlobalVariable: 1 << 8,
248
- PageLabelFromPagegroup: 1 << 9,
252
+ PageLabelFromUrlPattern: 1 << 9,
249
253
  PageWasPrerendered: 1 << 10,
250
254
  PageWasBfCacheRestored: 1 << 11,
251
255
  };
@@ -261,8 +265,8 @@
261
265
  }
262
266
 
263
267
  /**
264
- * Get the interaction attribution name for an element
265
- */
268
+ * Get the interaction attribution name for an element
269
+ */
266
270
  function interactionAttributionForElement(el) {
267
271
  // Our first preference is to use the data-sctrack attribute from anywhere in the tree
268
272
  var trackId = getClosestScTrackAttribute(el);
@@ -354,6 +358,7 @@
354
358
  };
355
359
  return Logger;
356
360
  }());
361
+
357
362
  var sessionValue = 0;
358
363
  var sessionEntries = [];
359
364
  var maximumSessionValue = 0;
@@ -363,9 +368,9 @@
363
368
  var latestEntry = sessionEntries[sessionEntries.length - 1];
364
369
  if (sessionEntries.length &&
365
370
  (entry.startTime - latestEntry.startTime >= 1000 ||
366
- entry.startTime - firstEntry.startTime >= 5000)) {
367
- sessionValue = entry.value;
368
- sessionEntries = [entry];
371
+ entry.startTime - firstEntry.startTime >= 5000)) {
372
+ sessionValue = entry.value;
373
+ sessionEntries = [entry];
369
374
  }
370
375
  else {
371
376
  sessionValue += entry.value;
@@ -384,9 +389,9 @@
384
389
  }
385
390
 
386
391
  /**
387
- * This implementation is based on the web-vitals implementation, however it is stripped back to the
388
- * bare minimum required to measure just the INP value and does not store the actual event entries.
389
- */
392
+ * This implementation is based on the web-vitals implementation, however it is stripped back to the
393
+ * bare minimum required to measure just the INP value and does not store the actual event entries.
394
+ */
390
395
  // The maximum number of interactions to store
391
396
  var MAX_INTERACTIONS = 10;
392
397
  // A list of the slowest interactions
@@ -423,9 +428,9 @@
423
428
  return slowestEntries.some(function (e2) { return e1.startTime === e2.startTime && e1.duration === e2.duration; });
424
429
  }
425
430
  /**
426
- * Returns an estimated high percentile INP value based on the total number of interactions on the
427
- * current page.
428
- */
431
+ * Returns an estimated high percentile INP value based on the total number of interactions on the
432
+ * current page.
433
+ */
429
434
  function getHighPercentileINP() {
430
435
  var _a;
431
436
  var index = Math.min(slowestEntries.length - 1, Math.floor(getInteractionCount() / 50));
@@ -440,8 +445,7 @@
440
445
 
441
446
  var ALL_ENTRIES = [];
442
447
  function observe(type, callback, options) {
443
- if (typeof PerformanceObserver === "function" &&
444
- PerformanceObserver.supportedEntryTypes.includes(type)) {
448
+ if (typeof PerformanceObserver === "function" && PerformanceObserver.supportedEntryTypes.includes(type)) {
445
449
  var po = new PerformanceObserver(function (list) {
446
450
  list.getEntries().forEach(function (entry) { return callback(entry); });
447
451
  });
@@ -456,17 +460,14 @@
456
460
  function addEntry(entry) {
457
461
  ALL_ENTRIES.push(entry);
458
462
  }
459
- function clearEntries() {
460
- ALL_ENTRIES.splice(0);
461
- }
462
463
 
463
464
  /**
464
- * A server timing metric that has its value set to the duration field
465
- */
465
+ * A server timing metric that has its value set to the duration field
466
+ */
466
467
  var TYPE_DURATION = "r";
467
468
  /**
468
- * When a description metric has no value, we consider it to be a boolean and set it to this value.
469
- */
469
+ * When a description metric has no value, we consider it to be a boolean and set it to this value.
470
+ */
470
471
  var BOOLEAN_TRUE_VALUE = "true";
471
472
  function getKeyValuePairs(config, serverTiming) {
472
473
  var pairs = {};
@@ -500,7 +501,7 @@
500
501
  if (Array.isArray(patterns)) {
501
502
  for (var i in patterns) {
502
503
  var pattern = patterns[i];
503
- if (patternMatchesUrl(pattern, hostname, pathname)) {
504
+ if (typeof pattern === "string" && patternMatchesUrl(pattern, hostname, pathname)) {
504
505
  if (firstOnly) {
505
506
  return key;
506
507
  }
@@ -542,10 +543,18 @@
542
543
  // -------------------------------------------------------------------------
543
544
  /// End
544
545
  // -------------------------------------------------------------------------
545
- var SCRIPT_VERSION = "309";
546
+ var SCRIPT_VERSION = "311";
546
547
  var logger = new Logger();
547
548
  var globalConfig = fromObject(LUX);
548
549
  logger.logEvent(LogEvent.EvaluationStart, [SCRIPT_VERSION]);
550
+ // Variable aliases that allow the minifier to reduce file size.
551
+ var document = window.document;
552
+ var addEventListener = window.addEventListener;
553
+ var removeEventListener = window.removeEventListener;
554
+ var setTimeout = window.setTimeout;
555
+ var clearTimeout = window.clearTimeout;
556
+ var encodeURIComponent = window.encodeURIComponent;
557
+ var thisScript = document.currentScript || {};
549
558
  // Log JS errors.
550
559
  var nErrors = 0;
551
560
  function errorHandler(e) {
@@ -560,30 +569,30 @@
560
569
  // Sample & limit other errors.
561
570
  // Send the error beacon.
562
571
  new Image().src =
563
- globalConfig.errorBeaconUrl +
564
- "?v=" +
565
- SCRIPT_VERSION +
566
- "&id=" +
567
- getCustomerId() +
568
- "&fn=" +
569
- encodeURIComponent(e.filename) +
570
- "&ln=" +
571
- e.lineno +
572
- "&cn=" +
573
- e.colno +
574
- "&msg=" +
575
- encodeURIComponent(e.message) +
576
- "&l=" +
577
- encodeURIComponent(_getPageLabel()) +
578
- (connectionType() ? "&ct=" + connectionType() : "") +
579
- "&HN=" +
580
- encodeURIComponent(document.location.hostname) +
581
- "&PN=" +
582
- encodeURIComponent(document.location.pathname);
583
- }
584
- }
585
- }
586
- window.addEventListener("error", errorHandler);
572
+ globalConfig.errorBeaconUrl +
573
+ "?v=" +
574
+ SCRIPT_VERSION +
575
+ "&id=" +
576
+ getCustomerId() +
577
+ "&fn=" +
578
+ encodeURIComponent(e.filename) +
579
+ "&ln=" +
580
+ e.lineno +
581
+ "&cn=" +
582
+ e.colno +
583
+ "&msg=" +
584
+ encodeURIComponent(e.message) +
585
+ "&l=" +
586
+ encodeURIComponent(_getPageLabel()) +
587
+ (connectionType() ? "&ct=" + connectionType() : "") +
588
+ "&HN=" +
589
+ encodeURIComponent(document.location.hostname) +
590
+ "&PN=" +
591
+ encodeURIComponent(document.location.pathname);
592
+ }
593
+ }
594
+ }
595
+ addEventListener("error", errorHandler);
587
596
  var logEntry = function (entry) {
588
597
  logger.logEvent(LogEvent.PerformanceEntryReceived, [entry]);
589
598
  };
@@ -611,9 +620,9 @@
611
620
  logEntry(entry);
612
621
  });
613
622
  observe("first-input", function (entry) {
614
- var fid = entry.processingStart - entry.startTime;
615
- if (!gFirstInputDelay || gFirstInputDelay < fid) {
616
- gFirstInputDelay = floor(fid);
623
+ var entryTime = entry.processingStart - entry.startTime;
624
+ if (!gFirstInputDelay || gFirstInputDelay < entryTime) {
625
+ gFirstInputDelay = floor(entryTime);
617
626
  }
618
627
  // Allow first-input events to be considered for INP
619
628
  addEntry$1(entry);
@@ -642,11 +651,24 @@
642
651
  var gMaxMeasureTimeout; // setTimeout timer for sending the beacon after a maximum measurement time
643
652
  var pageRestoreTime; // ms since navigationStart representing when the page was restored from the bfcache
644
653
  /**
645
- * To measure the way a user experienced a metric, we measure metrics relative to the time the user
646
- * started viewing the page. On prerendered pages, this is activationStart. On bfcache restores, this
647
- * is the page restore time. On all other pages this value will be zero.
648
- */
649
- var getZeroTime = function () { return pageRestoreTime || getNavigationEntry().activationStart; };
654
+ * To measure the way a user experienced a metric, we measure metrics relative to the time the user
655
+ * started viewing the page. On prerendered pages, this is activationStart. On bfcache restores, this
656
+ * is the page restore time. On all other pages this value will be zero.
657
+ */
658
+ var getZeroTime = function () {
659
+ var _a;
660
+ return Math.max(pageRestoreTime || 0, getNavigationEntry().activationStart, ((_a = _getMark(START_MARK)) === null || _a === void 0 ? void 0 : _a.startTime) || 0);
661
+ };
662
+ /**
663
+ * Most time-based metrics that LUX reports should be relative to the "zero" marker, rounded down
664
+ * to the nearest unit so as not to report times in the future, and clamped to zero.
665
+ */
666
+ var processTimeMetric = function (value) { return clamp(floor(value - getZeroTime())); };
667
+ /**
668
+ * Some values should only be reported if they are non-zero. The exception to this is when the page
669
+ * was prerendered or restored from BF cache
670
+ */
671
+ var shouldReportValue = function (value) { return value > 0 || pageRestoreTime || wasPrerendered(); };
650
672
  if (_sample()) {
651
673
  logger.logEvent(LogEvent.SessionIsSampled, [globalConfig.samplerate]);
652
674
  }
@@ -688,11 +710,11 @@
688
710
  removeListeners();
689
711
  }
690
712
  function removeListeners() {
691
- window.removeEventListener("pointerup", onPointerUp, ghListenerOptions);
692
- window.removeEventListener("pointercancel", onPointerCancel, ghListenerOptions);
713
+ removeEventListener("pointerup", onPointerUp, ghListenerOptions);
714
+ removeEventListener("pointercancel", onPointerCancel, ghListenerOptions);
693
715
  }
694
- window.addEventListener("pointerup", onPointerUp, ghListenerOptions);
695
- window.addEventListener("pointercancel", onPointerCancel, ghListenerOptions);
716
+ addEventListener("pointerup", onPointerUp, ghListenerOptions);
717
+ addEventListener("pointercancel", onPointerCancel, ghListenerOptions);
696
718
  }
697
719
  // Record FID as the delta between when the event happened and when the
698
720
  // listener was able to execute.
@@ -732,16 +754,16 @@
732
754
  }
733
755
  // Attach event listener to input events.
734
756
  gaEventTypes.forEach(function (eventType) {
735
- window.addEventListener(eventType, onInput, ghListenerOptions);
757
+ addEventListener(eventType, onInput, ghListenerOptions);
736
758
  });
737
759
  ////////////////////// FID END
738
760
  /**
739
- * Returns the time elapsed (in ms) since navigationStart. For SPAs, returns
740
- * the time elapsed since the last LUX.init call.
741
- *
742
- * When `absolute = true` the time is always relative to navigationStart, even
743
- * in SPAs.
744
- */
761
+ * Returns the time elapsed (in ms) since navigationStart. For SPAs, returns
762
+ * the time elapsed since the last LUX.init call.
763
+ *
764
+ * When `absolute = true` the time is always relative to navigationStart, even
765
+ * in SPAs.
766
+ */
745
767
  function _now(absolute) {
746
768
  var sinceNavigationStart = msSinceNavigationStart();
747
769
  var startMark = _getMark(START_MARK);
@@ -766,7 +788,7 @@
766
788
  return performance.mark.apply(performance, args);
767
789
  }
768
790
  // ...Otherwise provide a polyfill
769
- if (__ENABLE_POLYFILLS) {
791
+ {
770
792
  var name_1 = args[0];
771
793
  var detail = ((_a = args[1]) === null || _a === void 0 ? void 0 : _a.detail) || null;
772
794
  var startTime = ((_b = args[1]) === null || _b === void 0 ? void 0 : _b.startTime) || _now();
@@ -829,14 +851,14 @@
829
851
  return performance.measure.apply(performance, args);
830
852
  }
831
853
  // ...Otherwise provide a polyfill
832
- if (__ENABLE_POLYFILLS) {
854
+ {
833
855
  var navEntry = getNavigationEntry();
834
856
  var startTime = typeof startMarkName === "number" ? startMarkName : 0;
835
857
  var endTime = typeof endMarkName === "number" ? endMarkName : _now();
836
858
  var throwError = function (missingMark) {
837
859
  throw new DOMException("Failed to execute 'measure' on 'Performance': The mark '" +
838
- missingMark +
839
- "' does not exist");
860
+ missingMark +
861
+ "' does not exist");
840
862
  };
841
863
  if (typeof startMarkName === "string") {
842
864
  var startMark = _getMark(startMarkName);
@@ -924,7 +946,7 @@
924
946
  var startMark = _getMark(START_MARK);
925
947
  // For user timing values taken in a SPA page load, we need to adjust them
926
948
  // so that they're zeroed against the last LUX.init() call.
927
- var tZero = startMark ? startMark.startTime : 0;
949
+ var tZero = getZeroTime();
928
950
  // marks
929
951
  _getMarks().forEach(function (mark) {
930
952
  var name = mark.name;
@@ -973,12 +995,13 @@
973
995
  // Return a string of Element Timing Metrics formatted for beacon querystring.
974
996
  function elementTimingValues() {
975
997
  var aET = [];
976
- var startMark = _getMark(START_MARK);
977
- var tZero = startMark ? startMark.startTime : getZeroTime();
978
998
  getEntries("element").forEach(function (entry) {
979
999
  if (entry.identifier && entry.startTime) {
980
- logger.logEvent(LogEvent.PerformanceEntryProcessed, [entry]);
981
- aET.push(entry.identifier + "|" + floor(entry.startTime - tZero));
1000
+ var value = processTimeMetric(entry.startTime);
1001
+ if (shouldReportValue(value)) {
1002
+ logger.logEvent(LogEvent.PerformanceEntryProcessed, [entry]);
1003
+ aET.push(entry.identifier + "|" + value);
1004
+ }
982
1005
  }
983
1006
  });
984
1007
  return aET.join(",");
@@ -995,20 +1018,7 @@
995
1018
  var longTaskEntries = getEntries("longtask");
996
1019
  // Add up totals for each "type" of long task
997
1020
  if (longTaskEntries.length) {
998
- // Long Task start times are relative to NavigationStart which is "0".
999
- // But if it is a SPA then the relative start time is gStartMark.
1000
- var startMark = _getMark(START_MARK);
1001
- var tZero_1 = startMark ? startMark.startTime : 0;
1002
- // Do not include Long Tasks that start after the page is done.
1003
- // For full page loads, "done" is loadEventEnd.
1004
- var tEnd_1 = timing.loadEventEnd - timing.navigationStart;
1005
- if (startMark) {
1006
- // For SPA page loads (determined by the presence of a start mark), "done" is gEndMark.
1007
- var endMark = _getMark(END_MARK);
1008
- if (endMark) {
1009
- tEnd_1 = endMark.startTime;
1010
- }
1011
- }
1021
+ var tZero_1 = getZeroTime();
1012
1022
  longTaskEntries.forEach(function (entry) {
1013
1023
  var dur = floor(entry.duration);
1014
1024
  if (entry.startTime < tZero_1) {
@@ -1016,21 +1026,18 @@
1016
1026
  // LUX.init() was called. If so, only include the duration after tZero.
1017
1027
  dur -= tZero_1 - entry.startTime;
1018
1028
  }
1019
- else if (entry.startTime >= tEnd_1) {
1020
- // In a SPA it is possible that a Long Task started after loadEventEnd but before our
1021
- // callback from setTimeout(200) happened. Do not include anything that started after tEnd.
1022
- return;
1023
- }
1024
- logger.logEvent(LogEvent.PerformanceEntryProcessed, [entry]);
1025
- var type = entry.attribution[0].name; // TODO - is there ever more than 1 attribution???
1026
- if (!hCPU[type]) {
1027
- // initialize this category
1028
- hCPU[type] = 0;
1029
- hCPUDetails[type] = "";
1029
+ // Only process entries that we calculated to have a valid duration
1030
+ if (dur > 0) {
1031
+ logger.logEvent(LogEvent.PerformanceEntryProcessed, [entry]);
1032
+ var type = entry.attribution[0].name;
1033
+ if (!hCPU[type]) {
1034
+ hCPU[type] = 0;
1035
+ hCPUDetails[type] = "";
1036
+ }
1037
+ hCPU[type] += dur;
1038
+ // Send back the raw startTime and duration, as well as the adjusted duration.
1039
+ hCPUDetails[type] += "," + floor(entry.startTime) + "|" + dur;
1030
1040
  }
1031
- hCPU[type] += dur;
1032
- // Send back the raw startTime and duration, as well as the adjusted duration.
1033
- hCPUDetails[type] += "," + floor(entry.startTime) + "|" + dur;
1034
1041
  });
1035
1042
  }
1036
1043
  // TODO - Add more types if/when they become available.
@@ -1042,12 +1049,12 @@
1042
1049
  }
1043
1050
  var hStats = cpuStats(hCPUDetails[jsType]);
1044
1051
  var sStats = ",n|" +
1045
- hStats["count"] +
1046
- ",d|" +
1047
- hStats["median"] +
1048
- ",x|" +
1049
- hStats["max"] +
1050
- (0 === hStats["fci"] ? "" : ",i|" + hStats["fci"]); // only add FCI if it is non-zero
1052
+ hStats.count +
1053
+ ",d|" +
1054
+ hStats.median +
1055
+ ",x|" +
1056
+ hStats.max +
1057
+ (typeof hStats.fci === "undefined" ? "" : ",i|" + hStats.fci);
1051
1058
  sCPU += "s|" + hCPU[jsType] + sStats + hCPUDetails[jsType];
1052
1059
  return sCPU;
1053
1060
  }
@@ -1055,11 +1062,11 @@
1055
1062
  function cpuStats(sDetails) {
1056
1063
  // tuples of starttime|duration, eg: ,456|250,789|250,1012|250
1057
1064
  var max = 0;
1058
- var fci = getFcp() || 0; // FCI is beginning of 5 second window of no Long Tasks _after_ first contentful paint
1059
- // If FCP is 0 then that means FCP is not supported.
1060
- // If FCP is not supported then we can NOT calculate a valid FCI.
1061
- // Thus, leave FCI = 0 and exclude it from the beacon above.
1062
- var bFoundFci = 0 === fci ? true : false;
1065
+ // FCI is beginning of 5 second window of no Long Tasks _after_ first contentful paint
1066
+ var fcp = getFcp();
1067
+ var fci = fcp || 0;
1068
+ // If FCP is not supported, we can't calculate a valid FCI.
1069
+ var bFoundFci = typeof fcp === "undefined";
1063
1070
  var aValues = [];
1064
1071
  var aTuples = sDetails.split(",");
1065
1072
  for (var i = 0; i < aTuples.length; i++) {
@@ -1079,7 +1086,10 @@
1079
1086
  }
1080
1087
  else {
1081
1088
  // Less than 5 seconds of inactivity
1082
- fci = start + dur; // FCI is now the end of this Long Task
1089
+ var val = processTimeMetric(start + dur);
1090
+ if (shouldReportValue(val)) {
1091
+ fci = val; // FCI is now the end of this Long Task
1092
+ }
1083
1093
  }
1084
1094
  }
1085
1095
  }
@@ -1102,9 +1112,7 @@
1102
1112
  return 0;
1103
1113
  }
1104
1114
  var half = floor(aValues.length / 2);
1105
- aValues.sort(function (a, b) {
1106
- return a - b;
1107
- });
1115
+ aValues.sort(sortNumeric);
1108
1116
  if (aValues.length % 2) {
1109
1117
  // Return the middle value.
1110
1118
  return aValues[half];
@@ -1119,42 +1127,39 @@
1119
1127
  var sLuxjs = "";
1120
1128
  if (performance.getEntriesByName) {
1121
1129
  // Get the lux script URL (including querystring params).
1122
- var luxScript = getScriptElement("/js/lux.js");
1123
- if (luxScript) {
1124
- var aResources = performance.getEntriesByName(luxScript.src);
1125
- if (aResources && aResources.length) {
1126
- var r = aResources[0];
1127
- // DO NOT USE DURATION!!!!!
1128
- // See https://www.stevesouders.com/blog/2014/11/25/serious-confusion-with-resource-timing/
1129
- var dns = floor(r.domainLookupEnd - r.domainLookupStart);
1130
- var tcp = floor(r.connectEnd - r.connectStart);
1131
- var fb = floor(r.responseStart - r.requestStart);
1132
- var content = floor(r.responseEnd - r.responseStart);
1133
- var networkDuration = dns + tcp + fb + content;
1134
- var parseEval = scriptEndTime - scriptStartTime;
1135
- var transferSize = r.encodedBodySize ? r.encodedBodySize : 0;
1136
- // Instead of a delimiter use a 1-letter abbreviation as a separator.
1137
- sLuxjs =
1138
- "d" +
1139
- dns +
1140
- "t" +
1141
- tcp +
1142
- "f" +
1143
- fb +
1144
- "c" +
1145
- content +
1146
- "n" +
1147
- networkDuration +
1148
- "e" +
1149
- parseEval +
1150
- "r" +
1151
- globalConfig.samplerate + // sample rate
1152
- (typeof transferSize === "number" ? "x" + transferSize : "") +
1153
- (typeof gLuxSnippetStart === "number" ? "l" + gLuxSnippetStart : "") +
1154
- "s" +
1155
- (scriptStartTime - timing.navigationStart) + // when lux.js started getting evaluated relative to navigationStart
1156
- "";
1157
- }
1130
+ var aResources = performance.getEntriesByName(thisScript.src);
1131
+ if (aResources && aResources.length) {
1132
+ var r = aResources[0];
1133
+ // DO NOT USE DURATION!!!!!
1134
+ // See https://www.stevesouders.com/blog/2014/11/25/serious-confusion-with-resource-timing/
1135
+ var dns = floor(r.domainLookupEnd - r.domainLookupStart);
1136
+ var tcp = floor(r.connectEnd - r.connectStart);
1137
+ var fb = floor(r.responseStart - r.requestStart);
1138
+ var content = floor(r.responseEnd - r.responseStart);
1139
+ var networkDuration = dns + tcp + fb + content;
1140
+ var parseEval = scriptEndTime - scriptStartTime;
1141
+ var transferSize = r.encodedBodySize ? r.encodedBodySize : 0;
1142
+ // Instead of a delimiter use a 1-letter abbreviation as a separator.
1143
+ sLuxjs =
1144
+ "d" +
1145
+ dns +
1146
+ "t" +
1147
+ tcp +
1148
+ "f" +
1149
+ fb +
1150
+ "c" +
1151
+ content +
1152
+ "n" +
1153
+ networkDuration +
1154
+ "e" +
1155
+ parseEval +
1156
+ "r" +
1157
+ globalConfig.samplerate + // sample rate
1158
+ (typeof transferSize === "number" ? "x" + transferSize : "") +
1159
+ (typeof gLuxSnippetStart === "number" ? "l" + gLuxSnippetStart : "") +
1160
+ "s" +
1161
+ (scriptStartTime - timing.navigationStart) + // when lux.js started getting evaluated relative to navigationStart
1162
+ "";
1158
1163
  }
1159
1164
  }
1160
1165
  return sLuxjs;
@@ -1185,9 +1190,9 @@
1185
1190
  if (gCustomerDataTimeout) {
1186
1191
  // Cancel the timer for any previous beacons so that if they have not
1187
1192
  // yet been sent we can combine all the data in a new beacon.
1188
- window.clearTimeout(gCustomerDataTimeout);
1193
+ clearTimeout(gCustomerDataTimeout);
1189
1194
  }
1190
- gCustomerDataTimeout = window.setTimeout(_sendCustomerData, 100);
1195
+ gCustomerDataTimeout = setTimeout(_sendCustomerData, 100);
1191
1196
  }
1192
1197
  }
1193
1198
  // _sample()
@@ -1200,9 +1205,9 @@
1200
1205
  return parseInt(nThis) < globalConfig.samplerate;
1201
1206
  }
1202
1207
  /**
1203
- * Re-initialize lux.js to start a new "page". This is typically called within a SPA at the
1204
- * beginning of a page transition, but is also called internally when the BF cache is restored.
1205
- */
1208
+ * Re-initialize lux.js to start a new "page". This is typically called within a SPA at the
1209
+ * beginning of a page transition, but is also called internally when the BF cache is restored.
1210
+ */
1206
1211
  function _init(startTime) {
1207
1212
  // Some customers (incorrectly) call LUX.init on the very first page load of a SPA. This would
1208
1213
  // cause some first-page-only data (like paint metrics) to be lost. To prevent this, we silently
@@ -1232,7 +1237,6 @@
1232
1237
  gbFirstPV = 0;
1233
1238
  gSyncId = createSyncId();
1234
1239
  gUid = refreshUniqueId(gSyncId);
1235
- clearEntries();
1236
1240
  reset$1();
1237
1241
  reset();
1238
1242
  nErrors = 0;
@@ -1353,14 +1357,17 @@
1353
1357
  ns += start; // "navigationStart" for a SPA is the real navigationStart plus the start mark
1354
1358
  var end = floor(endMark.startTime) - start; // delta from start mark
1355
1359
  s =
1356
- ns +
1357
- "fs" +
1358
- 0 + // fetchStart is the same as navigationStart for a SPA
1359
- "ls" +
1360
- end +
1361
- "le" +
1362
- end +
1363
- "";
1360
+ ns +
1361
+ // fetchStart and activationStart are the same as navigationStart for a SPA
1362
+ "as" +
1363
+ 0 +
1364
+ "fs" +
1365
+ 0 +
1366
+ "ls" +
1367
+ end +
1368
+ "le" +
1369
+ end +
1370
+ "";
1364
1371
  }
1365
1372
  else if (performance.timing) {
1366
1373
  // Return the real Nav Timing metrics because this is the "main" page view (not a SPA)
@@ -1368,17 +1375,20 @@
1368
1375
  var startRender = getStartRender();
1369
1376
  var fcp = getFcp();
1370
1377
  var lcp = getLcp();
1371
- var prefixNTValue = function (key, prefix) {
1372
- // activationStart is always absolute. Other values are relative to activationStart.
1373
- var zero = key === "activationStart" ? 0 : getZeroTime();
1378
+ var prefixNTValue = function (key, prefix, ignoreZero) {
1374
1379
  if (typeof navEntry_1[key] === "number") {
1375
- var value = clamp(floor(navEntry_1[key] - zero));
1376
- return prefix + value;
1380
+ var value = navEntry_1[key];
1381
+ // We allow zero values for most navigation timing metrics, but for some metrics we want
1382
+ // to ignore zeroes. The exceptions are that all metrics can be zero if the page was either
1383
+ // prerendered or restored from the BF cache.
1384
+ if (shouldReportValue(value) || !ignoreZero) {
1385
+ return prefix + processTimeMetric(value);
1386
+ }
1377
1387
  }
1378
1388
  return "";
1379
1389
  };
1380
- var loadEventStartStr = prefixNTValue("loadEventStart", "ls");
1381
- var loadEventEndStr = prefixNTValue("loadEventEnd", "le");
1390
+ var loadEventStartStr = prefixNTValue("loadEventStart", "ls", true);
1391
+ var loadEventEndStr = prefixNTValue("loadEventEnd", "le", true);
1382
1392
  if (pageRestoreTime && startMark && endMark) {
1383
1393
  // For bfcache restores, we set the load time to the time it took for the page to be restored.
1384
1394
  var loadTime = floor(endMark.startTime - startMark.startTime);
@@ -1386,43 +1396,44 @@
1386
1396
  loadEventEndStr = "le" + loadTime;
1387
1397
  }
1388
1398
  var redirect = wasRedirected();
1399
+ var isSecure = document.location.protocol === "https:";
1389
1400
  s = [
1390
1401
  ns,
1391
- prefixNTValue("activationStart", "as"),
1392
- redirect ? prefixNTValue("redirectStart", "rs") : "",
1393
- redirect ? prefixNTValue("redirectEnd", "re") : "",
1402
+ "as" + clamp(navEntry_1.activationStart),
1403
+ redirect && !pageRestoreTime ? prefixNTValue("redirectStart", "rs") : "",
1404
+ redirect && !pageRestoreTime ? prefixNTValue("redirectEnd", "re") : "",
1394
1405
  prefixNTValue("fetchStart", "fs"),
1395
1406
  prefixNTValue("domainLookupStart", "ds"),
1396
1407
  prefixNTValue("domainLookupEnd", "de"),
1397
1408
  prefixNTValue("connectStart", "cs"),
1398
- prefixNTValue("secureConnectionStart", "sc"),
1409
+ isSecure ? prefixNTValue("secureConnectionStart", "sc") : "",
1399
1410
  prefixNTValue("connectEnd", "ce"),
1400
1411
  prefixNTValue("requestStart", "qs"),
1401
1412
  prefixNTValue("responseStart", "bs"),
1402
1413
  prefixNTValue("responseEnd", "be"),
1403
- prefixNTValue("domInteractive", "oi"),
1404
- prefixNTValue("domContentLoadedEventStart", "os"),
1405
- prefixNTValue("domContentLoadedEventEnd", "oe"),
1406
- prefixNTValue("domComplete", "oc"),
1414
+ prefixNTValue("domInteractive", "oi", true),
1415
+ prefixNTValue("domContentLoadedEventStart", "os", true),
1416
+ prefixNTValue("domContentLoadedEventEnd", "oe", true),
1417
+ prefixNTValue("domComplete", "oc", true),
1407
1418
  loadEventStartStr,
1408
1419
  loadEventEndStr,
1409
- typeof startRender !== "undefined" ? "sr" + clamp(startRender) : "",
1410
- typeof fcp !== "undefined" ? "fc" + clamp(fcp) : "",
1411
- typeof lcp !== "undefined" ? "lc" + clamp(lcp) : "",
1420
+ typeof startRender !== "undefined" ? "sr" + startRender : "",
1421
+ typeof fcp !== "undefined" ? "fc" + fcp : "",
1422
+ typeof lcp !== "undefined" ? "lc" + lcp : "",
1412
1423
  ].join("");
1413
1424
  }
1414
1425
  else if (endMark) {
1415
1426
  // This is a "main" page view that does NOT support Navigation Timing - strange.
1416
1427
  var end = floor(endMark.startTime);
1417
1428
  s =
1418
- ns +
1419
- "fs" +
1420
- 0 + // fetchStart is the same as navigationStart
1421
- "ls" +
1422
- end +
1423
- "le" +
1424
- end +
1425
- "";
1429
+ ns +
1430
+ "fs" +
1431
+ 0 + // fetchStart is the same as navigationStart
1432
+ "ls" +
1433
+ end +
1434
+ "le" +
1435
+ end +
1436
+ "";
1426
1437
  }
1427
1438
  return s;
1428
1439
  }
@@ -1432,7 +1443,10 @@
1432
1443
  for (var i = 0; i < paintEntries.length; i++) {
1433
1444
  var entry = paintEntries[i];
1434
1445
  if (entry.name === "first-contentful-paint") {
1435
- return floor(entry.startTime - getZeroTime());
1446
+ var value = processTimeMetric(entry.startTime);
1447
+ if (shouldReportValue(value)) {
1448
+ return value;
1449
+ }
1436
1450
  }
1437
1451
  }
1438
1452
  return undefined;
@@ -1442,8 +1456,11 @@
1442
1456
  var lcpEntries = getEntries("largest-contentful-paint");
1443
1457
  if (lcpEntries.length) {
1444
1458
  var lastEntry = lcpEntries[lcpEntries.length - 1];
1445
- logger.logEvent(LogEvent.PerformanceEntryProcessed, [lastEntry]);
1446
- return floor(lastEntry.startTime - getZeroTime());
1459
+ var value = processTimeMetric(lastEntry.startTime);
1460
+ if (shouldReportValue(value)) {
1461
+ logger.logEvent(LogEvent.PerformanceEntryProcessed, [lastEntry]);
1462
+ return value;
1463
+ }
1447
1464
  }
1448
1465
  return undefined;
1449
1466
  }
@@ -1454,12 +1471,17 @@
1454
1471
  if ("PerformancePaintTiming" in self) {
1455
1472
  var paintEntries = getEntriesByType("paint");
1456
1473
  if (paintEntries.length) {
1457
- // If the Paint Timing API is supported, use the value of the first paint event
1458
- var paintValues = paintEntries.map(function (entry) { return entry.startTime; });
1459
- return floor(Math.min.apply(null, paintValues) - getZeroTime());
1474
+ var paintValues = paintEntries.map(function (entry) { return entry.startTime; }).sort(sortNumeric);
1475
+ // Use the earliest valid paint entry as the start render time.
1476
+ for (var i = 0; i < paintValues.length; i++) {
1477
+ var value = processTimeMetric(paintValues[i]);
1478
+ if (shouldReportValue(value)) {
1479
+ return value;
1480
+ }
1481
+ }
1460
1482
  }
1461
1483
  }
1462
- if (performance.timing && timing.msFirstPaint && __ENABLE_POLYFILLS) {
1484
+ if (performance.timing && timing.msFirstPaint && true) {
1463
1485
  // If IE/Edge, use the prefixed `msFirstPaint` property (see http://msdn.microsoft.com/ff974719).
1464
1486
  return floor(timing.msFirstPaint - timing.navigationStart);
1465
1487
  }
@@ -1473,40 +1495,11 @@
1473
1495
  return getHighPercentileINP();
1474
1496
  }
1475
1497
  function getCustomerId() {
1476
- if (typeof LUX.customerid === "undefined") {
1477
- // Extract the id of the lux.js script element.
1478
- var luxScript = getScriptElement("/js/lux.js");
1479
- if (luxScript) {
1480
- LUX.customerid = getQuerystringParam(luxScript.src, "id");
1481
- }
1498
+ if (!LUX.customerid) {
1499
+ LUX.customerid = thisScript.src.match(/id=(\d+)/).pop();
1482
1500
  }
1483
1501
  return LUX.customerid || "";
1484
1502
  }
1485
- // Return the SCRIPT DOM element whose SRC contains the URL snippet.
1486
- // This is used to find the LUX script element.
1487
- function getScriptElement(urlsnippet) {
1488
- var aScripts = document.getElementsByTagName("script");
1489
- for (var i = 0, len = aScripts.length; i < len; i++) {
1490
- var script = aScripts[i];
1491
- if (script.src && -1 !== script.src.indexOf(urlsnippet)) {
1492
- return script;
1493
- }
1494
- }
1495
- return undefined;
1496
- }
1497
- function getQuerystringParam(url, name) {
1498
- var qs = url.split("?")[1];
1499
- var aTuples = qs.split("&");
1500
- for (var i = 0, len = aTuples.length; i < len; i++) {
1501
- var tuple = aTuples[i];
1502
- var aTuple = tuple.split("=");
1503
- var key = aTuple[0];
1504
- if (name === key) {
1505
- return aTuple[1];
1506
- }
1507
- }
1508
- return undefined;
1509
- }
1510
1503
  function avgDomDepth() {
1511
1504
  var aElems = document.getElementsByTagName("*");
1512
1505
  var i = aElems.length;
@@ -1645,14 +1638,14 @@
1645
1638
  }
1646
1639
  function createMaxMeasureTimeout() {
1647
1640
  clearMaxMeasureTimeout();
1648
- gMaxMeasureTimeout = window.setTimeout(function () {
1641
+ gMaxMeasureTimeout = setTimeout(function () {
1649
1642
  gFlags = addFlag(gFlags, Flags.BeaconSentAfterTimeout);
1650
1643
  _sendLux();
1651
1644
  }, globalConfig.maxMeasureTime - _now());
1652
1645
  }
1653
1646
  function clearMaxMeasureTimeout() {
1654
1647
  if (gMaxMeasureTimeout) {
1655
- window.clearTimeout(gMaxMeasureTimeout);
1648
+ clearTimeout(gMaxMeasureTimeout);
1656
1649
  }
1657
1650
  }
1658
1651
  function _getBeaconUrl(customData) {
@@ -1688,7 +1681,7 @@
1688
1681
  !gSyncId ||
1689
1682
  !_sample() || // OUTSIDE the sampled range
1690
1683
  gbLuxSent // LUX data already sent
1691
- ) {
1684
+ ) {
1692
1685
  return;
1693
1686
  }
1694
1687
  logger.logEvent(LogEvent.DataCollectionStart);
@@ -1741,49 +1734,49 @@
1741
1734
  var is = inlineTagSize("script");
1742
1735
  var ic = inlineTagSize("style");
1743
1736
  var metricsQueryString =
1744
- // only send Nav Timing and lux.js metrics on initial pageload (not for SPA page views)
1745
- (gbNavSent ? "" : "&NT=" + getNavTiming()) +
1746
- (gbFirstPV ? "&LJS=" + sLuxjs : "") +
1747
- // Page Stats
1748
- "&PS=ns" +
1749
- numScripts() +
1750
- "bs" +
1751
- blockingScripts() +
1752
- (is > -1 ? "is" + is : "") +
1753
- "ss" +
1754
- numStylesheets() +
1755
- "bc" +
1756
- blockingStylesheets() +
1757
- (ic > -1 ? "ic" + ic : "") +
1758
- "ia" +
1759
- imagesATF().length +
1760
- "it" +
1761
- document.getElementsByTagName("img").length + // total number of images
1762
- "dd" +
1763
- avgDomDepth() +
1764
- "nd" +
1765
- document.getElementsByTagName("*").length + // numdomelements
1766
- "vh" +
1767
- document.documentElement.clientHeight + // see http://www.quirksmode.org/mobile/viewports.html
1768
- "vw" +
1769
- document.documentElement.clientWidth +
1770
- "dh" +
1771
- docHeight(document) +
1772
- "dw" +
1773
- docWidth(document) +
1774
- (docSize() ? "ds" + docSize() : "") + // document HTTP transfer size (bytes)
1775
- (connectionType() ? "ct" + connectionType() + "_" : "") + // delimit with "_" since values can be non-numeric so need a way to extract with regex in VCL
1776
- "er" +
1777
- nErrors +
1778
- "nt" +
1779
- navigationType() +
1780
- (navigator.deviceMemory ? "dm" + Math.round(navigator.deviceMemory) : "") + // device memory (GB)
1781
- (sIx ? "&IX=" + sIx : "") +
1782
- (typeof gFirstInputDelay !== "undefined" ? "&FID=" + gFirstInputDelay : "") +
1783
- (sCPU ? "&CPU=" + sCPU : "") +
1784
- (sET ? "&ET=" + sET : "") + // element timing
1785
- (typeof CLS !== "undefined" ? "&CLS=" + CLS : "") +
1786
- (typeof INP !== "undefined" ? "&INP=" + INP : "");
1737
+ // only send Nav Timing and lux.js metrics on initial pageload (not for SPA page views)
1738
+ (gbNavSent ? "" : "&NT=" + getNavTiming()) +
1739
+ (gbFirstPV ? "&LJS=" + sLuxjs : "") +
1740
+ // Page Stats
1741
+ "&PS=ns" +
1742
+ numScripts() +
1743
+ "bs" +
1744
+ blockingScripts() +
1745
+ (is > -1 ? "is" + is : "") +
1746
+ "ss" +
1747
+ numStylesheets() +
1748
+ "bc" +
1749
+ blockingStylesheets() +
1750
+ (ic > -1 ? "ic" + ic : "") +
1751
+ "ia" +
1752
+ imagesATF().length +
1753
+ "it" +
1754
+ document.getElementsByTagName("img").length + // total number of images
1755
+ "dd" +
1756
+ avgDomDepth() +
1757
+ "nd" +
1758
+ document.getElementsByTagName("*").length + // numdomelements
1759
+ "vh" +
1760
+ document.documentElement.clientHeight + // see http://www.quirksmode.org/mobile/viewports.html
1761
+ "vw" +
1762
+ document.documentElement.clientWidth +
1763
+ "dh" +
1764
+ docHeight(document) +
1765
+ "dw" +
1766
+ docWidth(document) +
1767
+ (docSize() ? "ds" + docSize() : "") + // document HTTP transfer size (bytes)
1768
+ (connectionType() ? "ct" + connectionType() + "_" : "") + // delimit with "_" since values can be non-numeric so need a way to extract with regex in VCL
1769
+ "er" +
1770
+ nErrors +
1771
+ "nt" +
1772
+ navigationType() +
1773
+ (navigator.deviceMemory ? "dm" + Math.round(navigator.deviceMemory) : "") + // device memory (GB)
1774
+ (sIx ? "&IX=" + sIx : "") +
1775
+ (typeof gFirstInputDelay !== "undefined" ? "&FID=" + gFirstInputDelay : "") +
1776
+ (sCPU ? "&CPU=" + sCPU : "") +
1777
+ (sET ? "&ET=" + sET : "") + // element timing
1778
+ (typeof CLS !== "undefined" ? "&CLS=" + CLS : "") +
1779
+ (typeof INP !== "undefined" ? "&INP=" + INP : "");
1787
1780
  // We add the user timing entries last so that we can split them to reduce the URL size if necessary.
1788
1781
  var utValues = userTimingValues();
1789
1782
  var _b = fitUserTimingEntries(utValues, globalConfig, baseUrl + metricsQueryString), beaconUtValues = _b[0], remainingUtValues = _b[1];
@@ -1807,8 +1800,8 @@
1807
1800
  }
1808
1801
  var ixTimerId;
1809
1802
  function _sendIxAfterDelay() {
1810
- window.clearTimeout(ixTimerId);
1811
- ixTimerId = window.setTimeout(_sendIx, 100);
1803
+ clearTimeout(ixTimerId);
1804
+ ixTimerId = setTimeout(_sendIx, 100);
1812
1805
  }
1813
1806
  // Beacon back the IX data separately (need to sync with LUX beacon on the backend).
1814
1807
  function _sendIx() {
@@ -1842,7 +1835,7 @@
1842
1835
  !gSyncId ||
1843
1836
  !_sample() || // OUTSIDE the sampled range
1844
1837
  !gbLuxSent // LUX has NOT been sent yet, so wait to include it there
1845
- ) {
1838
+ ) {
1846
1839
  return;
1847
1840
  }
1848
1841
  var sCustomerData = valuesToString(getUpdatedCustomData());
@@ -1870,6 +1863,19 @@
1870
1863
  }
1871
1864
  }
1872
1865
  function _keyHandler(e) {
1866
+ var keyCode = e.keyCode;
1867
+ /**
1868
+ * Ignore modifier keys
1869
+ *
1870
+ * 16 = Shift
1871
+ * 17 = Control
1872
+ * 18 = Alt
1873
+ * 20 = Caps Lock
1874
+ * 224 = Meta/Command
1875
+ */
1876
+ if (keyCode === 16 || keyCode === 17 || keyCode === 18 || keyCode === 20 || keyCode === 224) {
1877
+ return;
1878
+ }
1873
1879
  _removeIxHandlers();
1874
1880
  if (typeof ghIx["k"] === "undefined") {
1875
1881
  ghIx["k"] = _now();
@@ -1914,10 +1920,10 @@
1914
1920
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
1915
1921
  function addListener(type, callback, useCapture) {
1916
1922
  if (useCapture === void 0) { useCapture = false; }
1917
- if (window.addEventListener) {
1918
- window.addEventListener(type, callback, useCapture);
1923
+ if (addEventListener) {
1924
+ addEventListener(type, callback, useCapture);
1919
1925
  }
1920
- else if (window.attachEvent && __ENABLE_POLYFILLS) {
1926
+ else if (window.attachEvent && true) {
1921
1927
  window.attachEvent("on" + type, callback);
1922
1928
  }
1923
1929
  }
@@ -1925,10 +1931,10 @@
1925
1931
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
1926
1932
  function removeListener(type, callback, useCapture) {
1927
1933
  if (useCapture === void 0) { useCapture = false; }
1928
- if (window.removeEventListener) {
1929
- window.removeEventListener(type, callback, useCapture);
1934
+ if (removeEventListener) {
1935
+ removeEventListener(type, callback, useCapture);
1930
1936
  }
1931
- else if (window.detachEvent && __ENABLE_POLYFILLS) {
1937
+ else if (window.detachEvent && true) {
1932
1938
  window.detachEvent("on" + type, callback);
1933
1939
  }
1934
1940
  }
@@ -2016,7 +2022,7 @@
2016
2022
  if (typeof LUX.pagegroups !== "undefined") {
2017
2023
  var label = getMatchesFromPatternMap(LUX.pagegroups, location.hostname, location.pathname, true);
2018
2024
  if (label) {
2019
- gFlags = addFlag(gFlags, Flags.PageLabelFromPagegroup);
2025
+ gFlags = addFlag(gFlags, Flags.PageLabelFromUrlPattern);
2020
2026
  return label;
2021
2027
  }
2022
2028
  }
@@ -2057,11 +2063,11 @@
2057
2063
  function _setCookie(name, value, seconds) {
2058
2064
  try {
2059
2065
  document.cookie =
2060
- name +
2061
- "=" +
2062
- escape(value) +
2063
- (seconds ? "; max-age=" + seconds : "") +
2064
- "; path=/; SameSite=Lax";
2066
+ name +
2067
+ "=" +
2068
+ escape(value) +
2069
+ (seconds ? "; max-age=" + seconds : "") +
2070
+ "; path=/; SameSite=Lax";
2065
2071
  }
2066
2072
  catch (e) {
2067
2073
  logger.logEvent(LogEvent.CookieSetError);
@@ -2111,7 +2117,7 @@
2111
2117
  // bfcache. Since we have no "onload" event to hook into after a bfcache restore, we rely on the
2112
2118
  // unload and maxMeasureTime handlers to send the beacon.
2113
2119
  if (globalConfig.newBeaconOnPageShow) {
2114
- window.addEventListener("pageshow", function (event) {
2120
+ addEventListener("pageshow", function (event) {
2115
2121
  if (event.persisted) {
2116
2122
  // Record the timestamp of the bfcache restore
2117
2123
  pageRestoreTime = event.timeStamp;
@@ -2141,9 +2147,9 @@
2141
2147
  // Set the maximum measurement timer
2142
2148
  createMaxMeasureTimeout();
2143
2149
  /**
2144
- * LUX functions and properties must be attached to the existing global object to ensure that
2145
- * changes made to the global object are reflected in the "internal" LUX object, and vice versa.
2146
- */
2150
+ * LUX functions and properties must be attached to the existing global object to ensure that
2151
+ * changes made to the global object are reflected in the "internal" LUX object, and vice versa.
2152
+ */
2147
2153
  var globalLux = globalConfig;
2148
2154
  // Functions
2149
2155
  globalLux.mark = _mark;
@@ -2168,8 +2174,8 @@
2168
2174
  // Public properties
2169
2175
  globalLux.version = SCRIPT_VERSION;
2170
2176
  /**
2171
- * Run a command from the command queue
2172
- */
2177
+ * Run a command from the command queue
2178
+ */
2173
2179
  function _runCommand(_a) {
2174
2180
  var fn = _a[0], args = _a.slice(1);
2175
2181
  if (typeof globalLux[fn] === "function") {
@@ -17,6 +17,12 @@
17
17
  display: block !important; // stylelint-disable-line declaration-no-important
18
18
  }
19
19
 
20
+ .js-enabled .govuk-accordion__section-content[hidden] {
21
+ @supports (content-visibility: hidden) {
22
+ content-visibility: auto;
23
+ }
24
+ }
25
+
20
26
  // Change the colour from the blue link colour to black.
21
27
  .govuk-accordion__section-button {
22
28
  color: govuk-colour("black") !important; // stylelint-disable-line declaration-no-important
@@ -34,6 +34,12 @@
34
34
  // stylelint-disable max-nesting-depth
35
35
 
36
36
  .gem-c-govspeak {
37
+ a[href^="/"]:after,a[href^="http://"]:after,a[href^="https://"]:after {
38
+ content: " (" attr(href) ")";
39
+ font-size: 90%;
40
+ word-wrap: break-word;
41
+ }
42
+
37
43
  .media-player {
38
44
  display: none;
39
45
  }
@@ -54,8 +54,9 @@
54
54
  )
55
55
  end
56
56
 
57
+ data_attributes[:ga4_link] = ga4_link
57
58
  %>
58
- <%= tag.section class: class_names(container_class_names), data: { module: "ga4-link-tracker", ga4_track_links_only: "", ga4_link: ga4_link } do %>
59
+ <%= tag.section class: class_names(container_class_names), data: { module: "ga4-link-tracker" } do %>
59
60
  <%= tag.div class: "gem-c-attachment__thumbnail" do %>
60
61
  <%= link_to attachment.url,
61
62
  class: "govuk-link",
@@ -1,6 +1,7 @@
1
1
  <div class="govuk-width-container">
2
2
  <%= render "govuk_publishing_components/components/phase_banner", {
3
3
  phase: "beta",
4
+ ga4_tracking: true,
4
5
  message: sanitize(t("components.layout_for_public.account_layout.feedback.banners.phase_banner_html"))
5
6
  } unless omit_account_phase_banner %>
6
7
 
@@ -1,3 +1,3 @@
1
1
  module GovukPublishingComponents
2
- VERSION = "35.15.0".freeze
2
+ VERSION = "35.15.1".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: 35.15.0
4
+ version: 35.15.1
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: 2023-08-31 00:00:00.000000000 Z
11
+ date: 2023-09-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: govuk_app_config