govuk_publishing_components 29.15.0 → 29.15.3

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 (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: