govuk_publishing_components 29.15.0 → 29.15.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/gtm-click-tracking.js +24 -13
  3. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/gtm-page-views.js +10 -13
  4. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/gtm-schemas.js +32 -0
  5. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4.js +1 -0
  6. data/app/assets/javascripts/govuk_publishing_components/components/accordion.js +17 -22
  7. data/app/assets/stylesheets/govuk_publishing_components/components/govspeak/_charts.scss +13 -2
  8. data/app/models/govuk_publishing_components/audit_applications.rb +49 -9
  9. data/app/models/govuk_publishing_components/audit_comparer.rb +47 -9
  10. data/app/views/govuk_publishing_components/audit/_components.html.erb +12 -31
  11. data/app/views/govuk_publishing_components/audit/_items_in_applications.html.erb +50 -0
  12. data/app/views/govuk_publishing_components/components/_table.html.erb +3 -2
  13. data/app/views/govuk_publishing_components/components/docs/back_link.yml +1 -1
  14. data/app/views/govuk_publishing_components/components/docs/big_number.yml +2 -2
  15. data/app/views/govuk_publishing_components/components/docs/breadcrumbs.yml +2 -2
  16. data/app/views/govuk_publishing_components/components/docs/button.yml +41 -40
  17. data/app/views/govuk_publishing_components/components/docs/cards.yml +2 -0
  18. data/app/views/govuk_publishing_components/components/docs/checkboxes.yml +216 -216
  19. data/app/views/govuk_publishing_components/components/docs/cookie_banner.yml +2 -1
  20. data/app/views/govuk_publishing_components/components/docs/copy_to_clipboard.yml +2 -2
  21. data/app/views/govuk_publishing_components/components/docs/details.yml +5 -1
  22. data/app/views/govuk_publishing_components/components/docs/document_list.yml +1 -2
  23. data/app/views/govuk_publishing_components/components/docs/error_alert.yml +4 -0
  24. data/app/views/govuk_publishing_components/components/docs/error_summary.yml +4 -6
  25. data/app/views/govuk_publishing_components/components/docs/govspeak.yml +6 -7
  26. data/app/views/govuk_publishing_components/components/docs/image_card.yml +3 -2
  27. data/app/views/govuk_publishing_components/components/docs/intervention.yml +25 -25
  28. data/app/views/govuk_publishing_components/components/docs/organisation_logo.yml +1 -2
  29. data/app/views/govuk_publishing_components/components/docs/print_link.yml +5 -1
  30. data/app/views/govuk_publishing_components/components/docs/select.yml +101 -98
  31. data/app/views/govuk_publishing_components/components/docs/table.yml +6 -1
  32. data/app/views/govuk_publishing_components/components/docs/tabs.yml +4 -0
  33. data/lib/govuk_publishing_components/app_helpers/table_helper.rb +4 -2
  34. data/lib/govuk_publishing_components/version.rb +1 -1
  35. metadata +5 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f53467f684078c59a2e499d0697b47183adacc1b30b9c19839ab8a8983715ff2
4
- data.tar.gz: edddfebbcd07e825aa735e3bbe59fe000ebf5b2007272522ef94e92506cae352
3
+ metadata.gz: 1093c2ff6d40fae820a8b90e7a349d7e8dd78b10fca660453365343d7968749c
4
+ data.tar.gz: 3607d6e31004a9697a60a6c7075124b085b2c7a592c6f159e9540fa9ed7c0ad6
5
5
  SHA512:
6
- metadata.gz: 25eed8d95465c897c95ab654b97e2bfc15fbf956fd7535c361354da8326cc23795160413abdca24bb80757f4c6ea4c1033f3ca96474caf705ae92059896bf8c8
7
- data.tar.gz: a7c01b6e8fa79cde09ef1a04c596a97a2dde847341c7e50fece0997cd78472b8a6f30741f228feb6c29b969c3374664f46d9262827027fc42ec4a67bb0c59bd4
6
+ metadata.gz: 126afbff6dcbcab4a12c6551ab3546c2727841a9454df9a2eafae820bf8dcb483ad578b041e3250f085b3ba34534eabbb80727715f706391fdc2530d975da97a
7
+ data.tar.gz: ea8bdcc6c1f05fc3f469de5fe182ff304ea58e228ad9caf8c89ecf8f66cc8ad8c279a5ff4d5556f09fbed75f88cd5cbd5cc46c21afc2dd1249befcbe16af8dd6
@@ -7,7 +7,7 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
7
7
 
8
8
  function GtmClickTracking (module) {
9
9
  this.module = module
10
- this.trackingTrigger = 'data-gtm-event-name' // elements with this attribute get tracked
10
+ this.trackingTrigger = 'data-ga4' // elements with this attribute get tracked
11
11
  }
12
12
 
13
13
  GtmClickTracking.prototype.init = function () {
@@ -18,12 +18,24 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
18
18
  if (window.dataLayer) {
19
19
  var target = this.findTrackingAttributes(event.target)
20
20
  if (target) {
21
- var data = {
22
- event: 'analytics',
23
- event_name: target.getAttribute('data-gtm-event-name'),
24
- // get entire URL apart from domain
25
- link_url: window.location.href.substring(window.location.origin.length),
26
- ui: JSON.parse(target.getAttribute('data-gtm-attributes')) || {}
21
+ var schema = new window.GOVUK.analyticsGA4.Schemas().eventSchema()
22
+
23
+ try {
24
+ var data = target.getAttribute(this.trackingTrigger)
25
+ data = JSON.parse(data)
26
+ } catch (e) {
27
+ // if there's a problem with the config, don't start the tracker
28
+ console.error('GA4 configuration error: ' + e.message, window.location)
29
+ return
30
+ }
31
+
32
+ schema.event = 'event_data'
33
+ // get attributes from the data attribute to send to GA
34
+ // only allow it if it already exists in the schema
35
+ for (var property in data) {
36
+ if (schema.event_data[property]) {
37
+ schema.event_data[property] = data[property]
38
+ }
27
39
  }
28
40
 
29
41
  // Ensure it only tracks aria-expanded in an accordion element, instead of in any child of the clicked element
@@ -39,15 +51,14 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
39
51
  var detailsElement = target.closest('details')
40
52
 
41
53
  if (ariaExpanded) {
42
- data.ui.text = data.ui.text || target.innerText
43
- data.ui.action = (ariaExpanded === 'false') ? 'opened' : 'closed'
54
+ schema.event_data.text = data.text || target.innerText
55
+ schema.event_data.action = (ariaExpanded === 'false') ? 'opened' : 'closed'
44
56
  } else if (detailsElement) {
45
- data.ui.text = data.ui.text || detailsElement.textContent
57
+ schema.event_data.text = data.text || detailsElement.textContent
46
58
  var openAttribute = detailsElement.getAttribute('open')
47
- data.ui.action = (openAttribute == null) ? 'opened' : 'closed'
59
+ schema.event_data.action = (openAttribute == null) ? 'opened' : 'closed'
48
60
  }
49
-
50
- window.dataLayer.push(data)
61
+ window.dataLayer.push(schema)
51
62
  }
52
63
  }
53
64
  }
@@ -9,29 +9,26 @@
9
9
  sendPageView: function () {
10
10
  if (window.dataLayer) {
11
11
  var data = {
12
- event: 'config_ready',
13
- page: {
12
+ event: 'page_view',
13
+ page_view: {
14
14
  location: this.getLocation(),
15
15
  referrer: this.getReferrer(),
16
16
  title: this.getTitle(),
17
- status_code: this.getStatusCode()
18
- },
19
- publishing: {
17
+ status_code: this.getStatusCode(),
18
+
20
19
  document_type: this.getMetaContent('format'),
21
20
  publishing_app: this.getMetaContent('publishing-app'),
22
21
  rendering_app: this.getMetaContent('rendering-app'),
23
22
  schema_name: this.getMetaContent('schema-name'),
24
- content_id: this.getMetaContent('content-id')
25
- },
26
- taxonomy: {
23
+ content_id: this.getMetaContent('content-id'),
24
+
27
25
  section: this.getMetaContent('section'),
28
26
  taxon_slug: this.getMetaContent('taxon-slug'),
29
27
  taxon_id: this.getMetaContent('taxon-id'),
30
28
  themes: this.getMetaContent('themes'),
31
29
  taxon_slugs: this.getMetaContent('taxon-slugs'),
32
- taxon_ids: this.getMetaContent('taxon-ids')
33
- },
34
- content: {
30
+ taxon_ids: this.getMetaContent('taxon-ids'),
31
+
35
32
  language: this.getLanguage(),
36
33
  history: this.getHistory(),
37
34
  withdrawn: this.getWithDrawn(),
@@ -65,9 +62,9 @@
65
62
  // https://github.com/alphagov/static/blob/main/app/views/root/_error_page.html.erb#L32
66
63
  getStatusCode: function () {
67
64
  if (window.httpStatusCode) {
68
- return window.httpStatusCode
65
+ return window.httpStatusCode.toString()
69
66
  } else {
70
- return 200
67
+ return '200'
71
68
  }
72
69
  },
73
70
 
@@ -0,0 +1,32 @@
1
+ ;(function (global) {
2
+ 'use strict'
3
+
4
+ var GOVUK = global.GOVUK || {}
5
+
6
+ var Schemas = function () {
7
+ this.null = 'n/a'
8
+ }
9
+
10
+ Schemas.prototype.eventSchema = function () {
11
+ return {
12
+ event: this.null,
13
+
14
+ event_data: {
15
+ event_name: this.null,
16
+ type: this.null,
17
+ url: this.null,
18
+ text: this.null,
19
+ index: this.null,
20
+ index_total: this.null,
21
+ section: this.null,
22
+ action: this.null,
23
+ external: this.null
24
+ }
25
+ }
26
+ }
27
+
28
+ GOVUK.analyticsGA4 = GOVUK.analyticsGA4 || {}
29
+ GOVUK.analyticsGA4.Schemas = Schemas
30
+
31
+ global.GOVUK = GOVUK
32
+ })(window)
@@ -1,4 +1,5 @@
1
1
  // The following modules are imported in a specific order
2
+ //= require ./analytics-ga4/gtm-schemas
2
3
  //= require ./analytics-ga4/pii-remover
3
4
  //= require ./analytics-ga4/gtm-page-views
4
5
  //= require ./analytics-ga4/gtm-click-tracking
@@ -10,27 +10,22 @@ window.GOVUK.Modules.GovukAccordion = window.GOVUKFrontend.Accordion;
10
10
  function GemAccordion ($module) {
11
11
  this.$module = $module
12
12
  this.sectionClass = 'govuk-accordion__section'
13
- this.sectionClassExpanded = 'govuk-accordion__section--expanded'
14
- this.sectionHeaderClass = 'govuk-accordion__section-header'
15
- this.sectionInnerContent = 'govuk-accordion__section-content'
16
- this.showAllControls = 'govuk-accordion__show-all'
17
- this.sectionButton = 'govuk-accordion__section-button'
18
- this.headingText = 'govuk-accordion__section-heading-text'
19
-
20
- // Translated component content and language attribute pulled from data attributes
13
+ this.sectionExpandedClass = 'govuk-accordion__section--expanded'
14
+ this.sectionInnerContentClass = 'govuk-accordion__section-content'
15
+
16
+ this.sectionHeader = '.govuk-accordion__section-header'
17
+ this.showAllControls = '.govuk-accordion__show-all'
18
+ this.sectionButton = '.govuk-accordion__section-button'
19
+ this.headingText = '.govuk-accordion__section-heading-text'
20
+
21
+ // language attribute pulled from data attributes
21
22
  this.$module.actions = {}
22
23
  this.$module.actions.locale = this.$module.getAttribute('data-locale')
23
- this.$module.actions.showText = this.$module.getAttribute('data-show-text')
24
- this.$module.actions.hideText = this.$module.getAttribute('data-hide-text')
25
- this.$module.actions.showAllText = this.$module.getAttribute('data-show-all-text')
26
- this.$module.actions.hideAllText = this.$module.getAttribute('data-hide-all-text')
27
- this.$module.actions.thisSectionVisuallyHidden = this.$module.getAttribute('data-this-section-visually-hidden')
28
24
  }
29
25
 
30
26
  GemAccordion.prototype.init = function () {
31
27
  // Indicate that JavaScript has worked
32
- this.$module.classList.add('gem-c-accordion--active')
33
- this.$module.querySelector('.' + this.showAllControls).classList.add('gem-c-accordion__show-all')
28
+ this.$module.querySelector(this.showAllControls).classList.add('gem-c-accordion__show-all')
34
29
 
35
30
  // Feature flag for anchor tag navigation used on manuals
36
31
  if (this.$module.getAttribute('data-anchor-navigation') === 'true') {
@@ -50,7 +45,7 @@ window.GOVUK.Modules.GovukAccordion = window.GOVUKFrontend.Accordion;
50
45
  var showAllAttributes = this.$module.getAttribute('data-show-all-attributes')
51
46
  if (showAllAttributes) {
52
47
  try {
53
- var showAll = this.$module.querySelector('.' + this.showAllControls)
48
+ var showAll = this.$module.querySelector(this.showAllControls)
54
49
  var values = JSON.parse(showAllAttributes)
55
50
  var keys = Object.keys(values)
56
51
  for (var i = 0; i < keys.length; i++) {
@@ -74,7 +69,7 @@ window.GOVUK.Modules.GovukAccordion = window.GOVUKFrontend.Accordion;
74
69
  // Add event listeners for links to open accordion sections when navigated to using said anchor links on the page
75
70
  // Adding an event listener to all anchor link a tags in an accordion is risky but we circumvent this risk partially by only being a layer of accordion behaviour instead of any sort of change to link behaviour
76
71
  GemAccordion.prototype.addEventListenersForAnchors = function () {
77
- var links = this.$module.querySelectorAll('.' + this.sectionInnerContent + ' a[href*="#"]')
72
+ var links = this.$module.querySelectorAll(this.sectionInnerContentClass + ' a[href*="#"]')
78
73
 
79
74
  nodeListForEach(links, function (link) {
80
75
  if (link.pathname === window.location.pathname) {
@@ -87,7 +82,7 @@ window.GOVUK.Modules.GovukAccordion = window.GOVUKFrontend.Accordion;
87
82
  GemAccordion.prototype.openForAnchor = function (hash) {
88
83
  var target = document.getElementById(hash)
89
84
  var $section = this.getContainingSection(target)
90
- var $header = $section.querySelector('.' + this.sectionHeaderClass)
85
+ var $header = $section.querySelector(this.sectionHeader)
91
86
  var $expanded = this.getContainingSection($section)
92
87
  var $parent = $header.parentElement
93
88
 
@@ -95,7 +90,7 @@ window.GOVUK.Modules.GovukAccordion = window.GOVUKFrontend.Accordion;
95
90
  // Should the target anchor link be within the same page, open section - navigate normally
96
91
  // Should the target anchor link be within a different, closed section, open this section
97
92
  // Should the target anchor link be within a different page and different, closed section open this section
98
- if ($expanded && (!$parent.classList.contains(this.sectionClassExpanded))) {
93
+ if ($expanded && (!$parent.classList.contains(this.sectionExpandedClass))) {
99
94
  $header.click()
100
95
  }
101
96
  }
@@ -119,7 +114,7 @@ window.GOVUK.Modules.GovukAccordion = window.GOVUKFrontend.Accordion;
119
114
 
120
115
  // To track the Accordion's "Show all sections" / "Hide all sections" button click events and pass them to the GA event tracking
121
116
  GemAccordion.prototype.addAccordionOpenAllTracking = function () {
122
- this.$module.querySelector('.' + this.showAllControls).addEventListener('click', function (event) {
117
+ this.$module.querySelector(this.showAllControls).addEventListener('click', function (event) {
123
118
  var expanded = event.target.getAttribute('aria-expanded') === 'true'
124
119
  var label = expanded ? 'Show all sections' : 'Hide all sections'
125
120
  var action = expanded ? 'accordionOpened' : 'accordionClosed'
@@ -141,7 +136,7 @@ window.GOVUK.Modules.GovukAccordion = window.GOVUKFrontend.Accordion;
141
136
  }
142
137
 
143
138
  GemAccordion.prototype.addEventListenerSections = function () {
144
- var sections = this.$module.querySelectorAll('.' + this.sectionButton)
139
+ var sections = this.$module.querySelectorAll(this.sectionButton)
145
140
  nodeListForEach(sections, function (section) {
146
141
  section.addEventListener('click', this.addAccordionSectionTracking.bind(this, section))
147
142
  }.bind(this))
@@ -150,7 +145,7 @@ window.GOVUK.Modules.GovukAccordion = window.GOVUKFrontend.Accordion;
150
145
  // If the Accordion's sections are opened on click, then pass them to the GA event tracking
151
146
  GemAccordion.prototype.addAccordionSectionTracking = function (section) {
152
147
  var expanded = section.getAttribute('aria-expanded') === 'false'
153
- var label = section.querySelector('.' + this.headingText).textContent
148
+ var label = section.querySelector(this.headingText).textContent
154
149
  var action = expanded ? 'accordionOpened' : 'accordionClosed'
155
150
  var options = { transport: 'beacon', label: label }
156
151
 
@@ -25,12 +25,23 @@
25
25
  $caption-side: top; // Caption alignment. Top or bottom.
26
26
  $key-width: 160px; // Only used by IE. Other browsers get smallest width that fits content
27
27
 
28
+ // The following accessible colour palette has been developed to meet the colour contrast requirements for adjacent colours (as set out in WCAG 2.1)
29
+ // For charts, the palette should be used instead of the GOV.UK colour palette - https://design-system.service.gov.uk/styles/colour/
30
+ // https://gss.civilservice.gov.uk/policy-store/data-visualisation-colours-in-charts/#section-5
31
+
32
+ $gss-colour-dark-blue: #12436d;
33
+ $gss-colour-turquoise: #28a197;
34
+ $gss-colour-dark-pink: #801650;
35
+ $gss-colour-orange: #f46a25;
36
+ $gss-colour-dark-grey: #3d3d3d;
37
+ $gss-colour-plum: #a285d1;
38
+
28
39
  // CHART COLOUR SCHEME
29
40
 
30
41
  $chart-border: govuk-colour("white"); // Chart border colour
31
42
  $key-border: govuk-colour("white"); // Key border colour
32
- $bar-colours: govuk-colour("blue"), govuk-colour("turquoise"), govuk-colour("green"), govuk-colour("light-green"), govuk-colour("yellow"), govuk-colour("orange"), govuk-colour("red"), govuk-colour("bright-purple", $legacy: "bright-red");
33
- $bar-text-colours: govuk-colour("white"), govuk-colour("black"), govuk-colour("white"), govuk-colour("black"), govuk-colour("black"), govuk-colour("black"), govuk-colour("white"), govuk-colour("white");
43
+ $bar-colours: $gss-colour-dark-blue, $gss-colour-turquoise, $gss-colour-dark-pink, $gss-colour-orange, $gss-colour-dark-grey, $gss-colour-plum;
44
+ $bar-text-colours: govuk-colour("white"), govuk-colour("white"), govuk-colour("white"), govuk-colour("black"), govuk-colour("white"), govuk-colour("black");
34
45
  $bar-cell-colour: govuk-colour("black");
35
46
  $bar-outdented-colour: govuk-colour("black");
36
47
 
@@ -6,8 +6,10 @@ module GovukPublishingComponents
6
6
  @path = path
7
7
  application_found = application_exists(path)
8
8
  components_found = []
9
+ @component_locations = {}
9
10
  @gem_style_references = []
10
11
  @jquery_references = []
12
+ @helper_references = {}
11
13
 
12
14
  if application_found
13
15
  templates = Dir["#{path}/app/views/**/*.erb"]
@@ -25,15 +27,15 @@ module GovukPublishingComponents
25
27
  @find_all_javascripts = /\/\/ *= require govuk_publishing_components\/all_components/
26
28
  find_javascripts = /(?<=require govuk_publishing_components\/components\/)[a-zA-Z_-]+/
27
29
 
28
- components_in_templates = find_components(templates, find_components, "templates") || []
29
- components_in_stylesheets = find_components(stylesheets, find_stylesheets, "stylesheets") || []
30
- components_in_print_stylesheets = find_components(stylesheets, find_print_stylesheets, "print_stylesheets") || []
31
- components_in_javascripts = find_components(javascripts, find_javascripts, "javascripts") || []
30
+ components_in_templates = find_components(templates, find_components, "templates", true) || []
31
+ components_in_stylesheets = find_components(stylesheets, find_stylesheets, "stylesheets", false) || []
32
+ components_in_print_stylesheets = find_components(stylesheets, find_print_stylesheets, "print_stylesheets", false) || []
33
+ components_in_javascripts = find_components(javascripts, find_javascripts, "javascripts", false) || []
32
34
 
33
35
  ruby_paths = %w[/app/helpers/ /app/presenters/ /lib/]
34
36
  components_in_ruby = []
35
37
  ruby_paths.each do |ruby_path|
36
- components_in_ruby << find_components(Dir["#{path}#{ruby_path}**/*.{rb,erb}"], find_components, "ruby") || []
38
+ components_in_ruby << find_components(Dir["#{path}#{ruby_path}**/*.{rb,erb}"], find_components, "ruby", true) || []
37
39
  end
38
40
  components_in_ruby = components_in_ruby.flatten.uniq
39
41
 
@@ -67,17 +69,35 @@ module GovukPublishingComponents
67
69
  components_found: components_found,
68
70
  gem_style_references: @gem_style_references.flatten.uniq.sort,
69
71
  jquery_references: @jquery_references.flatten.uniq.sort,
72
+ component_locations: @component_locations,
73
+ helper_references: @helper_references,
70
74
  }
71
75
  end
72
76
 
73
77
  private
74
78
 
75
- def find_components(files, find, type)
79
+ def find_components(files, find, type, keep_locations)
76
80
  components_found = []
77
81
 
78
82
  files.each do |file|
79
83
  src = File.read(file)
80
- components_found << find_match(find, src, type)
84
+
85
+ if keep_locations
86
+ components = find_match(find, src, type)
87
+ if components.any?
88
+ components_found << components
89
+ components.each do |component|
90
+ component_sym = component.to_sym
91
+ @component_locations[component_sym] = [] unless @component_locations[component_sym]
92
+ @component_locations[component_sym] << clean_file_path(file)
93
+ @component_locations[component_sym].sort!
94
+ end
95
+ end
96
+ else
97
+ components_found << find_match(find, src, type)
98
+ end
99
+
100
+ get_helper_references(file, src) if %w[ruby templates].include?(type)
81
101
 
82
102
  if type == "javascripts"
83
103
  jquery_references = find_code_references(file, src, /\$\(/)
@@ -93,12 +113,30 @@ module GovukPublishingComponents
93
113
  components_found.flatten.uniq.sort
94
114
  end
95
115
 
116
+ def get_helper_references(file, src)
117
+ helper_use = find_match(/GovukPublishingComponents::(?:AppHelpers|Presenters)::[a-zA-Z]+/, src, "helper")
118
+ if helper_use.any?
119
+ helper_use.each do |helper|
120
+ class_name = helper.gsub(/GovukPublishingComponents::(AppHelpers)?(Presenters)?::+/, "")
121
+ helper_sym = class_name.to_sym
122
+ @helper_references[helper_sym] = [] unless @helper_references[helper_sym]
123
+ @helper_references[helper_sym] << clean_file_path(file)
124
+ @helper_references[helper_sym].uniq!
125
+ @helper_references[helper_sym].sort!
126
+ end
127
+ end
128
+ end
129
+
130
+ # looks for components in the given src of a file
131
+ # returns an array of component names or an empty array
96
132
  def find_match(find, src, type)
97
133
  return %w[all] if src.match(@find_all_stylesheets) && type == "stylesheets"
98
134
  return %w[all] if src.match(@find_all_print_stylesheets) && type == "print_stylesheets"
99
135
  return %w[all] if src.match(@find_all_javascripts) && type == "javascripts"
100
136
 
101
137
  matches = src.scan(find)
138
+ return [] unless matches.any?
139
+
102
140
  all_matches = []
103
141
  matches.each do |match|
104
142
  all_matches << clean_file_name(match.tr('[])\'"', ""))
@@ -108,9 +146,11 @@ module GovukPublishingComponents
108
146
  end
109
147
 
110
148
  def find_code_references(file, src, regex)
111
- clean_file_path = /(?<=#{Regexp.escape(@path.to_s)}\/)[\/a-zA-Z_-]+.[a-zA-Z.]+/
149
+ return clean_file_path(file) if regex.match?(src)
150
+ end
112
151
 
113
- return file[clean_file_path] if regex.match?(src)
152
+ def clean_file_path(file)
153
+ file[/(?<=#{Regexp.escape(@path.to_s)}\/)[\/a-zA-Z_-]+.[a-zA-Z.]+/]
114
154
  end
115
155
 
116
156
  def clean_file_name(name)
@@ -22,6 +22,7 @@ module GovukPublishingComponents
22
22
  @gem_data = gem_data
23
23
  @applications_data = sort_results(results)
24
24
  @gem_data[:components_by_application] = get_components_by_application || []
25
+ @gem_data[:helpers_used_by_applications] = get_helpers_used_by_applications || []
25
26
  end
26
27
  end
27
28
 
@@ -106,6 +107,8 @@ module GovukPublishingComponents
106
107
  warning_count: warnings.length,
107
108
  gem_style_references: result[:gem_style_references],
108
109
  jquery_references: result[:jquery_references],
110
+ component_locations: result[:component_locations],
111
+ helper_references: result[:helper_references],
109
112
  }
110
113
  else
111
114
  data << {
@@ -244,32 +247,67 @@ module GovukPublishingComponents
244
247
  (haystack - needle).flatten.sort
245
248
  end
246
249
 
250
+ # returns details of component inclusion by applications
247
251
  def get_components_by_application
248
252
  results = []
249
253
  found_something = false
250
254
 
251
255
  @gem_data[:component_listing].each do |component|
252
- found_in_applications = []
256
+ component_name = component[:name]
257
+ locations = []
253
258
 
254
259
  @applications_data.each do |application|
255
- next unless application[:application_found]
260
+ next unless application[:application_found] && application[:component_locations][component_name.to_sym]
256
261
 
257
- name = application[:name]
262
+ application_name = application[:name]
258
263
  found_something = true
259
264
 
260
- application[:summary].each do |item|
261
- found_in_applications << name if item[:value].include?(component[:name])
262
- end
265
+ locations << {
266
+ name: application_name,
267
+ locations: application[:component_locations][component_name.to_sym],
268
+ }
263
269
  end
264
270
 
271
+ locations = locations.flatten
272
+
265
273
  results << {
266
- component: component[:name],
267
- count: found_in_applications.uniq.length,
268
- list: found_in_applications.uniq.join(", "),
274
+ name: component_name,
275
+ count: locations.length,
276
+ locations: locations,
269
277
  }
270
278
  end
271
279
 
272
280
  results if found_something
273
281
  end
282
+
283
+ # returns data of components gem helpers used in applications
284
+ def get_helpers_used_by_applications
285
+ results = []
286
+
287
+ @applications_data.each do |application|
288
+ next unless application[:application_found] && !application[:helper_references].blank?
289
+
290
+ application[:helper_references].each do |key, value|
291
+ location = {
292
+ name: application[:name],
293
+ locations: value,
294
+ }
295
+
296
+ match = results.find { |x| x[:name] == key }
297
+ if match
298
+ match[:locations] << location
299
+ match[:count] = match[:count] + 1
300
+ else
301
+ results << {
302
+ name: key,
303
+ count: 1,
304
+ locations: [location],
305
+ }
306
+ end
307
+ end
308
+ end
309
+
310
+ results
311
+ end
274
312
  end
275
313
  end
@@ -56,38 +56,19 @@
56
56
  }
57
57
  %>
58
58
 
59
- <% if @other_applications %>
60
- <% components_by_application = capture do %>
61
- <% if @components[:components_by_application].any? %>
62
- <dl class="govuk-summary-list">
63
- <% @components[:components_by_application].each do |component| %>
64
- <div class="govuk-summary-list__row">
65
- <dt class="govuk-summary-list__key">
66
- <%= component[:component] %> (<%= component[:count] %>)
67
- </dt>
68
- <dd class="govuk-summary-list__value">
69
- <%= component[:list] %>
70
- </dd>
71
- </div>
72
- <% end %>
73
- </dl>
74
- <% end %>
75
- <% end %>
59
+ <%= render 'items_in_applications',
60
+ heading: 'Components by application',
61
+ summary: 'Shows which applications use each component',
62
+ content: @components[:components_by_application],
63
+ items: component_items
64
+ %>
76
65
 
77
- <%
78
- component_items << {
79
- heading: {
80
- text: "Components by application",
81
- },
82
- summary: {
83
- text: "Shows which applications use each component",
84
- },
85
- content: {
86
- html: components_by_application
87
- },
88
- }
89
- %>
90
- <% end %>
66
+ <%= render 'items_in_applications',
67
+ heading: 'Helpers by application',
68
+ summary: 'Shows any applications that use helper classes from the components gem',
69
+ content: @components[:helpers_used_by_applications],
70
+ items: component_items
71
+ %>
91
72
 
92
73
  <%= render "govuk_publishing_components/components/accordion", {
93
74
  items: component_items
@@ -0,0 +1,50 @@
1
+ <% if @other_applications %>
2
+ <% accordion_content = capture do %>
3
+ <% if content.any? %>
4
+ <dl class="govuk-summary-list">
5
+ <% content.each do |item| %>
6
+ <div class="govuk-summary-list__row">
7
+ <dt class="govuk-summary-list__key">
8
+ <%= item[:name] %> (<%= pluralize(item[:count], 'use') %>)
9
+ </dt>
10
+ <dd class="govuk-summary-list__value">
11
+ <% item[:locations].each do |application| %>
12
+ <% github_link = 'https://github.com/alphagov/' + application[:name] + '/blob/main/' %>
13
+ <details class="govuk-details govuk-!-margin-bottom-2" data-module="govuk-details">
14
+ <summary class="govuk-details__summary">
15
+ <span class="govuk-details__summary-text">
16
+ <%= application[:name] %> (<%= application[:locations].length %>)
17
+ </span>
18
+ </summary>
19
+ <div class="govuk-details__text">
20
+ <ul class="govuk-list govuk-list--bullet">
21
+ <% application[:locations].each do |location| %>
22
+ <li>
23
+ <a href="<%= github_link %><%= location %>" class="govuk-link"><%= location %></a>
24
+ </li>
25
+ <% end %>
26
+ </ul>
27
+ </div>
28
+ </details>
29
+ <% end %>
30
+ </dd>
31
+ </div>
32
+ <% end %>
33
+ </dl>
34
+ <% end %>
35
+ <% end %>
36
+
37
+ <%
38
+ items << {
39
+ heading: {
40
+ text: heading,
41
+ },
42
+ summary: {
43
+ text: summary,
44
+ },
45
+ content: {
46
+ html: accordion_content
47
+ },
48
+ }
49
+ %>
50
+ <% end %>
@@ -13,10 +13,11 @@
13
13
  %>
14
14
 
15
15
  <% @table = capture do %>
16
- <%= GovukPublishingComponents::AppHelpers::TableHelper.helper(self, caption, table_id, {
16
+ <%= GovukPublishingComponents::AppHelpers::TableHelper.helper(self, caption, {
17
17
  sortable: sortable,
18
18
  filterable: filterable,
19
- caption_classes: caption_classes
19
+ caption_classes: caption_classes,
20
+ table_id: table_id
20
21
  }) do |t| %>
21
22
 
22
23
  <% if head.any? %>
@@ -18,4 +18,4 @@ examples:
18
18
  data:
19
19
  href: '#'
20
20
  data_attributes:
21
- tracking: GT-1234
21
+ an_attribute: the value
@@ -36,8 +36,8 @@ examples:
36
36
  with_data_attributes:
37
37
  description: |
38
38
  If a `href` attribute is present, `data_attributes` will apply to the `span` containing the number value (see below).
39
-
40
- This will also not automatically apply a `gem-track-click` module attribute if the data attributes pertain to click tracking. Remember to apply this outside the component call in a surrounding element, if using.
39
+
40
+ 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).
41
41
  data:
42
42
  number: 23
43
43
  label: Ministerial departments
@@ -2,9 +2,9 @@ name: "Breadcrumbs"
2
2
  description: "Navigational breadcrumbs, showing page hierarchy"
3
3
  body: |
4
4
  Accepts an array of breadcrumb objects. Each crumb must have a title and a URL.
5
- Links have tracking data but links to the homepage (any link with a url of `/`) will be tracked separately as `homeLinkClicked`
5
+ Links have tracking data but links to the homepage (any link with a url of `/`) will be tracked separately as `homeLinkClicked`.
6
6
 
7
- We recommend that if using the breadcrumbs for navigation purposes, you set `collapse_on_mobile` to `true` to make things more readable for mobile users. However, you can specify `collapse_on_mobile:``false` or remove the flag completely to stop this behaviour.
7
+ We recommend that if using the breadcrumbs for navigation purposes, you set `collapse_on_mobile` to `true` to make things more readable for mobile users. However, you can specify `collapse_on_mobile:``false` or remove the flag completely to stop this behaviour.
8
8
  shared_accessibility_criteria:
9
9
  - link
10
10
  accessibility_criteria: