govuk_publishing_components 35.3.4 → 35.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/component_guide/audit-filter.js +81 -0
  3. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-core.js +4 -0
  4. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-link-tracker.js +4 -3
  5. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-specialist-link-tracker.js +5 -1
  6. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/init-ga4.js +1 -1
  7. data/app/assets/javascripts/govuk_publishing_components/components/step-by-step-nav.js +1 -1
  8. data/app/assets/javascripts/govuk_publishing_components/vendor/lux/lux-reporter.js +245 -176
  9. data/app/assets/stylesheets/component_guide/application.scss +16 -0
  10. data/app/assets/stylesheets/govuk_publishing_components/components/_layout-super-navigation-header.scss +0 -5
  11. data/app/assets/stylesheets/govuk_publishing_components/components/_search.scss +0 -12
  12. data/app/assets/stylesheets/govuk_publishing_components/components/govspeak/_attachment.scss +0 -11
  13. data/app/assets/stylesheets/govuk_publishing_components/components/helpers/_brand-colours.scss +0 -24
  14. data/app/models/govuk_publishing_components/audit_applications.rb +14 -0
  15. data/app/models/govuk_publishing_components/audit_comparer.rb +14 -0
  16. data/app/models/govuk_publishing_components/audit_components.rb +34 -32
  17. data/app/views/govuk_publishing_components/audit/_applications.html.erb +40 -32
  18. data/app/views/govuk_publishing_components/audit/_component_contents.html.erb +56 -12
  19. data/app/views/govuk_publishing_components/audit/_components.html.erb +9 -7
  20. data/app/views/govuk_publishing_components/audit/show.html.erb +5 -1
  21. data/app/views/govuk_publishing_components/components/_hint.html.erb +5 -1
  22. data/app/views/govuk_publishing_components/components/_label.html.erb +6 -6
  23. data/app/views/govuk_publishing_components/components/_related_navigation.html.erb +3 -1
  24. data/app/views/govuk_publishing_components/components/docs/hint.yml +1 -1
  25. data/app/views/govuk_publishing_components/components/related_navigation/_section.html.erb +1 -1
  26. data/config/locales/en.yml +2 -2
  27. data/lib/generators/govuk_publishing_components/component_generator.rb +2 -2
  28. data/lib/govuk_publishing_components/presenters/related_navigation_helper.rb +8 -8
  29. data/lib/govuk_publishing_components/version.rb +1 -1
  30. data/node_modules/axe-core/README.md +1 -3
  31. data/node_modules/axe-core/axe.js +4385 -1157
  32. data/node_modules/axe-core/axe.min.js +2 -2
  33. data/node_modules/axe-core/locales/_template.json +12 -0
  34. data/node_modules/axe-core/package.json +2 -1
  35. data/node_modules/axe-core/sri-history.json +4 -0
  36. metadata +4 -3
@@ -42,9 +42,10 @@
42
42
  var autoMode = getProperty(obj, "auto", true);
43
43
  return {
44
44
  auto: autoMode,
45
+ autoWhenHidden: getProperty(obj, "autoWhenHidden", false),
45
46
  beaconUrl: getProperty(obj, "beaconUrl", "https://lux.speedcurve.com/lux/"),
47
+ conversions: getProperty(obj, "conversions", undefined),
46
48
  customerid: getProperty(obj, "customerid", undefined),
47
- debug: getProperty(obj, "debug", false),
48
49
  errorBeaconUrl: getProperty(obj, "errorBeaconUrl", "https://lux.speedcurve.com/error/"),
49
50
  jspagelabel: getProperty(obj, "jspagelabel", undefined),
50
51
  label: getProperty(obj, "label", undefined),
@@ -52,7 +53,6 @@
52
53
  maxBeaconUTEntries: getProperty(obj, "maxBeaconUTEntries", 20),
53
54
  maxErrors: getProperty(obj, "maxErrors", 5),
54
55
  maxMeasureTime: getProperty(obj, "maxMeasureTime", 60000),
55
- measureUntil: getProperty(obj, "measureUntil", "onload"),
56
56
  minMeasureTime: getProperty(obj, "minMeasureTime", 0),
57
57
  samplerate: getProperty(obj, "samplerate", 100),
58
58
  sendBeaconOnPageHidden: getProperty(obj, "sendBeaconOnPageHidden", autoMode),
@@ -69,6 +69,7 @@
69
69
 
70
70
  var START_MARK = "LUX_start";
71
71
  var END_MARK = "LUX_end";
72
+ var BOOLEAN_TRUE = "true";
72
73
 
73
74
  var customDataValues = {};
74
75
  var updatedCustomData = {};
@@ -111,6 +112,104 @@
111
112
  return encodeURIComponent(strings.join(","));
112
113
  }
113
114
 
115
+ function floor(x) {
116
+ return Math.floor(x);
117
+ }
118
+
119
+ function now() {
120
+ return Date.now ? Date.now() : +new Date();
121
+ }
122
+
123
+ var scriptStartTime = now();
124
+
125
+ var _a;
126
+ // If the various performance APIs aren't available, we export an empty object to
127
+ // prevent having to make regular typeof checks.
128
+ var performance = window.performance || {};
129
+ var timing = performance.timing || {
130
+ // If performance.timing isn't available, we attempt to polyfill the navigationStart value.
131
+ // Our first attempt is from LUX.ns, which is the time that the snippet execution began. If this
132
+ // is not available, we fall back to the time that the current script execution began.
133
+ navigationStart: ((_a = window.LUX) === null || _a === void 0 ? void 0 : _a.ns) || scriptStartTime,
134
+ };
135
+ function msSinceNavigationStart() {
136
+ if (performance.now) {
137
+ return floor(performance.now());
138
+ }
139
+ return now() - timing.navigationStart;
140
+ }
141
+ function navigationType() {
142
+ if (performance.navigation && typeof performance.navigation.type !== "undefined") {
143
+ return performance.navigation.type;
144
+ }
145
+ return "";
146
+ }
147
+ function getNavigationEntry() {
148
+ var navEntries = getEntriesByType("navigation");
149
+ if (navEntries.length) {
150
+ var entry_1 = navEntries[0];
151
+ entry_1.navigationStart = 0;
152
+ if (typeof entry_1.activationStart === "undefined") {
153
+ entry_1.activationStart = 0;
154
+ }
155
+ return entry_1;
156
+ }
157
+ var navType = navigationType();
158
+ var entry = {
159
+ navigationStart: 0,
160
+ activationStart: 0,
161
+ startTime: 0,
162
+ type: navType == 2 ? "back_forward" : navType === 1 ? "reload" : "navigate",
163
+ };
164
+ if (__ENABLE_POLYFILLS) {
165
+ for (var key in timing) {
166
+ if (typeof timing[key] === "number" && key !== "navigationStart") {
167
+ entry[key] = Math.max(0, timing[key] - timing.navigationStart);
168
+ }
169
+ }
170
+ }
171
+ return entry;
172
+ }
173
+ /**
174
+ * Simple wrapper around performance.getEntriesByType to provide fallbacks for
175
+ * legacy browsers, and work around edge cases where undefined is returned instead
176
+ * of an empty PerformanceEntryList.
177
+ */
178
+ function getEntriesByType(type) {
179
+ if (typeof performance.getEntriesByType === "function") {
180
+ var entries = performance.getEntriesByType(type);
181
+ if (entries && entries.length) {
182
+ return entries;
183
+ }
184
+ }
185
+ return [];
186
+ }
187
+
188
+ function isVisible() {
189
+ if (document.visibilityState) {
190
+ return document.visibilityState === "visible";
191
+ }
192
+ // For browsers that don't support document.visibilityState, we assume the page is visible.
193
+ return true;
194
+ }
195
+ function onVisible(cb) {
196
+ if (isVisible()) {
197
+ cb();
198
+ }
199
+ else {
200
+ var onVisibleCallback_1 = function () {
201
+ if (isVisible()) {
202
+ cb();
203
+ removeEventListener("visibilitychange", onVisibleCallback_1);
204
+ }
205
+ };
206
+ addEventListener("visibilitychange", onVisibleCallback_1, true);
207
+ }
208
+ }
209
+ function wasPrerendered() {
210
+ return document.prerendering || getNavigationEntry().activationStart > 0;
211
+ }
212
+
114
213
  var Flags = {
115
214
  InitCalled: 1 << 0,
116
215
  NavTimingNotSupported: 1 << 1,
@@ -122,6 +221,7 @@
122
221
  PageLabelFromLabelProp: 1 << 7,
123
222
  PageLabelFromGlobalVariable: 1 << 8,
124
223
  PageLabelFromPagegroup: 1 << 9,
224
+ PageWasPrerendered: 1 << 10,
125
225
  };
126
226
  function addFlag(flags, flag) {
127
227
  return flags | flag;
@@ -177,10 +277,6 @@
177
277
  return null;
178
278
  }
179
279
 
180
- function now() {
181
- return Date.now ? Date.now() : +new Date();
182
- }
183
-
184
280
  var LogEvent = {
185
281
  // Internal events
186
282
  EvaluationStart: 1,
@@ -254,65 +350,6 @@
254
350
  return sessionValue;
255
351
  }
256
352
 
257
- var scriptStartTime = now();
258
-
259
- var _a;
260
- // If the various performance APIs aren't available, we export an empty object to
261
- // prevent having to make regular typeof checks.
262
- var performance = window.performance || {};
263
- var timing = performance.timing || {
264
- // If performance.timing isn't available, we attempt to polyfill the navigationStart value.
265
- // Our first attempt is from LUX.ns, which is the time that the snippet execution began. If this
266
- // is not available, we fall back to the time that the current script execution began.
267
- navigationStart: ((_a = window.LUX) === null || _a === void 0 ? void 0 : _a.ns) || scriptStartTime,
268
- };
269
- function msSinceNavigationStart() {
270
- if (performance.now) {
271
- return performance.now();
272
- }
273
- return now() - timing.navigationStart;
274
- }
275
- function navigationType() {
276
- if (performance.navigation && typeof performance.navigation.type !== "undefined") {
277
- return performance.navigation.type;
278
- }
279
- return "";
280
- }
281
- function getNavigationEntry() {
282
- var navEntries = getEntriesByType("navigation");
283
- if (navEntries.length) {
284
- return navEntries[0];
285
- }
286
- var navType = navigationType();
287
- var entry = {
288
- activationStart: 0,
289
- startTime: 0,
290
- type: navType == 2 ? "back_forward" : navType === 1 ? "reload" : "navigate",
291
- };
292
- if (__ENABLE_POLYFILLS) {
293
- for (var key in timing) {
294
- if (typeof timing[key] === "number" && key !== "navigationStart") {
295
- entry[key] = Math.max(0, timing[key] - timing.navigationStart);
296
- }
297
- }
298
- }
299
- return entry;
300
- }
301
- /**
302
- * Simple wrapper around performance.getEntriesByType to provide fallbacks for
303
- * legacy browsers, and work around edge cases where undefined is returned instead
304
- * of an empty PerformanceEntryList.
305
- */
306
- function getEntriesByType(type) {
307
- if (typeof performance.getEntriesByType === "function") {
308
- var entries = performance.getEntriesByType(type);
309
- if (entries && entries.length) {
310
- return entries;
311
- }
312
- }
313
- return [];
314
- }
315
-
316
353
  /**
317
354
  * This implementation is based on the web-vitals implementation, however it is stripped back to the
318
355
  * bare minimum required to measure just the INP value and does not store the actual event entries.
@@ -342,7 +379,7 @@
342
379
  slowestEntriesMap[interactionId] = { duration: duration, interactionId: interactionId, startTime: startTime };
343
380
  slowestEntries.push(slowestEntriesMap[interactionId]);
344
381
  }
345
- // Only store the longest <MAX_INTERACTIONS> interactions
382
+ // Only store the longest <MAX_INTERACTIONS> interactions
346
383
  slowestEntries.sort(function (a, b) { return b.duration - a.duration; });
347
384
  slowestEntries.splice(MAX_INTERACTIONS).forEach(function (entry) {
348
385
  delete slowestEntriesMap[entry.interactionId];
@@ -368,6 +405,18 @@
368
405
  return interactionCountEstimate;
369
406
  }
370
407
 
408
+ /**
409
+ * Get the number of milliseconds between navigationStart and the given PerformanceNavigationTiming key
410
+ */
411
+ function getNavTimingValue(key) {
412
+ var navEntry = getNavigationEntry();
413
+ var relativeTo = key === "activationStart" ? 0 : navEntry.activationStart;
414
+ if (typeof navEntry[key] === "number") {
415
+ return Math.max(0, navEntry[key] - relativeTo);
416
+ }
417
+ return undefined;
418
+ }
419
+
371
420
  /******************************************************************************
372
421
  Copyright (c) Microsoft Corporation.
373
422
 
@@ -416,6 +465,27 @@
416
465
  ALL_ENTRIES.splice(0);
417
466
  }
418
467
 
468
+ function getMatchesFromPatternMap(patternMap, hostname, pathname, firstOnly) {
469
+ var matches = [];
470
+ for (var key in patternMap) {
471
+ var patterns = patternMap[key];
472
+ if (Array.isArray(patterns)) {
473
+ for (var i in patterns) {
474
+ var pattern = patterns[i];
475
+ if (patternMatchesUrl(pattern, hostname, pathname)) {
476
+ if (firstOnly) {
477
+ return key;
478
+ }
479
+ matches.push(key);
480
+ }
481
+ }
482
+ }
483
+ }
484
+ if (firstOnly) {
485
+ return undefined;
486
+ }
487
+ return matches;
488
+ }
419
489
  function patternMatchesUrl(pattern, hostname, pathname) {
420
490
  var regex = createRegExpFromPattern(pattern);
421
491
  if (pattern.charAt(0) === "/") {
@@ -444,7 +514,7 @@
444
514
  // -------------------------------------------------------------------------
445
515
  /// End
446
516
  // -------------------------------------------------------------------------
447
- var SCRIPT_VERSION = "307";
517
+ var SCRIPT_VERSION = "308";
448
518
  var logger = new Logger();
449
519
  var globalConfig = fromObject(LUX);
450
520
  logger.logEvent(LogEvent.EvaluationStart, [SCRIPT_VERSION]);
@@ -542,6 +612,7 @@
542
612
  var gUid = refreshUniqueId(gSyncId); // cookie for this session ("Unique ID")
543
613
  var gCustomerDataTimeout; // setTimeout timer for sending a Customer Data beacon after onload
544
614
  var gMaxMeasureTimeout; // setTimeout timer for sending the beacon after a maximum measurement time
615
+ var navEntry = getNavigationEntry();
545
616
  if (_sample()) {
546
617
  logger.logEvent(LogEvent.SessionIsSampled, [globalConfig.samplerate]);
547
618
  }
@@ -564,7 +635,7 @@
564
635
  // Record the FIRST input delay.
565
636
  function recordDelay(delay) {
566
637
  if (!gFirstInputDelay) {
567
- gFirstInputDelay = Math.round(delay); // milliseconds
638
+ gFirstInputDelay = delay;
568
639
  // remove event listeners
569
640
  gaEventTypes.forEach(function (eventType) {
570
641
  removeEventListener(eventType, onInput, ghListenerOptions);
@@ -631,12 +702,12 @@
631
702
  });
632
703
  ////////////////////// FID END
633
704
  /**
634
- * Returns the time elapsed (in ms) since navigationStart. For SPAs, returns
635
- * the time elapsed since the last LUX.init call.
636
- *
637
- * When `absolute = true` the time is always relative to navigationStart, even
638
- * in SPAs.
639
- */
705
+ * Returns the time elapsed (in ms) since navigationStart. For SPAs, returns
706
+ * the time elapsed since the last LUX.init call.
707
+ *
708
+ * When `absolute = true` the time is always relative to navigationStart, even
709
+ * in SPAs.
710
+ */
640
711
  function _now(absolute) {
641
712
  var sinceNavigationStart = msSinceNavigationStart();
642
713
  var startMark = _getMark(START_MARK);
@@ -737,9 +808,9 @@
737
808
  if (startMark) {
738
809
  startTime = startMark.startTime;
739
810
  }
740
- else if (timing[startMarkName]) {
811
+ else if (typeof navEntry[startMarkName] === "number") {
741
812
  // the mark name can also be a property from Navigation Timing
742
- startTime = timing[startMarkName] - timing.navigationStart;
813
+ startTime = navEntry[startMarkName];
743
814
  }
744
815
  else {
745
816
  throwError(startMarkName);
@@ -750,15 +821,15 @@
750
821
  if (endMark) {
751
822
  endTime = endMark.startTime;
752
823
  }
753
- else if (timing[endMarkName]) {
824
+ else if (typeof navEntry[endMarkName] === "number") {
754
825
  // the mark name can also be a property from Navigation Timing
755
- endTime = timing[endMarkName] - timing.navigationStart;
826
+ endTime = navEntry[endMarkName];
756
827
  }
757
828
  else {
758
829
  throwError(endMarkName);
759
830
  }
760
831
  }
761
- var duration = Math.round(endTime) - Math.round(startTime);
832
+ var duration = endTime - startTime;
762
833
  var detail = null;
763
834
  if (options) {
764
835
  if (options.duration) {
@@ -826,7 +897,7 @@
826
897
  // Don't include the internal marks in the beacon
827
898
  return;
828
899
  }
829
- var startTime = Math.round(mark.startTime - tZero);
900
+ var startTime = floor(mark.startTime - tZero);
830
901
  if (startTime < 0) {
831
902
  // Exclude marks that were taken before the current SPA page view
832
903
  return;
@@ -845,8 +916,8 @@
845
916
  return;
846
917
  }
847
918
  var name = measure.name;
848
- var startTime = Math.round(measure.startTime - tZero);
849
- var duration = Math.round(measure.duration);
919
+ var startTime = floor(measure.startTime - tZero);
920
+ var duration = floor(measure.duration);
850
921
  if (typeof hUT[name] === "undefined" || startTime > hUT[name].startTime) {
851
922
  hUT[name] = { startTime: startTime, duration: duration };
852
923
  }
@@ -872,7 +943,7 @@
872
943
  getEntries("element").forEach(function (entry) {
873
944
  if (entry.identifier && entry.startTime) {
874
945
  logger.logEvent(LogEvent.PerformanceEntryProcessed, [entry]);
875
- aET.push(entry.identifier + "|" + Math.round(entry.startTime - tZero));
946
+ aET.push(entry.identifier + "|" + floor(entry.startTime - tZero));
876
947
  }
877
948
  });
878
949
  return aET.join(",");
@@ -904,7 +975,7 @@
904
975
  }
905
976
  }
906
977
  longTaskEntries.forEach(function (entry) {
907
- var dur = Math.round(entry.duration);
978
+ var dur = floor(entry.duration);
908
979
  if (entry.startTime < tZero_1) {
909
980
  // In a SPA it is possible that we were in the middle of a Long Task when
910
981
  // LUX.init() was called. If so, only include the duration after tZero.
@@ -924,7 +995,7 @@
924
995
  }
925
996
  hCPU[type] += dur;
926
997
  // Send back the raw startTime and duration, as well as the adjusted duration.
927
- hCPUDetails[type] += "," + Math.round(entry.startTime) + "|" + dur;
998
+ hCPUDetails[type] += "," + floor(entry.startTime) + "|" + dur;
928
999
  });
929
1000
  }
930
1001
  // TODO - Add more types if/when they become available.
@@ -942,7 +1013,7 @@
942
1013
  ",x|" +
943
1014
  hStats["max"] +
944
1015
  (0 === hStats["fci"] ? "" : ",i|" + hStats["fci"]); // only add FCI if it is non-zero
945
- sCPU += "s|" + hCPU[jsType] + sStats + hCPUDetails[jsType];
1016
+ sCPU += "s|" + hCPU[jsType] + sStats + hCPUDetails[jsType];
946
1017
  return sCPU;
947
1018
  }
948
1019
  // Return a hash of "stats" about the CPU details incl. count, max, and median.
@@ -995,7 +1066,7 @@
995
1066
  if (0 === aValues.length) {
996
1067
  return 0;
997
1068
  }
998
- var half = Math.floor(aValues.length / 2);
1069
+ var half = floor(aValues.length / 2);
999
1070
  aValues.sort(function (a, b) {
1000
1071
  return a - b;
1001
1072
  });
@@ -1020,10 +1091,10 @@
1020
1091
  var r = aResources[0];
1021
1092
  // DO NOT USE DURATION!!!!!
1022
1093
  // See https://www.stevesouders.com/blog/2014/11/25/serious-confusion-with-resource-timing/
1023
- var dns = Math.round(r.domainLookupEnd - r.domainLookupStart);
1024
- var tcp = Math.round(r.connectEnd - r.connectStart); // includes ssl negotiation
1025
- var fb = Math.round(r.responseStart - r.requestStart); // first byte
1026
- var content = Math.round(r.responseEnd - r.responseStart);
1094
+ var dns = floor(r.domainLookupEnd - r.domainLookupStart);
1095
+ var tcp = floor(r.connectEnd - r.connectStart);
1096
+ var fb = floor(r.responseStart - r.requestStart);
1097
+ var content = floor(r.responseEnd - r.responseStart);
1027
1098
  var networkDuration = dns + tcp + fb + content;
1028
1099
  var parseEval = scriptEndTime - scriptStartTime;
1029
1100
  var transferSize = r.encodedBodySize ? r.encodedBodySize : 0;
@@ -1149,8 +1220,8 @@
1149
1220
  !e.async &&
1150
1221
  !e.defer &&
1151
1222
  0 !== (e.compareDocumentPosition(lastViewportElem) & 4)) {
1152
- // If the script has a SRC and async is false and it occurs BEFORE the last viewport element,
1153
- // then increment the counter.
1223
+ // If the script has a SRC and async is false and it occurs BEFORE the last viewport element,
1224
+ // then increment the counter.
1154
1225
  num++;
1155
1226
  }
1156
1227
  }
@@ -1236,9 +1307,9 @@
1236
1307
  var endMark = _getMark(END_MARK);
1237
1308
  if (startMark && endMark) {
1238
1309
  // This is a SPA page view, so send the SPA marks & measures instead of Nav Timing.
1239
- var start = Math.round(startMark.startTime); // the start mark is "zero"
1310
+ var start = floor(startMark.startTime); // the start mark is "zero"
1240
1311
  ns += start; // "navigationStart" for a SPA is the real navigationStart plus the start mark
1241
- var end = Math.round(endMark.startTime) - start; // delta from start mark
1312
+ var end = floor(endMark.startTime) - start; // delta from start mark
1242
1313
  s =
1243
1314
  ns +
1244
1315
  "fs" +
@@ -1251,38 +1322,44 @@
1251
1322
  }
1252
1323
  else if (performance.timing) {
1253
1324
  // Return the real Nav Timing metrics because this is the "main" page view (not a SPA)
1254
- var t = timing;
1255
- var startRender = getStartRender(); // first paint
1256
- var fcp = getFcp(); // first contentful paint
1257
- var lcp = getLcp(); // largest contentful paint
1258
- s =
1259
- ns +
1260
- (t.redirectStart ? "rs" + (t.redirectStart - ns) : "") +
1261
- (t.redirectEnd ? "re" + (t.redirectEnd - ns) : "") +
1262
- (t.fetchStart ? "fs" + (t.fetchStart - ns) : "") +
1263
- (t.domainLookupStart ? "ds" + (t.domainLookupStart - ns) : "") +
1264
- (t.domainLookupEnd ? "de" + (t.domainLookupEnd - ns) : "") +
1265
- (t.connectStart ? "cs" + (t.connectStart - ns) : "") +
1266
- (t.secureConnectionStart ? "sc" + (t.secureConnectionStart - ns) : "") +
1267
- (t.connectEnd ? "ce" + (t.connectEnd - ns) : "") +
1268
- (t.requestStart ? "qs" + (t.requestStart - ns) : "") + // reQuest start
1269
- (t.responseStart ? "bs" + (t.responseStart - ns) : "") + // body start
1270
- (t.responseEnd ? "be" + (t.responseEnd - ns) : "") +
1271
- (t.domLoading ? "ol" + (t.domLoading - ns) : "") +
1272
- (t.domInteractive ? "oi" + (t.domInteractive - ns) : "") +
1273
- (t.domContentLoadedEventStart ? "os" + (t.domContentLoadedEventStart - ns) : "") +
1274
- (t.domContentLoadedEventEnd ? "oe" + (t.domContentLoadedEventEnd - ns) : "") +
1275
- (t.domComplete ? "oc" + (t.domComplete - ns) : "") +
1276
- (t.loadEventStart ? "ls" + (t.loadEventStart - ns) : "") +
1277
- (t.loadEventEnd ? "le" + (t.loadEventEnd - ns) : "") +
1278
- (typeof startRender !== "undefined" ? "sr" + startRender : "") +
1279
- (typeof fcp !== "undefined" ? "fc" + fcp : "") +
1280
- (typeof lcp !== "undefined" ? "lc" + lcp : "") +
1281
- "";
1325
+ var startRender = getStartRender();
1326
+ var fcp = getFcp();
1327
+ var lcp = getLcp();
1328
+ var prefixNTValue = function (key, prefix) {
1329
+ var value = getNavTimingValue(key);
1330
+ if (typeof value === "undefined") {
1331
+ return "";
1332
+ }
1333
+ return prefix + value;
1334
+ };
1335
+ s = [
1336
+ ns,
1337
+ prefixNTValue("activationStart", "as"),
1338
+ prefixNTValue("redirectStart", "rs"),
1339
+ prefixNTValue("redirectEnd", "re"),
1340
+ prefixNTValue("fetchStart", "fs"),
1341
+ prefixNTValue("domainLookupStart", "ds"),
1342
+ prefixNTValue("domainLookupEnd", "de"),
1343
+ prefixNTValue("connectStart", "cs"),
1344
+ prefixNTValue("secureConnectionStart", "sc"),
1345
+ prefixNTValue("connectEnd", "ce"),
1346
+ prefixNTValue("requestStart", "qs"),
1347
+ prefixNTValue("responseStart", "bs"),
1348
+ prefixNTValue("responseEnd", "be"),
1349
+ prefixNTValue("domInteractive", "oi"),
1350
+ prefixNTValue("domContentLoadedEventStart", "os"),
1351
+ prefixNTValue("domContentLoadedEventEnd", "oe"),
1352
+ prefixNTValue("domComplete", "oc"),
1353
+ prefixNTValue("loadEventStart", "ls"),
1354
+ prefixNTValue("loadEventEnd", "le"),
1355
+ typeof startRender !== "undefined" ? "sr" + startRender : "",
1356
+ typeof fcp !== "undefined" ? "fc" + fcp : "",
1357
+ typeof lcp !== "undefined" ? "lc" + lcp : "",
1358
+ ].join("");
1282
1359
  }
1283
1360
  else if (endMark) {
1284
1361
  // This is a "main" page view that does NOT support Navigation Timing - strange.
1285
- var end = Math.round(endMark.startTime);
1362
+ var end = floor(endMark.startTime);
1286
1363
  s =
1287
1364
  ns +
1288
1365
  "fs" +
@@ -1301,7 +1378,7 @@
1301
1378
  for (var i = 0; i < paintEntries.length; i++) {
1302
1379
  var entry = paintEntries[i];
1303
1380
  if (entry.name === "first-contentful-paint") {
1304
- return Math.round(entry.startTime);
1381
+ return floor(entry.startTime);
1305
1382
  }
1306
1383
  }
1307
1384
  return undefined;
@@ -1312,7 +1389,7 @@
1312
1389
  if (lcpEntries.length) {
1313
1390
  var lastEntry = lcpEntries[lcpEntries.length - 1];
1314
1391
  logger.logEvent(LogEvent.PerformanceEntryProcessed, [lastEntry]);
1315
- return Math.max(0, Math.round(lastEntry.startTime - getNavigationEntry().activationStart));
1392
+ return floor(lastEntry.startTime);
1316
1393
  }
1317
1394
  return undefined;
1318
1395
  }
@@ -1320,22 +1397,18 @@
1320
1397
  // Mostly works on just Chrome and IE.
1321
1398
  // Return undefined if not supported.
1322
1399
  function getStartRender() {
1323
- if (performance.timing) {
1400
+ if ("PerformancePaintTiming" in self) {
1324
1401
  var paintEntries = getEntriesByType("paint");
1325
1402
  if (paintEntries.length) {
1326
- // If Paint Timing API is supported, use it.
1327
- for (var i = 0; i < paintEntries.length; i++) {
1328
- var entry = paintEntries[i];
1329
- if (entry.name === "first-paint") {
1330
- return Math.round(entry.startTime);
1331
- }
1332
- }
1333
- }
1334
- else if (timing.msFirstPaint && __ENABLE_POLYFILLS) {
1335
- // If IE/Edge, use the prefixed `msFirstPaint` property (see http://msdn.microsoft.com/ff974719).
1336
- return Math.round(timing.msFirstPaint - timing.navigationStart);
1403
+ // If the Paint Timing API is supported, use the value of the first paint event
1404
+ var paintValues = paintEntries.map(function (entry) { return entry.startTime; });
1405
+ return floor(Math.min.apply(null, paintValues));
1337
1406
  }
1338
1407
  }
1408
+ if (performance.timing && timing.msFirstPaint && __ENABLE_POLYFILLS) {
1409
+ // If IE/Edge, use the prefixed `msFirstPaint` property (see http://msdn.microsoft.com/ff974719).
1410
+ return floor(timing.msFirstPaint - timing.navigationStart);
1411
+ }
1339
1412
  logger.logEvent(LogEvent.PaintTimingNotSupported);
1340
1413
  return undefined;
1341
1414
  }
@@ -1411,7 +1484,7 @@
1411
1484
  }
1412
1485
  // Return the main HTML document transfer size (in bytes).
1413
1486
  function docSize() {
1414
- return getNavigationEntry().encodedBodySize || 0;
1487
+ return navEntry.encodedBodySize || 0;
1415
1488
  }
1416
1489
  // Return the connection type based on Network Information API.
1417
1490
  // Note this API is in flux.
@@ -1576,7 +1649,7 @@
1576
1649
  if (!gbIxSent) {
1577
1650
  sIx = ixValues();
1578
1651
  if (sIx === "") {
1579
- // If there are no interaction metrics, we
1652
+ // If there are no interaction metrics, we
1580
1653
  INP = undefined;
1581
1654
  }
1582
1655
  }
@@ -1584,9 +1657,17 @@
1584
1657
  var sCPU = cpuTimes();
1585
1658
  var CLS = getCLS$1();
1586
1659
  var sLuxjs = selfLoading();
1587
- if (document.visibilityState && "visible" !== document.visibilityState) {
1660
+ if (!isVisible()) {
1588
1661
  gFlags = addFlag(gFlags, Flags.VisibilityStateNotVisible);
1589
1662
  }
1663
+ if (wasPrerendered()) {
1664
+ gFlags = addFlag(gFlags, Flags.PageWasPrerendered);
1665
+ }
1666
+ if (LUX.conversions) {
1667
+ getMatchesFromPatternMap(LUX.conversions, location.hostname, location.pathname).forEach(function (conversion) {
1668
+ LUX.addData(conversion, BOOLEAN_TRUE);
1669
+ });
1670
+ }
1590
1671
  // We want ALL beacons to have ALL the data used for query filters (geo, pagelabel, browser, & customerdata).
1591
1672
  // So we create a base URL that has all the necessary information:
1592
1673
  var baseUrl = _getBeaconUrl(getAllCustomData());
@@ -1676,7 +1757,7 @@
1676
1757
  var sIx = ixValues(); // Interaction Metrics
1677
1758
  var INP = getINP();
1678
1759
  if (sIx) {
1679
- var beaconUrl = _getBeaconUrl(getUpdatedCustomData()) +
1760
+ var beaconUrl = _getBeaconUrl(getUpdatedCustomData()) +
1680
1761
  "&IX=" +
1681
1762
  sIx +
1682
1763
  (typeof gFirstInputDelay !== "undefined" ? "&FID=" + gFirstInputDelay : "") +
@@ -1718,13 +1799,13 @@
1718
1799
  // Note for scroll input we don't remove the handlers or send the IX beacon because we want to
1719
1800
  // capture click and key events as well, since these are typically more important than scrolls.
1720
1801
  if (typeof ghIx["s"] === "undefined") {
1721
- ghIx["s"] = Math.round(_now());
1802
+ ghIx["s"] = _now();
1722
1803
  }
1723
1804
  }
1724
1805
  function _keyHandler(e) {
1725
1806
  _removeIxHandlers();
1726
1807
  if (typeof ghIx["k"] === "undefined") {
1727
- ghIx["k"] = Math.round(_now());
1808
+ ghIx["k"] = _now();
1728
1809
  if (e && e.target instanceof Element) {
1729
1810
  var trackId = interactionAttributionForElement(e.target);
1730
1811
  if (trackId) {
@@ -1737,7 +1818,7 @@
1737
1818
  function _clickHandler(e) {
1738
1819
  _removeIxHandlers();
1739
1820
  if (typeof ghIx["c"] === "undefined") {
1740
- ghIx["c"] = Math.round(_now());
1821
+ ghIx["c"] = _now();
1741
1822
  var target = void 0;
1742
1823
  try {
1743
1824
  // Seeing "Permission denied" errors, so do a simple try-catch.
@@ -1865,30 +1946,11 @@
1865
1946
  gFlags = addFlag(gFlags, Flags.PageLabelFromLabelProp);
1866
1947
  return LUX.label;
1867
1948
  }
1868
- else if (typeof LUX.pagegroups !== "undefined") {
1869
- var pagegroups = LUX.pagegroups;
1870
- var label_1 = "";
1871
- var _loop_1 = function (pagegroup) {
1872
- var rules = pagegroups[pagegroup];
1873
- if (Array.isArray(rules)) {
1874
- rules.every(function (rule) {
1875
- if (patternMatchesUrl(rule, document.location.hostname, document.location.pathname)) {
1876
- label_1 = pagegroup;
1877
- return false; // stop when first match is found
1878
- }
1879
- return true;
1880
- });
1881
- }
1882
- // exits loop when first match is found
1883
- if (label_1) {
1884
- gFlags = addFlag(gFlags, Flags.PageLabelFromPagegroup);
1885
- return { value: label_1 };
1886
- }
1887
- };
1888
- for (var pagegroup in pagegroups) {
1889
- var state_1 = _loop_1(pagegroup);
1890
- if (typeof state_1 === "object")
1891
- return state_1.value;
1949
+ if (typeof LUX.pagegroups !== "undefined") {
1950
+ var label = getMatchesFromPatternMap(LUX.pagegroups, location.hostname, location.pathname, true);
1951
+ if (label) {
1952
+ gFlags = addFlag(gFlags, Flags.PageLabelFromPagegroup);
1953
+ return label;
1892
1954
  }
1893
1955
  }
1894
1956
  if (typeof LUX.jspagelabel !== "undefined") {
@@ -1969,9 +2031,16 @@
1969
2031
  setTimeout(sendBeaconAfterMinimumMeasureTime_1, timeRemaining);
1970
2032
  }
1971
2033
  };
1972
- sendBeaconAfterMinimumMeasureTime_1();
2034
+ if (globalConfig.autoWhenHidden) {
2035
+ // The autoWhenHidden config forces the beacon to be sent even when the page is not visible.
2036
+ sendBeaconAfterMinimumMeasureTime_1();
2037
+ }
2038
+ else {
2039
+ // Otherwise we only send the beacon when the page is visible.
2040
+ onVisible(sendBeaconAfterMinimumMeasureTime_1);
2041
+ }
1973
2042
  }
1974
- // Add the unload handlers for auto mode, or when LUX.measureUntil is "pagehidden"
2043
+ // Add the unload handlers when sendBeaconOnPageHidden is enabled
1975
2044
  if (globalConfig.sendBeaconOnPageHidden) {
1976
2045
  _addUnloadHandlers();
1977
2046
  }
@@ -1980,9 +2049,9 @@
1980
2049
  // Set the maximum measurement timer
1981
2050
  createMaxMeasureTimeout();
1982
2051
  /**
1983
- * LUX functions and properties must be attached to the existing global object to ensure that
1984
- * changes made to the global object are reflected in the "internal" LUX object, and vice versa.
1985
- */
2052
+ * LUX functions and properties must be attached to the existing global object to ensure that
2053
+ * changes made to the global object are reflected in the "internal" LUX object, and vice versa.
2054
+ */
1986
2055
  var globalLux = globalConfig;
1987
2056
  // Functions
1988
2057
  globalLux.mark = _mark;
@@ -2007,8 +2076,8 @@
2007
2076
  // Public properties
2008
2077
  globalLux.version = SCRIPT_VERSION;
2009
2078
  /**
2010
- * Run a command from the command queue
2011
- */
2079
+ * Run a command from the command queue
2080
+ */
2012
2081
  function _runCommand(_a) {
2013
2082
  var fn = _a[0], args = _a.slice(1);
2014
2083
  if (typeof globalLux[fn] === "function") {