govuk_publishing_components 35.6.0 → 35.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/javascripts/component_guide/audit-filter.js +45 -0
- data/app/assets/javascripts/govuk_publishing_components/vendor/lux/lux-reporter.js +206 -114
- data/app/assets/stylesheets/component_guide/application.scss +0 -25
- data/app/assets/stylesheets/govuk_publishing_components/components/_document-list.scss +5 -9
- data/app/assets/stylesheets/govuk_publishing_components/components/_layout-for-public.scss +4 -0
- data/app/views/govuk_publishing_components/audit/_component_contents.html.erb +37 -49
- data/app/views/govuk_publishing_components/audit/show.html.erb +2 -1
- data/app/views/govuk_publishing_components/components/_attachment.html.erb +38 -18
- data/app/views/govuk_publishing_components/components/_character_count.html.erb +4 -2
- data/app/views/govuk_publishing_components/components/_document_list.html.erb +8 -7
- data/app/views/govuk_publishing_components/components/_feedback.html.erb +1 -0
- data/app/views/govuk_publishing_components/components/_layout_for_public.html.erb +9 -2
- data/app/views/govuk_publishing_components/components/_layout_super_navigation_header.html.erb +1 -0
- data/app/views/govuk_publishing_components/components/_metadata.html.erb +20 -14
- data/app/views/govuk_publishing_components/components/_radio.html.erb +1 -0
- data/app/views/govuk_publishing_components/components/_search.html.erb +1 -0
- data/app/views/govuk_publishing_components/components/_select.html.erb +1 -0
- data/app/views/govuk_publishing_components/components/_step_by_step_nav_related.html.erb +2 -2
- data/app/views/govuk_publishing_components/components/attachment/_thumbnail_document.html.erb +1 -1
- data/app/views/govuk_publishing_components/components/attachment/_thumbnail_generic.html.erb +1 -1
- data/app/views/govuk_publishing_components/components/attachment/_thumbnail_html.html.erb +3 -0
- data/app/views/govuk_publishing_components/components/attachment/_thumbnail_spreadsheet.html.erb +1 -1
- data/app/views/govuk_publishing_components/components/docs/attachment.yml +21 -0
- data/app/views/govuk_publishing_components/components/docs/document_list.yml +17 -0
- data/app/views/govuk_publishing_components/components/docs/layout_for_public.yml +6 -0
- data/app/views/layouts/govuk_publishing_components/application.html.erb +23 -20
- data/config/locales/ar.yml +1 -0
- data/config/locales/az.yml +1 -0
- data/config/locales/be.yml +1 -0
- data/config/locales/bg.yml +1 -0
- data/config/locales/bn.yml +1 -0
- data/config/locales/cs.yml +1 -0
- data/config/locales/cy.yml +1 -0
- data/config/locales/da.yml +1 -0
- data/config/locales/de.yml +1 -0
- data/config/locales/dr.yml +1 -0
- data/config/locales/el.yml +1 -0
- data/config/locales/en.yml +1 -0
- data/config/locales/es-419.yml +1 -0
- data/config/locales/es.yml +1 -0
- data/config/locales/et.yml +1 -0
- data/config/locales/fa.yml +1 -0
- data/config/locales/fi.yml +1 -0
- data/config/locales/fr.yml +1 -0
- data/config/locales/gd.yml +1 -0
- data/config/locales/gu.yml +1 -0
- data/config/locales/he.yml +1 -0
- data/config/locales/hi.yml +1 -0
- data/config/locales/hr.yml +1 -0
- data/config/locales/hu.yml +1 -0
- data/config/locales/hy.yml +1 -0
- data/config/locales/id.yml +1 -0
- data/config/locales/is.yml +1 -0
- data/config/locales/it.yml +1 -0
- data/config/locales/ja.yml +1 -0
- data/config/locales/ka.yml +1 -0
- data/config/locales/kk.yml +1 -0
- data/config/locales/ko.yml +1 -0
- data/config/locales/lt.yml +1 -0
- data/config/locales/lv.yml +1 -0
- data/config/locales/ms.yml +1 -0
- data/config/locales/mt.yml +1 -0
- data/config/locales/nl.yml +1 -0
- data/config/locales/no.yml +1 -0
- data/config/locales/pa-pk.yml +1 -0
- data/config/locales/pa.yml +1 -0
- data/config/locales/pl.yml +1 -0
- data/config/locales/ps.yml +1 -0
- data/config/locales/pt.yml +1 -0
- data/config/locales/ro.yml +1 -0
- data/config/locales/ru.yml +1 -0
- data/config/locales/si.yml +1 -0
- data/config/locales/sk.yml +1 -0
- data/config/locales/sl.yml +1 -0
- data/config/locales/so.yml +1 -0
- data/config/locales/sq.yml +1 -0
- data/config/locales/sr.yml +1 -0
- data/config/locales/sv.yml +1 -0
- data/config/locales/sw.yml +1 -0
- data/config/locales/ta.yml +1 -0
- data/config/locales/th.yml +1 -0
- data/config/locales/tk.yml +1 -0
- data/config/locales/tr.yml +1 -0
- data/config/locales/uk.yml +1 -0
- data/config/locales/ur.yml +1 -0
- data/config/locales/uz.yml +1 -0
- data/config/locales/vi.yml +1 -0
- data/config/locales/zh-hk.yml +1 -0
- data/config/locales/zh-tw.yml +1 -0
- data/config/locales/zh.yml +1 -0
- data/lib/govuk_publishing_components/app_helpers/asset_helper.rb +5 -1
- data/lib/govuk_publishing_components/presenters/attachment_helper.rb +15 -3
- data/lib/govuk_publishing_components/presenters/public_layout_helper.rb +5 -0
- data/lib/govuk_publishing_components/version.rb +1 -1
- data/node_modules/axe-core/README.md +4 -0
- data/node_modules/axe-core/axe.js +25 -19
- data/node_modules/axe-core/axe.min.js +2 -2
- data/node_modules/axe-core/package.json +1 -1
- data/node_modules/axe-core/sri-history.json +4 -0
- metadata +4 -3
@@ -42,7 +42,6 @@
|
|
42
42
|
var autoMode = getProperty(obj, "auto", true);
|
43
43
|
return {
|
44
44
|
auto: autoMode,
|
45
|
-
autoWhenHidden: getProperty(obj, "autoWhenHidden", false),
|
46
45
|
beaconUrl: getProperty(obj, "beaconUrl", "https://lux.speedcurve.com/lux/"),
|
47
46
|
conversions: getProperty(obj, "conversions", undefined),
|
48
47
|
customerid: getProperty(obj, "customerid", undefined),
|
@@ -54,9 +53,12 @@
|
|
54
53
|
maxErrors: getProperty(obj, "maxErrors", 5),
|
55
54
|
maxMeasureTime: getProperty(obj, "maxMeasureTime", 60000),
|
56
55
|
minMeasureTime: getProperty(obj, "minMeasureTime", 0),
|
56
|
+
newBeaconOnPageShow: getProperty(obj, "newBeaconOnPageShow", false),
|
57
57
|
samplerate: getProperty(obj, "samplerate", 100),
|
58
58
|
sendBeaconOnPageHidden: getProperty(obj, "sendBeaconOnPageHidden", autoMode),
|
59
|
+
serverTiming: getProperty(obj, "serverTiming", undefined),
|
59
60
|
trackErrors: getProperty(obj, "trackErrors", true),
|
61
|
+
trackHiddenPages: getProperty(obj, "trackHiddenPages", false),
|
60
62
|
pagegroups: getProperty(obj, "pagegroups", undefined),
|
61
63
|
};
|
62
64
|
}
|
@@ -102,9 +104,9 @@
|
|
102
104
|
function valuesToString(values) {
|
103
105
|
var strings = [];
|
104
106
|
for (var key in values) {
|
105
|
-
|
107
|
+
// Convert all values to strings
|
106
108
|
var value = "" + values[key];
|
107
|
-
|
109
|
+
// Strip out reserved characters (, and | are used as delimiters)
|
108
110
|
key = key.replace(/,/g, "").replace(/\|/g, "");
|
109
111
|
value = value.replace(/,/g, "").replace(/\|/g, "");
|
110
112
|
strings.push(key + "|" + value);
|
@@ -115,6 +117,13 @@
|
|
115
117
|
function floor(x) {
|
116
118
|
return Math.floor(x);
|
117
119
|
}
|
120
|
+
var max = Math.max;
|
121
|
+
/**
|
122
|
+
* Clamp a number so that it is never less than 0
|
123
|
+
*/
|
124
|
+
function clamp(x) {
|
125
|
+
return max(0, x);
|
126
|
+
}
|
118
127
|
|
119
128
|
function now() {
|
120
129
|
return Date.now ? Date.now() : +new Date();
|
@@ -147,10 +156,13 @@
|
|
147
156
|
function getNavigationEntry() {
|
148
157
|
var navEntries = getEntriesByType("navigation");
|
149
158
|
if (navEntries.length) {
|
150
|
-
var
|
151
|
-
entry_1
|
152
|
-
|
153
|
-
|
159
|
+
var nativeEntry = navEntries[0];
|
160
|
+
var entry_1 = {
|
161
|
+
navigationStart: 0,
|
162
|
+
activationStart: 0,
|
163
|
+
};
|
164
|
+
for (var key in nativeEntry) {
|
165
|
+
entry_1[key] = nativeEntry[key];
|
154
166
|
}
|
155
167
|
return entry_1;
|
156
168
|
}
|
@@ -164,7 +176,7 @@
|
|
164
176
|
if (__ENABLE_POLYFILLS) {
|
165
177
|
for (var key in timing) {
|
166
178
|
if (typeof timing[key] === "number" && key !== "navigationStart") {
|
167
|
-
entry[key] =
|
179
|
+
entry[key] = floor(timing[key] - timing.navigationStart);
|
168
180
|
}
|
169
181
|
}
|
170
182
|
}
|
@@ -189,26 +201,39 @@
|
|
189
201
|
if (document.visibilityState) {
|
190
202
|
return document.visibilityState === "visible";
|
191
203
|
}
|
192
|
-
|
204
|
+
// For browsers that don't support document.visibilityState, we assume the page is visible.
|
193
205
|
return true;
|
194
206
|
}
|
195
207
|
function onVisible(cb) {
|
196
|
-
|
197
|
-
|
208
|
+
afterPrerender(function () {
|
209
|
+
if (isVisible()) {
|
210
|
+
cb();
|
211
|
+
}
|
212
|
+
else {
|
213
|
+
var onVisibleCallback_1 = function () {
|
214
|
+
if (isVisible()) {
|
215
|
+
cb();
|
216
|
+
removeEventListener("visibilitychange", onVisibleCallback_1);
|
217
|
+
}
|
218
|
+
};
|
219
|
+
addEventListener("visibilitychange", onVisibleCallback_1, true);
|
220
|
+
}
|
221
|
+
});
|
222
|
+
}
|
223
|
+
function afterPrerender(cb) {
|
224
|
+
if (document.prerendering) {
|
225
|
+
document.addEventListener("prerenderingchange", cb, true);
|
198
226
|
}
|
199
227
|
else {
|
200
|
-
|
201
|
-
if (isVisible()) {
|
202
|
-
cb();
|
203
|
-
removeEventListener("visibilitychange", onVisibleCallback_1);
|
204
|
-
}
|
205
|
-
};
|
206
|
-
addEventListener("visibilitychange", onVisibleCallback_1, true);
|
228
|
+
cb();
|
207
229
|
}
|
208
230
|
}
|
209
231
|
function wasPrerendered() {
|
210
232
|
return document.prerendering || getNavigationEntry().activationStart > 0;
|
211
233
|
}
|
234
|
+
function wasRedirected() {
|
235
|
+
return getNavigationEntry().redirectCount > 0 || timing.redirectEnd > 0;
|
236
|
+
}
|
212
237
|
|
213
238
|
var Flags = {
|
214
239
|
InitCalled: 1 << 0,
|
@@ -222,6 +247,7 @@
|
|
222
247
|
PageLabelFromGlobalVariable: 1 << 8,
|
223
248
|
PageLabelFromPagegroup: 1 << 9,
|
224
249
|
PageWasPrerendered: 1 << 10,
|
250
|
+
PageWasBfCacheRestored: 1 << 11,
|
225
251
|
};
|
226
252
|
function addFlag(flags, flag) {
|
227
253
|
return flags | flag;
|
@@ -235,8 +261,8 @@
|
|
235
261
|
}
|
236
262
|
|
237
263
|
/**
|
238
|
-
|
239
|
-
|
264
|
+
* Get the interaction attribution name for an element
|
265
|
+
*/
|
240
266
|
function interactionAttributionForElement(el) {
|
241
267
|
// Our first preference is to use the data-sctrack attribute from anywhere in the tree
|
242
268
|
var trackId = getClosestScTrackAttribute(el);
|
@@ -291,6 +317,7 @@
|
|
291
317
|
UnloadHandlerTriggered: 10,
|
292
318
|
OnloadHandlerTriggered: 11,
|
293
319
|
MarkLoadTimeCalled: 12,
|
320
|
+
SendCancelledPageHidden: 13,
|
294
321
|
// Data collection events
|
295
322
|
SessionIsSampled: 21,
|
296
323
|
SessionIsNotSampled: 22,
|
@@ -315,39 +342,45 @@
|
|
315
342
|
PaintTimingNotSupported: 72,
|
316
343
|
};
|
317
344
|
var Logger = /** @class */ (function () {
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
345
|
+
function Logger() {
|
346
|
+
this.events = [];
|
347
|
+
}
|
348
|
+
Logger.prototype.logEvent = function (event, args) {
|
349
|
+
if (args === void 0) { args = []; }
|
350
|
+
this.events.push([now(), event, args]);
|
351
|
+
};
|
352
|
+
Logger.prototype.getEvents = function () {
|
353
|
+
return this.events;
|
354
|
+
};
|
355
|
+
return Logger;
|
329
356
|
}());
|
330
357
|
var sessionValue = 0;
|
331
358
|
var sessionEntries = [];
|
359
|
+
var maximumSessionValue = 0;
|
332
360
|
function addEntry$2(entry) {
|
333
361
|
if (!entry.hadRecentInput) {
|
334
362
|
var firstEntry = sessionEntries[0];
|
335
363
|
var latestEntry = sessionEntries[sessionEntries.length - 1];
|
336
364
|
if (sessionEntries.length &&
|
337
365
|
(entry.startTime - latestEntry.startTime >= 1000 ||
|
338
|
-
|
339
|
-
|
366
|
+
entry.startTime - firstEntry.startTime >= 5000)) {
|
367
|
+
sessionValue = entry.value;
|
368
|
+
sessionEntries = [entry];
|
340
369
|
}
|
341
|
-
|
342
|
-
|
370
|
+
else {
|
371
|
+
sessionValue += entry.value;
|
372
|
+
sessionEntries.push(entry);
|
373
|
+
}
|
374
|
+
maximumSessionValue = max(maximumSessionValue, sessionValue);
|
343
375
|
}
|
344
376
|
}
|
345
377
|
function reset$1() {
|
346
378
|
sessionValue = 0;
|
347
379
|
sessionEntries = [];
|
380
|
+
maximumSessionValue = 0;
|
348
381
|
}
|
349
382
|
function getCLS() {
|
350
|
-
return
|
383
|
+
return maximumSessionValue;
|
351
384
|
}
|
352
385
|
|
353
386
|
/**
|
@@ -372,7 +405,7 @@
|
|
372
405
|
var duration = entry.duration, startTime = entry.startTime, interactionId = entry.interactionId;
|
373
406
|
var existingEntry = slowestEntriesMap[interactionId];
|
374
407
|
if (existingEntry) {
|
375
|
-
existingEntry.duration =
|
408
|
+
existingEntry.duration = max(duration, existingEntry.duration);
|
376
409
|
}
|
377
410
|
else {
|
378
411
|
interactionCountEstimate++;
|
@@ -405,44 +438,6 @@
|
|
405
438
|
return interactionCountEstimate;
|
406
439
|
}
|
407
440
|
|
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
|
-
|
420
|
-
/******************************************************************************
|
421
|
-
Copyright (c) Microsoft Corporation.
|
422
|
-
|
423
|
-
Permission to use, copy, modify, and/or distribute this software for any
|
424
|
-
purpose with or without fee is hereby granted.
|
425
|
-
|
426
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
427
|
-
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
428
|
-
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
429
|
-
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
430
|
-
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
431
|
-
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
432
|
-
PERFORMANCE OF THIS SOFTWARE.
|
433
|
-
***************************************************************************** */
|
434
|
-
|
435
|
-
var __assign = function() {
|
436
|
-
__assign = Object.assign || function __assign(t) {
|
437
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
438
|
-
s = arguments[i];
|
439
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
|
440
|
-
}
|
441
|
-
return t;
|
442
|
-
};
|
443
|
-
return __assign.apply(this, arguments);
|
444
|
-
};
|
445
|
-
|
446
441
|
var ALL_ENTRIES = [];
|
447
442
|
function observe(type, callback, options) {
|
448
443
|
if (typeof PerformanceObserver === "function" &&
|
@@ -450,10 +445,10 @@
|
|
450
445
|
var po = new PerformanceObserver(function (list) {
|
451
446
|
list.getEntries().forEach(function (entry) { return callback(entry); });
|
452
447
|
});
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
448
|
+
po.observe(Object.assign({ type: type, buffered: true }, { options: options }));
|
449
|
+
return po;
|
450
|
+
}
|
451
|
+
return undefined;
|
457
452
|
}
|
458
453
|
function getEntries(type) {
|
459
454
|
return ALL_ENTRIES.filter(function (entry) { return entry.entryType === type; });
|
@@ -465,6 +460,39 @@
|
|
465
460
|
ALL_ENTRIES.splice(0);
|
466
461
|
}
|
467
462
|
|
463
|
+
/**
|
464
|
+
* A server timing metric that has its value set to the duration field
|
465
|
+
*/
|
466
|
+
var TYPE_DURATION = "r";
|
467
|
+
/**
|
468
|
+
* When a description metric has no value, we consider it to be a boolean and set it to this value.
|
469
|
+
*/
|
470
|
+
var BOOLEAN_TRUE_VALUE = "true";
|
471
|
+
function getKeyValuePairs(config, serverTiming) {
|
472
|
+
var pairs = {};
|
473
|
+
serverTiming.forEach(function (stEntry) {
|
474
|
+
var name = stEntry.name;
|
475
|
+
var description = stEntry.description;
|
476
|
+
if (name in config) {
|
477
|
+
var spec = config[name];
|
478
|
+
var multiplier = spec[1];
|
479
|
+
if (spec[0] === TYPE_DURATION) {
|
480
|
+
pairs[name] = stEntry.duration * (multiplier || 1);
|
481
|
+
}
|
482
|
+
else if (description && multiplier) {
|
483
|
+
var numericValue = parseFloat(description);
|
484
|
+
if (!isNaN(numericValue)) {
|
485
|
+
pairs[name] = numericValue * multiplier;
|
486
|
+
}
|
487
|
+
}
|
488
|
+
else {
|
489
|
+
pairs[name] = description || BOOLEAN_TRUE_VALUE;
|
490
|
+
}
|
491
|
+
}
|
492
|
+
});
|
493
|
+
return pairs;
|
494
|
+
}
|
495
|
+
|
468
496
|
function getMatchesFromPatternMap(patternMap, hostname, pathname, firstOnly) {
|
469
497
|
var matches = [];
|
470
498
|
for (var key in patternMap) {
|
@@ -496,7 +524,7 @@
|
|
496
524
|
return regex.test(hostname + pathname);
|
497
525
|
}
|
498
526
|
function createRegExpFromPattern(pattern) {
|
499
|
-
return new RegExp("^" + escapeStringForRegExp(pattern).
|
527
|
+
return new RegExp("^" + escapeStringForRegExp(pattern).replace(/\*/g, ".*") + "$", "i");
|
500
528
|
}
|
501
529
|
function escapeStringForRegExp(str) {
|
502
530
|
// Note: we don't escape * because it's our own special symbol!
|
@@ -514,7 +542,7 @@
|
|
514
542
|
// -------------------------------------------------------------------------
|
515
543
|
/// End
|
516
544
|
// -------------------------------------------------------------------------
|
517
|
-
var SCRIPT_VERSION = "
|
545
|
+
var SCRIPT_VERSION = "309";
|
518
546
|
var logger = new Logger();
|
519
547
|
var globalConfig = fromObject(LUX);
|
520
548
|
logger.logEvent(LogEvent.EvaluationStart, [SCRIPT_VERSION]);
|
@@ -585,7 +613,7 @@
|
|
585
613
|
observe("first-input", function (entry) {
|
586
614
|
var fid = entry.processingStart - entry.startTime;
|
587
615
|
if (!gFirstInputDelay || gFirstInputDelay < fid) {
|
588
|
-
gFirstInputDelay = fid;
|
616
|
+
gFirstInputDelay = floor(fid);
|
589
617
|
}
|
590
618
|
// Allow first-input events to be considered for INP
|
591
619
|
addEntry$1(entry);
|
@@ -612,7 +640,13 @@
|
|
612
640
|
var gUid = refreshUniqueId(gSyncId); // cookie for this session ("Unique ID")
|
613
641
|
var gCustomerDataTimeout; // setTimeout timer for sending a Customer Data beacon after onload
|
614
642
|
var gMaxMeasureTimeout; // setTimeout timer for sending the beacon after a maximum measurement time
|
615
|
-
var
|
643
|
+
var pageRestoreTime; // ms since navigationStart representing when the page was restored from the bfcache
|
644
|
+
/**
|
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; };
|
616
650
|
if (_sample()) {
|
617
651
|
logger.logEvent(LogEvent.SessionIsSampled, [globalConfig.samplerate]);
|
618
652
|
}
|
@@ -713,7 +747,7 @@
|
|
713
747
|
var startMark = _getMark(START_MARK);
|
714
748
|
// For SPA page views, we use our internal mark as a reference point
|
715
749
|
if (startMark && !absolute) {
|
716
|
-
return sinceNavigationStart - startMark.startTime;
|
750
|
+
return floor(sinceNavigationStart - startMark.startTime);
|
717
751
|
}
|
718
752
|
// For "regular" page views, we can use performance.now() if it's available...
|
719
753
|
return sinceNavigationStart;
|
@@ -796,6 +830,7 @@
|
|
796
830
|
}
|
797
831
|
// ...Otherwise provide a polyfill
|
798
832
|
if (__ENABLE_POLYFILLS) {
|
833
|
+
var navEntry = getNavigationEntry();
|
799
834
|
var startTime = typeof startMarkName === "number" ? startMarkName : 0;
|
800
835
|
var endTime = typeof endMarkName === "number" ? endMarkName : _now();
|
801
836
|
var throwError = function (missingMark) {
|
@@ -906,7 +941,7 @@
|
|
906
941
|
hUT[name] = { startTime: startTime };
|
907
942
|
}
|
908
943
|
else {
|
909
|
-
hUT[name].startTime =
|
944
|
+
hUT[name].startTime = max(startTime, hUT[name].startTime);
|
910
945
|
}
|
911
946
|
});
|
912
947
|
// measures
|
@@ -939,7 +974,7 @@
|
|
939
974
|
function elementTimingValues() {
|
940
975
|
var aET = [];
|
941
976
|
var startMark = _getMark(START_MARK);
|
942
|
-
var tZero = startMark ? startMark.startTime :
|
977
|
+
var tZero = startMark ? startMark.startTime : getZeroTime();
|
943
978
|
getEntries("element").forEach(function (entry) {
|
944
979
|
if (entry.identifier && entry.startTime) {
|
945
980
|
logger.logEvent(LogEvent.PerformanceEntryProcessed, [entry]);
|
@@ -1164,11 +1199,11 @@
|
|
1164
1199
|
var nThis = ("" + gUid).substr(-2); // number for THIS page - from 00 to 99
|
1165
1200
|
return parseInt(nThis) < globalConfig.samplerate;
|
1166
1201
|
}
|
1167
|
-
|
1168
|
-
|
1169
|
-
|
1170
|
-
|
1171
|
-
function _init() {
|
1202
|
+
/**
|
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
|
+
*/
|
1206
|
+
function _init(startTime) {
|
1172
1207
|
// Some customers (incorrectly) call LUX.init on the very first page load of a SPA. This would
|
1173
1208
|
// cause some first-page-only data (like paint metrics) to be lost. To prevent this, we silently
|
1174
1209
|
// bail from this function when we detect an unnecessary LUX.init call.
|
@@ -1176,6 +1211,14 @@
|
|
1176
1211
|
if (!endMark) {
|
1177
1212
|
return;
|
1178
1213
|
}
|
1214
|
+
// Mark the "navigationStart" for this SPA page. A start time can be passed through, for example
|
1215
|
+
// to set a page's start time as an event timestamp.
|
1216
|
+
if (startTime) {
|
1217
|
+
_mark(START_MARK, { startTime: startTime });
|
1218
|
+
}
|
1219
|
+
else {
|
1220
|
+
_mark(START_MARK);
|
1221
|
+
}
|
1179
1222
|
logger.logEvent(LogEvent.InitCalled);
|
1180
1223
|
// Clear all interactions from the previous "page".
|
1181
1224
|
_clearIx();
|
@@ -1197,8 +1240,6 @@
|
|
1197
1240
|
// Clear flags then set the flag that init was called (ie, this is a SPA).
|
1198
1241
|
gFlags = 0;
|
1199
1242
|
gFlags = addFlag(gFlags, Flags.InitCalled);
|
1200
|
-
// Mark the "navigationStart" for this SPA page.
|
1201
|
-
_mark(START_MARK);
|
1202
1243
|
// Reset the maximum measure timeout
|
1203
1244
|
createMaxMeasureTimeout();
|
1204
1245
|
}
|
@@ -1305,8 +1346,9 @@
|
|
1305
1346
|
var ns = timing.navigationStart;
|
1306
1347
|
var startMark = _getMark(START_MARK);
|
1307
1348
|
var endMark = _getMark(END_MARK);
|
1308
|
-
if (startMark && endMark) {
|
1349
|
+
if (startMark && endMark && !pageRestoreTime) {
|
1309
1350
|
// This is a SPA page view, so send the SPA marks & measures instead of Nav Timing.
|
1351
|
+
// Note: pageRestoreTime indicates this was a bfcache restore, which we don't want to treat as a SPA.
|
1310
1352
|
var start = floor(startMark.startTime); // the start mark is "zero"
|
1311
1353
|
ns += start; // "navigationStart" for a SPA is the real navigationStart plus the start mark
|
1312
1354
|
var end = floor(endMark.startTime) - start; // delta from start mark
|
@@ -1322,21 +1364,33 @@
|
|
1322
1364
|
}
|
1323
1365
|
else if (performance.timing) {
|
1324
1366
|
// Return the real Nav Timing metrics because this is the "main" page view (not a SPA)
|
1367
|
+
var navEntry_1 = getNavigationEntry();
|
1325
1368
|
var startRender = getStartRender();
|
1326
1369
|
var fcp = getFcp();
|
1327
1370
|
var lcp = getLcp();
|
1328
1371
|
var prefixNTValue = function (key, prefix) {
|
1329
|
-
|
1330
|
-
|
1331
|
-
|
1372
|
+
// activationStart is always absolute. Other values are relative to activationStart.
|
1373
|
+
var zero = key === "activationStart" ? 0 : getZeroTime();
|
1374
|
+
if (typeof navEntry_1[key] === "number") {
|
1375
|
+
var value = clamp(floor(navEntry_1[key] - zero));
|
1376
|
+
return prefix + value;
|
1332
1377
|
}
|
1333
|
-
return
|
1378
|
+
return "";
|
1334
1379
|
};
|
1380
|
+
var loadEventStartStr = prefixNTValue("loadEventStart", "ls");
|
1381
|
+
var loadEventEndStr = prefixNTValue("loadEventEnd", "le");
|
1382
|
+
if (pageRestoreTime && startMark && endMark) {
|
1383
|
+
// For bfcache restores, we set the load time to the time it took for the page to be restored.
|
1384
|
+
var loadTime = floor(endMark.startTime - startMark.startTime);
|
1385
|
+
loadEventStartStr = "ls" + loadTime;
|
1386
|
+
loadEventEndStr = "le" + loadTime;
|
1387
|
+
}
|
1388
|
+
var redirect = wasRedirected();
|
1335
1389
|
s = [
|
1336
1390
|
ns,
|
1337
1391
|
prefixNTValue("activationStart", "as"),
|
1338
|
-
prefixNTValue("redirectStart", "rs"),
|
1339
|
-
prefixNTValue("redirectEnd", "re"),
|
1392
|
+
redirect ? prefixNTValue("redirectStart", "rs") : "",
|
1393
|
+
redirect ? prefixNTValue("redirectEnd", "re") : "",
|
1340
1394
|
prefixNTValue("fetchStart", "fs"),
|
1341
1395
|
prefixNTValue("domainLookupStart", "ds"),
|
1342
1396
|
prefixNTValue("domainLookupEnd", "de"),
|
@@ -1350,11 +1404,11 @@
|
|
1350
1404
|
prefixNTValue("domContentLoadedEventStart", "os"),
|
1351
1405
|
prefixNTValue("domContentLoadedEventEnd", "oe"),
|
1352
1406
|
prefixNTValue("domComplete", "oc"),
|
1353
|
-
|
1354
|
-
|
1355
|
-
typeof startRender !== "undefined" ? "sr" + startRender : "",
|
1356
|
-
typeof fcp !== "undefined" ? "fc" + fcp : "",
|
1357
|
-
typeof lcp !== "undefined" ? "lc" + lcp : "",
|
1407
|
+
loadEventStartStr,
|
1408
|
+
loadEventEndStr,
|
1409
|
+
typeof startRender !== "undefined" ? "sr" + clamp(startRender) : "",
|
1410
|
+
typeof fcp !== "undefined" ? "fc" + clamp(fcp) : "",
|
1411
|
+
typeof lcp !== "undefined" ? "lc" + clamp(lcp) : "",
|
1358
1412
|
].join("");
|
1359
1413
|
}
|
1360
1414
|
else if (endMark) {
|
@@ -1378,7 +1432,7 @@
|
|
1378
1432
|
for (var i = 0; i < paintEntries.length; i++) {
|
1379
1433
|
var entry = paintEntries[i];
|
1380
1434
|
if (entry.name === "first-contentful-paint") {
|
1381
|
-
return floor(entry.startTime);
|
1435
|
+
return floor(entry.startTime - getZeroTime());
|
1382
1436
|
}
|
1383
1437
|
}
|
1384
1438
|
return undefined;
|
@@ -1389,7 +1443,7 @@
|
|
1389
1443
|
if (lcpEntries.length) {
|
1390
1444
|
var lastEntry = lcpEntries[lcpEntries.length - 1];
|
1391
1445
|
logger.logEvent(LogEvent.PerformanceEntryProcessed, [lastEntry]);
|
1392
|
-
return floor(lastEntry.startTime);
|
1446
|
+
return floor(lastEntry.startTime - getZeroTime());
|
1393
1447
|
}
|
1394
1448
|
return undefined;
|
1395
1449
|
}
|
@@ -1402,7 +1456,7 @@
|
|
1402
1456
|
if (paintEntries.length) {
|
1403
1457
|
// If the Paint Timing API is supported, use the value of the first paint event
|
1404
1458
|
var paintValues = paintEntries.map(function (entry) { return entry.startTime; });
|
1405
|
-
return floor(Math.min.apply(null, paintValues));
|
1459
|
+
return floor(Math.min.apply(null, paintValues) - getZeroTime());
|
1406
1460
|
}
|
1407
1461
|
}
|
1408
1462
|
if (performance.timing && timing.msFirstPaint && __ENABLE_POLYFILLS) {
|
@@ -1474,17 +1528,17 @@
|
|
1474
1528
|
}
|
1475
1529
|
function docHeight(doc) {
|
1476
1530
|
var body = doc.body, docelem = doc.documentElement;
|
1477
|
-
var height =
|
1531
|
+
var height = max(body ? body.scrollHeight : 0, body ? body.offsetHeight : 0, docelem ? docelem.clientHeight : 0, docelem ? docelem.scrollHeight : 0, docelem ? docelem.offsetHeight : 0);
|
1478
1532
|
return height;
|
1479
1533
|
}
|
1480
1534
|
function docWidth(doc) {
|
1481
1535
|
var body = doc.body, docelem = doc.documentElement;
|
1482
|
-
var width =
|
1536
|
+
var width = max(body ? body.scrollWidth : 0, body ? body.offsetWidth : 0, docelem ? docelem.clientWidth : 0, docelem ? docelem.scrollWidth : 0, docelem ? docelem.offsetWidth : 0);
|
1483
1537
|
return width;
|
1484
1538
|
}
|
1485
1539
|
// Return the main HTML document transfer size (in bytes).
|
1486
1540
|
function docSize() {
|
1487
|
-
return
|
1541
|
+
return getNavigationEntry().encodedBodySize || 0;
|
1488
1542
|
}
|
1489
1543
|
// Return the connection type based on Network Information API.
|
1490
1544
|
// Note this API is in flux.
|
@@ -1624,6 +1678,10 @@
|
|
1624
1678
|
// Beacon back the LUX data.
|
1625
1679
|
function _sendLux() {
|
1626
1680
|
var _a;
|
1681
|
+
if (!isVisible() && !globalConfig.trackHiddenPages) {
|
1682
|
+
logger.logEvent(LogEvent.SendCancelledPageHidden);
|
1683
|
+
return;
|
1684
|
+
}
|
1627
1685
|
clearMaxMeasureTimeout();
|
1628
1686
|
var customerid = getCustomerId();
|
1629
1687
|
if (!customerid ||
|
@@ -1663,6 +1721,15 @@
|
|
1663
1721
|
if (wasPrerendered()) {
|
1664
1722
|
gFlags = addFlag(gFlags, Flags.PageWasPrerendered);
|
1665
1723
|
}
|
1724
|
+
if (globalConfig.serverTiming) {
|
1725
|
+
var navEntry = getNavigationEntry();
|
1726
|
+
if (navEntry.serverTiming) {
|
1727
|
+
var stPairs = getKeyValuePairs(globalConfig.serverTiming, navEntry.serverTiming);
|
1728
|
+
for (var name_2 in stPairs) {
|
1729
|
+
_addData(name_2, stPairs[name_2]);
|
1730
|
+
}
|
1731
|
+
}
|
1732
|
+
}
|
1666
1733
|
if (LUX.conversions) {
|
1667
1734
|
getMatchesFromPatternMap(LUX.conversions, location.hostname, location.pathname).forEach(function (conversion) {
|
1668
1735
|
LUX.addData(conversion, BOOLEAN_TRUE);
|
@@ -1757,7 +1824,7 @@
|
|
1757
1824
|
var sIx = ixValues(); // Interaction Metrics
|
1758
1825
|
var INP = getINP();
|
1759
1826
|
if (sIx) {
|
1760
|
-
|
1827
|
+
var beaconUrl = _getBeaconUrl(getUpdatedCustomData()) +
|
1761
1828
|
"&IX=" +
|
1762
1829
|
sIx +
|
1763
1830
|
(typeof gFirstInputDelay !== "undefined" ? "&FID=" + gFirstInputDelay : "") +
|
@@ -2031,8 +2098,8 @@
|
|
2031
2098
|
setTimeout(sendBeaconAfterMinimumMeasureTime_1, timeRemaining);
|
2032
2099
|
}
|
2033
2100
|
};
|
2034
|
-
if (globalConfig.
|
2035
|
-
// The
|
2101
|
+
if (globalConfig.trackHiddenPages) {
|
2102
|
+
// The trackHiddenPages config forces the beacon to be sent even when the page is not visible.
|
2036
2103
|
sendBeaconAfterMinimumMeasureTime_1();
|
2037
2104
|
}
|
2038
2105
|
else {
|
@@ -2040,6 +2107,31 @@
|
|
2040
2107
|
onVisible(sendBeaconAfterMinimumMeasureTime_1);
|
2041
2108
|
}
|
2042
2109
|
}
|
2110
|
+
// When newBeaconOnPageShow = true, we initiate a new page view whenever a page is restored from
|
2111
|
+
// bfcache. Since we have no "onload" event to hook into after a bfcache restore, we rely on the
|
2112
|
+
// unload and maxMeasureTime handlers to send the beacon.
|
2113
|
+
if (globalConfig.newBeaconOnPageShow) {
|
2114
|
+
window.addEventListener("pageshow", function (event) {
|
2115
|
+
if (event.persisted) {
|
2116
|
+
// Record the timestamp of the bfcache restore
|
2117
|
+
pageRestoreTime = event.timeStamp;
|
2118
|
+
// In Chromium, document.visibilityState is still "hidden" when pageshow fires after a bfcache
|
2119
|
+
// restore. Wrapping this in a setTimeout ensures the browser has enough time to update the
|
2120
|
+
// visibility.
|
2121
|
+
// See https://bugs.chromium.org/p/chromium/issues/detail?id=1133363
|
2122
|
+
setTimeout(function () {
|
2123
|
+
if (gbLuxSent) {
|
2124
|
+
// If the beacon was already sent for this page, we start a new page view and mark the
|
2125
|
+
// load time as the time it took to restore the page.
|
2126
|
+
_init(pageRestoreTime);
|
2127
|
+
_markLoadTime();
|
2128
|
+
}
|
2129
|
+
// Flag the current page as a bfcache restore
|
2130
|
+
gFlags = addFlag(gFlags, Flags.PageWasBfCacheRestored);
|
2131
|
+
}, 0);
|
2132
|
+
}
|
2133
|
+
});
|
2134
|
+
}
|
2043
2135
|
// Add the unload handlers when sendBeaconOnPageHidden is enabled
|
2044
2136
|
if (globalConfig.sendBeaconOnPageHidden) {
|
2045
2137
|
_addUnloadHandlers();
|
@@ -6,31 +6,6 @@ $govuk-new-link-styles: true;
|
|
6
6
|
@import "govuk_publishing_components/govuk_frontend_support";
|
7
7
|
@import "govuk_publishing_components/component_support";
|
8
8
|
|
9
|
-
// Import the same stylesheets used in static
|
10
|
-
// https://github.com/alphagov/static/blob/198a598682df40ce4a2c3c286c06244297c18cf0/app/assets/stylesheets/application.scss
|
11
|
-
// Although the component guide does not use static, we still need to import the same stylesheets used in static
|
12
|
-
// to avoid any rendering issues
|
13
|
-
// By following the same approach as frontend rendering applications,
|
14
|
-
// we ensure that stylesheets are loaded in the expected order and components render correctly
|
15
|
-
@import "govuk_publishing_components/components/breadcrumbs";
|
16
|
-
@import "govuk_publishing_components/components/button";
|
17
|
-
@import "govuk_publishing_components/components/error-message";
|
18
|
-
@import "govuk_publishing_components/components/heading";
|
19
|
-
@import "govuk_publishing_components/components/hint";
|
20
|
-
@import "govuk_publishing_components/components/input";
|
21
|
-
@import "govuk_publishing_components/components/label";
|
22
|
-
@import "govuk_publishing_components/components/search";
|
23
|
-
@import "govuk_publishing_components/components/skip-link";
|
24
|
-
@import "govuk_publishing_components/components/textarea";
|
25
|
-
@import "govuk_publishing_components/components/title";
|
26
|
-
|
27
|
-
@import "govuk_publishing_components/components/cookie-banner";
|
28
|
-
@import "govuk_publishing_components/components/feedback";
|
29
|
-
@import "govuk_publishing_components/components/layout-footer";
|
30
|
-
@import "govuk_publishing_components/components/layout-for-public";
|
31
|
-
@import "govuk_publishing_components/components/layout-header";
|
32
|
-
@import "govuk_publishing_components/components/layout-super-navigation-header";
|
33
|
-
|
34
9
|
// Include required helpers
|
35
10
|
@import "../../stylesheets/govuk_publishing_components/components/helpers/markdown-typography";
|
36
11
|
|