govuk_publishing_components 35.15.1 → 35.15.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5edbe2c7a347d6bc8069704f3434dc4c41de45b3286f7640893f7ff8f62c25a8
4
- data.tar.gz: d17f853fdf1a5598b808a69fdec621da35aa8662bc911d5c951715cc53bfb6a0
3
+ metadata.gz: f8533adba3392301001871fbe61ae994c04e20161bc629ba88e2388e76b696da
4
+ data.tar.gz: 1eec5780f166fab5b8ba18ffa62c093d1d4f570cccf0c901f466cbf136dcbcff
5
5
  SHA512:
6
- metadata.gz: 0f5f8a3a9706d98e11ce756987eb9dc442dce2c3701eeb2dbfe8ff2ad48c6c48d27c0c8f056b9e3f851d53d4c6cfb1712c042f9699a658fad94618d679b6c974
7
- data.tar.gz: fc1469502870ba2a479cde17f7d8edc652270a3ce98efd2aa6128797634e484bf6448cb54712f4c12c116a4f9275d345cb39ffdf13901bde137fc80321769657
6
+ metadata.gz: 80f9f867f5cea155dbc5fc158ef4fb32ded03123f8bcc4885e06e3f44fe94dc7169a941758aa96b88953d7f7eda678c9c882490a90cce05bd085762562dc178a
7
+ data.tar.gz: 8a93fabbfae63dcc902449ff97d2cfa6d741cdd971a6bac9bc1c70fc1f285e438af91c8a885647b5fbc11d1a6f922472c75c98cff07c075d239cbd679ffa6d0d
@@ -205,6 +205,10 @@ window.GOVUK.analyticsGa4 = window.GOVUK.analyticsGa4 || {};
205
205
  }
206
206
  },
207
207
 
208
+ getPathname: function () {
209
+ return window.location.pathname
210
+ },
211
+
208
212
  getProtocol: function () {
209
213
  return window.location.protocol
210
214
  },
@@ -252,6 +256,13 @@ window.GOVUK.analyticsGa4 = window.GOVUK.analyticsGa4 || {};
252
256
 
253
257
  applyRedactionIfRequired: function (PIIRemover, element, data) {
254
258
  return element.closest('[data-ga4-do-not-redact]') ? data : PIIRemover.stripPIIWithOverride(data, true, true)
259
+ },
260
+
261
+ appendPathToAnchorLinks: function (url) {
262
+ if (!this.stringStartsWith(url, '#') || this.getPathname() === '/') {
263
+ return url
264
+ }
265
+ return this.getPathname() + url
255
266
  }
256
267
  },
257
268
 
@@ -279,7 +290,8 @@ window.GOVUK.analyticsGa4 = window.GOVUK.analyticsGa4 || {};
279
290
 
280
291
  // In order to extract the number of results from resultCount (which is a string at this point (e.g. '12,345 results')), we remove the comma and
281
292
  // split string at the space character so it can be parsed as an integer
282
- resultCount = resultCount.textContent.replace(',', '')
293
+ resultCount = window.GOVUK.analyticsGa4.core.trackFunctions.removeLinesAndExtraSpaces(resultCount.textContent)
294
+ resultCount = resultCount.replace(',', '')
283
295
  resultCount = resultCount.split(' ')[0]
284
296
 
285
297
  return parseInt(resultCount)
@@ -74,7 +74,7 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
74
74
  if (aTag) {
75
75
  var href = aTag.getAttribute('href')
76
76
  if (href) {
77
- schema.event_data.url = href
77
+ schema.event_data.url = window.GOVUK.analyticsGa4.core.trackFunctions.appendPathToAnchorLinks(href)
78
78
  }
79
79
  }
80
80
  }
@@ -62,13 +62,13 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
62
62
 
63
63
  Ga4LinkTracker.prototype.trackClick = function (event) {
64
64
  var element = event.target
65
-
65
+ var trackFunctions = window.GOVUK.analyticsGa4.core.trackFunctions
66
66
  // don't track this link if it's already being tracked by the ecommerce tracker
67
67
  if (element.closest('[data-ga4-ecommerce-path]')) {
68
68
  return
69
69
  }
70
70
 
71
- var target = window.GOVUK.analyticsGa4.core.trackFunctions.findTrackingAttributes(event.target, this.trackingTrigger)
71
+ var target = trackFunctions.findTrackingAttributes(event.target, this.trackingTrigger)
72
72
  if (target) {
73
73
  try {
74
74
  var data = target.getAttribute(this.trackingTrigger)
@@ -80,17 +80,19 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
80
80
  }
81
81
 
82
82
  var text = data.text || event.target.textContent
83
- data.text = window.GOVUK.analyticsGa4.core.trackFunctions.removeLinesAndExtraSpaces(text)
84
- data.text = window.GOVUK.analyticsGa4.core.trackFunctions.applyRedactionIfRequired(this.PIIRemover, element, data.text)
83
+ data.text = trackFunctions.removeLinesAndExtraSpaces(text)
84
+ data.text = trackFunctions.applyRedactionIfRequired(this.PIIRemover, element, data.text)
85
85
  if (!data.text && (element.querySelector('img') || element.querySelector('svg') || element.tagName === 'IMG' || element.closest('svg'))) {
86
86
  data.text = 'image'
87
87
  }
88
88
  var url = data.url || this.findLink(event.target).getAttribute('href')
89
- data.url = window.GOVUK.analyticsGa4.core.trackFunctions.applyRedactionIfRequired(this.PIIRemover, element, window.GOVUK.analyticsGa4.core.trackFunctions.removeCrossDomainParams(url))
90
- data.link_domain = window.GOVUK.analyticsGa4.core.trackFunctions.populateLinkDomain(data.url)
91
- data.link_path_parts = window.GOVUK.analyticsGa4.core.trackFunctions.populateLinkPathParts(data.url)
92
- data.method = window.GOVUK.analyticsGa4.core.trackFunctions.getClickType(event)
93
- data.external = window.GOVUK.analyticsGa4.core.trackFunctions.isExternalLink(data.url) ? 'true' : 'false'
89
+ data.url = trackFunctions.removeCrossDomainParams(url)
90
+ data.url = trackFunctions.applyRedactionIfRequired(this.PIIRemover, element, data.url)
91
+ data.url = trackFunctions.appendPathToAnchorLinks(data.url)
92
+ data.link_domain = trackFunctions.populateLinkDomain(data.url)
93
+ data.link_path_parts = trackFunctions.populateLinkPathParts(data.url)
94
+ data.method = trackFunctions.getClickType(event)
95
+ data.external = trackFunctions.isExternalLink(data.url) ? 'true' : 'false'
94
96
  data.index = this.setIndex(data.index, event.target)
95
97
 
96
98
  if (data.type === 'smart answer' && data.action === 'change response') {
@@ -57,7 +57,8 @@ window.GOVUK.analyticsGa4.analyticsModules = window.GOVUK.analyticsGa4.analytics
57
57
  emergency_banner: document.querySelector('[data-ga4-emergency-banner]') ? 'true' : undefined,
58
58
  phase_banner: this.getElementAttribute('data-ga4-phase-banner') || undefined,
59
59
  devolved_nations_banner: this.getElementAttribute('data-ga4-devolved-nations-banner') || undefined,
60
- cookie_banner: document.querySelector('[data-ga4-cookie-banner]') ? 'true' : undefined
60
+ cookie_banner: document.querySelector('[data-ga4-cookie-banner]') ? 'true' : undefined,
61
+ intervention: this.getInterventionPresence()
61
62
  }
62
63
  }
63
64
  window.GOVUK.analyticsGa4.core.sendData(data)
@@ -76,7 +77,7 @@ window.GOVUK.analyticsGa4.analyticsModules = window.GOVUK.analyticsGa4.analytics
76
77
  // remove GA parameters of the form _ga=2320.021-012302 or _gl=02.10320.01230-123
77
78
  stripGaParam: function (str) {
78
79
  str = str.replace(/(_ga=[0-9.-]+)/g, '_ga=[id]')
79
- str = str.replace(/(_gl=[0-9.-]+)/g, '_gl=[id]')
80
+ str = str.replace(/(_gl=[a-zA-Z0-9._\-*]+)/g, '_gl=[id]')
80
81
  return str
81
82
  },
82
83
 
@@ -112,11 +113,12 @@ window.GOVUK.analyticsGa4.analyticsModules = window.GOVUK.analyticsGa4.analytics
112
113
 
113
114
  getLanguage: function () {
114
115
  var content = document.getElementById('content')
116
+ var html = document.querySelector('html')
115
117
  if (content) {
116
118
  return content.getAttribute('lang') || this.nullValue
117
- } else {
118
- return this.nullValue
119
119
  }
120
+ // html.getAttribute('lang') is untested - Jasmine would not allow lang to be set on <html>.
121
+ return html.getAttribute('lang') || this.nullValue
120
122
  },
121
123
 
122
124
  getHistory: function () {
@@ -129,6 +131,25 @@ window.GOVUK.analyticsGa4.analyticsModules = window.GOVUK.analyticsGa4.analytics
129
131
  return (withdrawn === 'withdrawn') ? 'true' : 'false'
130
132
  },
131
133
 
134
+ getInterventionPresence: function () {
135
+ /* If the user hides the banner using JS, a cookie is set to hide it on future page loads.
136
+ * Therefore we need to start the intervention banner early so that it hides if this cookie exists.
137
+ * Without this, our pageview object will track the banner as visible before it gets hidden. */
138
+
139
+ var intervention = document.querySelector('[data-ga4-intervention-banner]')
140
+
141
+ if (intervention) {
142
+ window.GOVUK.modules.start(intervention)
143
+ var interventionHidden = intervention.getAttribute('hidden') === '' || intervention.getAttribute('hidden')
144
+
145
+ if (interventionHidden) {
146
+ return undefined
147
+ }
148
+ return 'true'
149
+ }
150
+ return undefined
151
+ },
152
+
132
153
  splitLongMetaContent: function (metatag) {
133
154
  var tag = this.getMetaContent(metatag)
134
155
  if (tag) {
@@ -538,6 +538,10 @@
538
538
  // -------------------------------------------------------------------------
539
539
  // Settings
540
540
  // -------------------------------------------------------------------------
541
+ // This ID usually appended to the end of the lux.js as a query string when
542
+ // using the SpeedCurve hosted version - but we have to include it here as
543
+ // this is self hosted.
544
+ LUX.customerid = 47044334;
541
545
  // Set the sample rate to 1% to avoid all events being sent.
542
546
  LUX.samplerate = 1;
543
547
  // -------------------------------------------------------------------------
@@ -1494,10 +1498,9 @@
1494
1498
  }
1495
1499
  return getHighPercentileINP();
1496
1500
  }
1501
+ // function simplified for our use, original would get the customerid from the script src URL
1502
+ // but we set it inside the code in this file, so this function just returns that
1497
1503
  function getCustomerId() {
1498
- if (!LUX.customerid) {
1499
- LUX.customerid = thisScript.src.match(/id=(\d+)/).pop();
1500
- }
1501
1504
  return LUX.customerid || "";
1502
1505
  }
1503
1506
  function avgDomDepth() {
@@ -2200,11 +2203,6 @@
2200
2203
  // More settings
2201
2204
  // ---------------------------------------------------------------------------
2202
2205
  //
2203
- // This ID usually appended to the end of the lux.js as a query string when
2204
- // using the SpeedCurve hosted version - but we have to include it here as
2205
- // this is self hosted.
2206
- LUX.customerid = 47044334;
2207
-
2208
2206
  // Setting debug to `true` shows what happening as it happens. Running
2209
2207
  // `LUX.getDebug()` in the browser's console will show the history of what's
2210
2208
  // happened.
@@ -13,11 +13,8 @@
13
13
  margin: 0 govuk-spacing(-3);
14
14
 
15
15
  display: grid;
16
- grid-auto-flow: row;
17
- // Use CSS grid to calculate the number of rows
18
- grid-template-rows: auto;
19
- // Use the tallest cell in the grid to set the height for all rows
20
- grid-auto-rows: fractions(1);
16
+ grid-auto-flow: row; // Use CSS grid to calculate the number of rows
17
+ grid-auto-rows: fractions(1); // Set all rows to same fractional height of the complete grid
21
18
  grid-template-columns: fractions(1);
22
19
 
23
20
  @include govuk-media-query($from: "tablet") {
@@ -11,6 +11,8 @@
11
11
 
12
12
  data_attributes ||= {}
13
13
  suggestion_data_attributes ||= {}
14
+ dismiss_data_attributes ||= {}
15
+ dismiss_link_data_attributes ||= {}
14
16
  data_attributes[:module] = "intervention"
15
17
  data_attributes["intervention-name"] = name
16
18
 
@@ -30,6 +32,11 @@
30
32
  intervention_helper = GovukPublishingComponents::Presenters::InterventionHelper.new(options)
31
33
  dismiss_href = intervention_helper.dismiss_link
32
34
 
35
+ ga4_tracking ||= false
36
+ suggestion_data_attributes[:module] = "#{suggestion_data_attributes[:module]} ga4-link-tracker".strip if ga4_tracking
37
+ suggestion_data_attributes[:ga4_link] = { event_name: "navigation", type: "intervention", section: suggestion_text, index: 1, index_total: 1 }.to_json if ga4_tracking
38
+ data_attributes[:ga4_intervention_banner] = "" if ga4_tracking # Added to the parent element for the GA4 pageview object to use
39
+
33
40
  suggestion_tag_options = {
34
41
  class: "govuk-link",
35
42
  href: suggestion_link_url,
@@ -51,6 +58,9 @@
51
58
  data: data_attributes,
52
59
  }
53
60
  section_options.merge!({ hidden: true }) if hide
61
+
62
+ dismiss_link_data_attributes[:module] = "#{dismiss_link_data_attributes[:module]} ga4-event-tracker".strip if ga4_tracking
63
+ dismiss_link_data_attributes[:ga4_event] = { event_name: "select_content", type: "intervention", section: suggestion_text, action: 'closed' }.to_json if ga4_tracking
54
64
  %>
55
65
  <% if intervention_helper.show? %>
56
66
  <%= tag.section **section_options do %>
@@ -62,8 +72,8 @@
62
72
  </p>
63
73
 
64
74
  <% if dismiss_text %>
65
- <p class="govuk-body">
66
- <%= tag.a class: "govuk-link js-dismiss-link", href: dismiss_href do %>
75
+ <%= tag.p class: "govuk-body", data: dismiss_data_attributes do %>
76
+ <%= tag.a class: "govuk-link js-dismiss-link", href: dismiss_href, data: dismiss_link_data_attributes do %>
67
77
  <svg class="gem-c-intervention__dismiss-icon"
68
78
  width="19" height="19" viewBox="0 0 19 19"
69
79
  aria-hidden="true"
@@ -74,7 +84,7 @@
74
84
  </svg>
75
85
  <%= dismiss_text %>
76
86
  <% end %>
77
- </p>
87
+ <% end %>
78
88
  <% end %>
79
89
  <% end %>
80
90
  <% end %>
@@ -65,8 +65,8 @@ examples:
65
65
 
66
66
  with_data_attributes:
67
67
  description: |
68
- This example shows the use of `suggestion_data_attributes` and
69
- `dismiss_data_attributes` for click tracking.
68
+ This example shows the use of `suggestion_data_attributes`,
69
+ `dismiss_data_attributes` for click tracking on the dismiss section <p> tag, and `dismiss_link_data_attributes` for adding attributes to the dismiss link <a> tag.
70
70
 
71
71
  Other data attributes can also be applied as required. Note that the component does not include built in tracking. If this is required consider using the [track click script](https://github.com/alphagov/govuk_publishing_components/blob/main/docs/analytics/track-click.md).
72
72
  data:
@@ -87,3 +87,15 @@ examples:
87
87
  track-dimension: Hide this suggestion
88
88
  track-dimension-index: 29
89
89
  track-label: hide the intervention
90
+ dismiss_link_data_attributes:
91
+ track-category: example
92
+ with_ga4_tracking:
93
+ description: |
94
+ Enables GA4 tracking on the banner. This includes link tracking on the component itself, event tracking on the 'Hide' link, and allows pageviews to record the presence of the banner on page load.
95
+ data:
96
+ ga4_tracking: true
97
+ suggestion_text: Based on your browsing you might be interested in
98
+ suggestion_link_text: "Travel abroad: step by step"
99
+ suggestion_link_url: /travel-abroad
100
+ dismiss_text: Hide this suggestion
101
+ name: another-campaign-name
@@ -241,6 +241,8 @@ en:
241
241
  href: "/sign-in-universal-credit"
242
242
  - label: Check your National Insurance record
243
243
  href: "/check-national-insurance-record"
244
+ - label: 'Check MOT history of a vehicle'
245
+ href: /check-mot-history
244
246
  popular_links_heading: Popular on GOV.UK
245
247
  search_text: Search GOV.UK
246
248
  metadata:
@@ -1,3 +1,3 @@
1
1
  module GovukPublishingComponents
2
- VERSION = "35.15.1".freeze
2
+ VERSION = "35.15.3".freeze
3
3
  end
@@ -164,9 +164,9 @@ declare namespace axe {
164
164
  interface NodeResult {
165
165
  html: string;
166
166
  impact?: ImpactValue;
167
- target: string[];
167
+ target: UnlabelledFrameSelector;
168
168
  xpath?: string[];
169
- ancestry?: string[];
169
+ ancestry?: UnlabelledFrameSelector;
170
170
  any: CheckResult[];
171
171
  all: CheckResult[];
172
172
  none: CheckResult[];
@@ -181,8 +181,11 @@ declare namespace axe {
181
181
  relatedNodes?: RelatedNode[];
182
182
  }
183
183
  interface RelatedNode {
184
- target: string[];
185
184
  html: string;
185
+ target: UnlabelledFrameSelector;
186
+ xpath?: string[];
187
+ ancestry?: UnlabelledFrameSelector;
188
+ element?: HTMLElement;
186
189
  }
187
190
  interface RuleLocale {
188
191
  [key: string]: {
@@ -193,7 +196,7 @@ declare namespace axe {
193
196
  interface CheckMessages {
194
197
  pass: string | { [key: string]: string };
195
198
  fail: string | { [key: string]: string };
196
- incomplete: string | { [key: string]: string };
199
+ incomplete?: string | { [key: string]: string };
197
200
  }
198
201
  interface CheckLocale {
199
202
  [key: string]: CheckMessages;
@@ -257,10 +260,31 @@ declare namespace axe {
257
260
  brand?: string;
258
261
  application?: string;
259
262
  }
263
+ interface CheckHelper {
264
+ async: () => (result: boolean | undefined | Error) => void;
265
+ data: (data: unknown) => void;
266
+ relatedNodes: (nodes: Element[]) => void;
267
+ }
268
+ interface AfterResult {
269
+ id: string;
270
+ data?: unknown;
271
+ relatedNodes: SerialDqElement[];
272
+ result: boolean | undefined;
273
+ node: SerialDqElement;
274
+ }
260
275
  interface Check {
261
276
  id: string;
262
- evaluate?: Function | string;
263
- after?: Function | string;
277
+ evaluate?:
278
+ | string
279
+ | ((
280
+ this: CheckHelper,
281
+ node: Element,
282
+ options: unknown,
283
+ virtualNode: VirtualNode
284
+ ) => boolean | undefined | void);
285
+ after?:
286
+ | string
287
+ | ((results: AfterResult[], options: unknown) => AfterResult[]);
264
288
  options?: any;
265
289
  matches?: string;
266
290
  enabled?: boolean;
@@ -280,9 +304,10 @@ declare namespace axe {
280
304
  all?: string[];
281
305
  none?: string[];
282
306
  tags?: string[];
283
- matches?: string;
307
+ matches?: string | ((node: Element, virtualNode: VirtualNode) => boolean);
284
308
  reviewOnFail?: boolean;
285
- metadata?: Omit<RuleMetadata, 'ruleId'>;
309
+ actIds?: string[];
310
+ metadata?: Omit<RuleMetadata, 'ruleId' | 'tags' | 'actIds'>;
286
311
  }
287
312
  interface AxePlugin {
288
313
  id: string;
@@ -346,7 +371,8 @@ declare namespace axe {
346
371
  type AxeReporter<T = unknown> = (
347
372
  rawResults: RawResult[],
348
373
  option: RunOptions,
349
- callback: (report: T) => void
374
+ resolve: (report: T) => void,
375
+ reject: (error: Error) => void
350
376
  ) => void;
351
377
 
352
378
  interface VirtualNode {
@@ -367,6 +393,42 @@ declare namespace axe {
367
393
  shadowSelect: (selector: CrossTreeSelector) => Element | null;
368
394
  shadowSelectAll: (selector: CrossTreeSelector) => Element[];
369
395
  getStandards(): Required<Standards>;
396
+ DqElement: new (
397
+ elm: Element,
398
+ options?: { absolutePaths?: boolean }
399
+ ) => SerialDqElement;
400
+ uuid: (
401
+ options?: { random?: Uint8Array | Array<number> },
402
+ buf?: Uint8Array | Array<number>,
403
+ offset?: number
404
+ ) => string | Uint8Array | Array<number>;
405
+ }
406
+
407
+ interface Aria {
408
+ getRoleType: (role: string | Element | VirtualNode | null) => string | null;
409
+ }
410
+
411
+ interface Dom {
412
+ isFocusable: (node: Element | VirtualNode) => boolean;
413
+ isNativelyFocusable: (node: Element | VirtualNode) => boolean;
414
+ }
415
+
416
+ type AccessibleTextOptions = {
417
+ inControlContext?: boolean;
418
+ inLabelledByContext?: boolean;
419
+ };
420
+
421
+ interface Text {
422
+ accessibleText: (
423
+ element: Element,
424
+ options?: AccessibleTextOptions
425
+ ) => string;
426
+ }
427
+
428
+ interface Commons {
429
+ aria: Aria;
430
+ dom: Dom;
431
+ text: Text;
370
432
  }
371
433
 
372
434
  interface EnvironmentData {
@@ -380,6 +442,7 @@ declare namespace axe {
380
442
  let version: string;
381
443
  let plugins: any;
382
444
  let utils: Utils;
445
+ let commons: Commons;
383
446
 
384
447
  /**
385
448
  * Source string to use as an injected script in Selenium