govuk_publishing_components 35.3.5 → 35.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) 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-link-tracker.js +4 -3
  4. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-specialist-link-tracker.js +5 -1
  5. data/app/assets/javascripts/govuk_publishing_components/components/step-by-step-nav.js +1 -1
  6. data/app/assets/javascripts/govuk_publishing_components/vendor/lux/lux-reporter.js +245 -176
  7. data/app/assets/stylesheets/component_guide/application.scss +16 -0
  8. data/app/assets/stylesheets/govuk_publishing_components/components/_layout-super-navigation-header.scss +0 -5
  9. data/app/assets/stylesheets/govuk_publishing_components/components/_search.scss +0 -12
  10. data/app/assets/stylesheets/govuk_publishing_components/components/govspeak/_attachment.scss +0 -11
  11. data/app/models/govuk_publishing_components/audit_applications.rb +14 -0
  12. data/app/models/govuk_publishing_components/audit_comparer.rb +14 -0
  13. data/app/models/govuk_publishing_components/audit_components.rb +34 -32
  14. data/app/views/govuk_publishing_components/audit/_applications.html.erb +40 -32
  15. data/app/views/govuk_publishing_components/audit/_component_contents.html.erb +56 -12
  16. data/app/views/govuk_publishing_components/audit/_components.html.erb +9 -7
  17. data/app/views/govuk_publishing_components/audit/show.html.erb +5 -1
  18. data/app/views/govuk_publishing_components/components/_hint.html.erb +5 -1
  19. data/app/views/govuk_publishing_components/components/_label.html.erb +6 -6
  20. data/app/views/govuk_publishing_components/components/docs/hint.yml +1 -1
  21. data/lib/generators/govuk_publishing_components/component_generator.rb +2 -2
  22. data/lib/govuk_publishing_components/presenters/related_navigation_helper.rb +8 -8
  23. data/lib/govuk_publishing_components/version.rb +1 -1
  24. data/node_modules/axe-core/README.md +1 -3
  25. data/node_modules/axe-core/axe.js +4385 -1157
  26. data/node_modules/axe-core/axe.min.js +2 -2
  27. data/node_modules/axe-core/locales/_template.json +12 -0
  28. data/node_modules/axe-core/package.json +2 -1
  29. data/node_modules/axe-core/sri-history.json +4 -0
  30. metadata +3 -2
@@ -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") {