govuk_publishing_components 35.1.1 → 35.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (25) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/component_guide/application.js +1 -0
  3. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-core.js +34 -4
  4. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-link-tracker.js +20 -2
  5. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/init-ga4.js +5 -0
  6. data/app/assets/javascripts/govuk_publishing_components/components/intervention.js +69 -0
  7. data/app/assets/javascripts/govuk_publishing_components/components/step-by-step-nav.js +5 -2
  8. data/app/assets/javascripts/govuk_publishing_components/lib/cookie-functions.js +1 -0
  9. data/app/assets/javascripts/govuk_publishing_components/vendor/lux/lux-reporter.js +430 -313
  10. data/app/assets/stylesheets/govuk_publishing_components/components/_layout-super-navigation-header.scss +2 -3
  11. data/app/controllers/govuk_publishing_components/component_guide_controller.rb +1 -1
  12. data/app/models/govuk_publishing_components/audit_applications.rb +5 -1
  13. data/app/models/govuk_publishing_components/audit_comparer.rb +4 -4
  14. data/app/views/govuk_publishing_components/audit/_applications.html.erb +22 -4
  15. data/app/views/govuk_publishing_components/components/_accordion.html.erb +25 -1
  16. data/app/views/govuk_publishing_components/components/_intervention.html.erb +15 -7
  17. data/app/views/govuk_publishing_components/components/_layout_super_navigation_header.html.erb +19 -5
  18. data/app/views/govuk_publishing_components/components/_step_by_step_nav.html.erb +23 -3
  19. data/app/views/govuk_publishing_components/components/_step_by_step_nav_related.html.erb +24 -4
  20. data/app/views/govuk_publishing_components/components/docs/intervention.yml +11 -6
  21. data/lib/govuk_publishing_components/presenters/component_wrapper_helper.rb +35 -12
  22. data/lib/govuk_publishing_components/presenters/intervention_helper.rb +16 -5
  23. data/lib/govuk_publishing_components/presenters/step_by_step_nav_helper.rb +0 -16
  24. data/lib/govuk_publishing_components/version.rb +1 -1
  25. metadata +5 -4
@@ -2,7 +2,6 @@
2
2
  @import "mixins/prefixed-transform";
3
3
  @import "mixins/grid-helper";
4
4
 
5
- $icon-size: 20px;
6
5
  $chevron-indent-spacing: 7px;
7
6
  $black-bar-height: 50px;
8
7
  $search-width-or-height: $black-bar-height;
@@ -343,9 +342,9 @@ $after-button-padding-left: govuk-spacing(4);
343
342
 
344
343
  .gem-c-layout-super-navigation-header__search-item-link-icon,
345
344
  .gem-c-layout-super-navigation-header__search-toggle-button-link-icon {
346
- height: $icon-size;
345
+ height: 20px;
347
346
  pointer-events: none;
348
- width: $icon-size;
347
+ width: 21px;
349
348
  }
350
349
 
351
350
  // Search and popular content dropdown.
@@ -2,7 +2,7 @@ module GovukPublishingComponents
2
2
  class ComponentGuideController < GovukPublishingComponents::ApplicationController
3
3
  append_view_path File.join(Rails.root, "app", "views", GovukPublishingComponents::Config.component_directory_name)
4
4
 
5
- MATCH_COMPONENTS = /(?<=govuk_publishing_components\/components\/)[\/a-zA-Z_-]+(?=['"])/.freeze
5
+ MATCH_COMPONENTS = /(?<=govuk_publishing_components\/components\/)[\/a-zA-Z_-]+(?=['"])/
6
6
 
7
7
  def index
8
8
  @application_path = Rails.root
@@ -18,7 +18,9 @@ module GovukPublishingComponents
18
18
 
19
19
  find_components = /(?<=govuk_publishing_components\/components\/)[a-zA-Z_-]+(?=['"])/
20
20
 
21
- @find_all_stylesheets = /@import ["']{1}govuk_publishing_components\/all_components/
21
+ @find_all_stylesheets = /@import ["']{1}govuk_publishing_components\/all_components/ # if using the all stylesheets option
22
+ @find_individual_asset_model = /render_component_stylesheets/ # if using per page component asset loading
23
+ @uses_individual_asset_model = false
22
24
  find_stylesheets = /(?<=@import ["']{1}govuk_publishing_components\/components\/)(?!print\/)+[a-zA-Z_-]+(?=['"])/
23
25
 
24
26
  @find_all_javascripts = /\/\/ *= require govuk_publishing_components\/all_components/
@@ -63,6 +65,7 @@ module GovukPublishingComponents
63
65
  jquery_references: @jquery_references.flatten.uniq.sort,
64
66
  component_locations: @component_locations,
65
67
  helper_references: @helper_references,
68
+ uses_individual_asset_model: @uses_individual_asset_model,
66
69
  }
67
70
  end
68
71
 
@@ -125,6 +128,7 @@ module GovukPublishingComponents
125
128
  return %w[all] if src.match(@find_all_stylesheets) && type == "stylesheet"
126
129
  return %w[all] if src.match(@find_all_javascripts) && type == "javascript"
127
130
 
131
+ @uses_individual_asset_model = true if src.match(@find_individual_asset_model) && type == "template"
128
132
  matches = src.scan(find)
129
133
  return [] unless matches.any?
130
134
 
@@ -54,15 +54,13 @@ module GovukPublishingComponents
54
54
 
55
55
  results.each do |result|
56
56
  if result[:application_found]
57
+ @current_uses_individual_asset_model = result[:uses_individual_asset_model]
57
58
  application_uses_static = @applications_using_static.include?(result[:name])
58
59
  templates = result[:components_found].find { |c| c[:location] == "template" }
59
60
  stylesheets = result[:components_found].find { |c| c[:location] == "stylesheet" }
60
61
  javascripts = result[:components_found].find { |c| c[:location] == "javascript" }
61
62
  ruby = result[:components_found].find { |c| c[:location] == "ruby" }
62
63
 
63
- @all_stylesheets = true if stylesheets[:components].include?("all")
64
- @all_javascripts = true if javascripts[:components].include?("all")
65
-
66
64
  templates[:components] = include_any_components_within_components(templates[:components])
67
65
 
68
66
  warnings = []
@@ -103,6 +101,7 @@ module GovukPublishingComponents
103
101
  jquery_references: result[:jquery_references],
104
102
  component_locations: result[:component_locations],
105
103
  helper_references: result[:helper_references],
104
+ uses_individual_asset_model: result[:uses_individual_asset_model],
106
105
  }
107
106
  else
108
107
  data << {
@@ -161,7 +160,8 @@ module GovukPublishingComponents
161
160
 
162
161
  check_static = @static_data && second_location != "code"
163
162
  asset_in_static = asset_already_in_static(second_location, component) if check_static
164
- raise_warning = asset_in_gem && !asset_in_static
163
+ suppress_warning = @current_uses_individual_asset_model && second_location == "stylesheet"
164
+ raise_warning = asset_in_gem && !asset_in_static && !suppress_warning
165
165
 
166
166
  # this raises a warning if the asset exists and isn't included either in the application or static
167
167
  warnings << create_warning(component, "Included in #{first_location} but not #{second_location}") if raise_warning
@@ -37,8 +37,24 @@
37
37
  <% github_link = 'https://github.com/alphagov/' + application[:name] + '/blob/main/' %>
38
38
 
39
39
  <% if @other_applications %>
40
+ <% if application[:uses_individual_asset_model] %>
41
+ <div class="govuk-warning-text">
42
+ <span class="govuk-warning-text__icon" aria-hidden="true">!</span>
43
+ <strong class="govuk-warning-text__text">
44
+ <span class="govuk-warning-text__assistive">Warning</span>
45
+ This application uses <a class="govuk-link" href="https://github.com/alphagov/govuk_publishing_components/blob/main/docs/set-up-individual-component-css-loading.md">per page asset loading</a> for components. Warnings about missing stylesheets have been suppressed.
46
+ </strong>
47
+ </div>
48
+ <% end %>
49
+
40
50
  <% if application[:uses_static] %>
41
- <p class="govuk-body">This application uses <a href="https://github.com/alphagov/static" class="govuk-link">static</a>, which can contain assets for components used in more than one application. Warnings for missing component assets in this application that are already included in static have been suppressed.</p>
51
+ <div class="govuk-warning-text">
52
+ <span class="govuk-warning-text__icon" aria-hidden="true">!</span>
53
+ <strong class="govuk-warning-text__text">
54
+ <span class="govuk-warning-text__assistive">Warning</span>
55
+ This application uses <a href="https://github.com/alphagov/static" class="govuk-link">static</a>, which can contain assets for components used in more than one application. Warnings for missing component assets in this application that are already included in static have been suppressed.
56
+ </strong>
57
+ </div>
42
58
  <% end %>
43
59
 
44
60
  <% application[:warnings].each do |warning| %>
@@ -67,6 +83,8 @@
67
83
  <dd class="govuk-summary-list__value">
68
84
  <% if item[:value].length > 0 %>
69
85
  <%= item[:value].join(", ") %>
86
+ <% elsif application[:uses_individual_asset_model] && item[:name] == "In stylesheets" %>
87
+ Uses per page component asset loading
70
88
  <% else %>
71
89
  None
72
90
  <% end %>
@@ -77,13 +95,13 @@
77
95
 
78
96
  <% if application[:gem_style_references].any? %>
79
97
  <%= render "govuk_publishing_components/components/heading", {
80
- text: "Component references",
98
+ text: "Component references (#{application[:gem_style_references].length})",
81
99
  font_size: "m",
82
100
  margin_bottom: 4,
83
101
  heading_level: 3,
84
102
  } %>
85
103
 
86
- <p class="govuk-body">This shows instances of `gem-c-` classes found in the application. If a reference is found in a stylesheet or in code a warning is created, as this could be a style override or hard coded component markup.</p>
104
+ <p class="govuk-body">This shows instances of `gem-c-` classes found in the application. This could be a style override or hard coded component markup, which is a violation of our principle of <a href="https://github.com/alphagov/govuk_publishing_components/blob/main/docs/component_principles.md#a-component-is-isolated-when" class="govuk-link">component isolation</a>.</p>
87
105
  <ul class="govuk-list govuk-list--bullet">
88
106
  <% application[:gem_style_references].each do |ref| %>
89
107
  <li>
@@ -95,7 +113,7 @@
95
113
 
96
114
  <% if application[:jquery_references].any? %>
97
115
  <%= render "govuk_publishing_components/components/heading", {
98
- text: "jQuery references",
116
+ text: "jQuery references (#{application[:jquery_references].length})",
99
117
  font_size: "m",
100
118
  margin_bottom: 4,
101
119
  heading_level: 3,
@@ -37,6 +37,7 @@
37
37
  index = i + 1
38
38
 
39
39
  item[:data_attributes] ||= nil
40
+ ga4_link_data_attributes ||= nil
40
41
 
41
42
  if ga4_tracking
42
43
  item[:data_attributes] ||= {}
@@ -49,6 +50,23 @@
49
50
  index_section_count: items.length,
50
51
  },
51
52
  }.to_json
53
+
54
+ # These attributes have been created separately from the item[:data_attributes]
55
+ # object in order to keep them from colliding with GA4 event tracking and UA
56
+ # tracking attributes
57
+ ga4_link_data_attributes = {}
58
+ ga4_link_data_attributes[:module] = "ga4-link-tracker"
59
+ ga4_link_data_attributes[:ga4_tracks_links_only] = ""
60
+ ga4_link_data_attributes[:ga4_set_indexes] = ""
61
+ ga4_link_data_attributes[:ga4_link] = {
62
+ event_name: "navigation",
63
+ type: "accordion",
64
+ section: item[:heading][:text],
65
+ index: {
66
+ index_section: index,
67
+ index_section_count: (items.length),
68
+ }
69
+ }.to_json
52
70
  end
53
71
 
54
72
  section_classes = %w(govuk-accordion__section)
@@ -74,7 +92,13 @@
74
92
  %>
75
93
  <%= tag.div(item[:summary][:text], id: "#{id}-summary-#{index}", class: summary_classes) if item[:summary].present? %>
76
94
  <% end %>
77
- <%= tag.div(item[:content][:html], id: "#{id}-content-#{index}", class: "govuk-accordion__section-content", 'aria-labelledby': "#{id}-heading-#{index}") %>
95
+ <%= tag.div(
96
+ item[:content][:html],
97
+ id: "#{id}-content-#{index}",
98
+ class: "govuk-accordion__section-content",
99
+ 'aria-labelledby': "#{id}-heading-#{index}",
100
+ data: ga4_link_data_attributes
101
+ ) %>
78
102
  <% end %>
79
103
  <% end %>
80
104
  <% end %>
@@ -1,6 +1,7 @@
1
1
  <%
2
2
  add_gem_component_stylesheet("intervention")
3
3
 
4
+ name ||= ""
4
5
  dismiss_text ||= false
5
6
  suggestion_link_text ||= false
6
7
  suggestion_link_url ||= false
@@ -10,16 +11,23 @@
10
11
 
11
12
  data_attributes ||= {}
12
13
  suggestion_data_attributes ||= {}
13
- dismiss_data_attributes ||= {}
14
+ data_attributes[:module] = "intervention"
15
+ data_attributes["intervention-name"] = name
14
16
 
15
17
  aria_attributes ||= {}
16
18
  aria_attributes[:label] = 'Intervention'
17
19
 
18
- local_assigns[:query_string] ||= request.query_string
19
- local_assigns[:suggestion_link_text] = suggestion_link_text
20
- local_assigns[:suggestion_link_url] = suggestion_link_url
20
+ options = {
21
+ name: name,
22
+ dismiss_text: dismiss_text,
23
+ params: request.params,
24
+ query_string: request.query_string,
25
+ suggestion_text: suggestion_text,
26
+ suggestion_link_text: suggestion_link_text,
27
+ suggestion_link_url: suggestion_link_url,
28
+ }
21
29
 
22
- intervention_helper = GovukPublishingComponents::Presenters::InterventionHelper.new(local_assigns)
30
+ intervention_helper = GovukPublishingComponents::Presenters::InterventionHelper.new(options)
23
31
  dismiss_href = intervention_helper.dismiss_link
24
32
 
25
33
  suggestion_tag_options = {
@@ -44,7 +52,7 @@
44
52
  }
45
53
  section_options.merge!({ hidden: true }) if hide
46
54
  %>
47
- <% if suggestion_text || (suggestion_link_text && suggestion_link_url) %>
55
+ <% if intervention_helper.show? %>
48
56
  <%= tag.section **section_options do %>
49
57
  <p class="govuk-body">
50
58
  <%= tag.span suggestion_text, class: "gem-c-intervention__textwrapper" if suggestion_text %>
@@ -55,7 +63,7 @@
55
63
 
56
64
  <% if dismiss_text %>
57
65
  <p class="govuk-body">
58
- <%= tag.a class: "govuk-link", href: dismiss_href, data: dismiss_data_attributes do %>
66
+ <%= tag.a class: "govuk-link js-dismiss-link", href: dismiss_href do %>
59
67
  <svg class="gem-c-intervention__dismiss-icon"
60
68
  width="19" height="19" viewBox="0 0 19 19"
61
69
  aria-hidden="true"
@@ -43,7 +43,9 @@
43
43
  "external": "false",
44
44
  "text": "GOV.UK",
45
45
  "section": "Logo",
46
- "index": 0,
46
+ "index": {
47
+ "index_section": 0,
48
+ },
47
49
  "index_total": navigation_links_length
48
50
  }.to_json %>"
49
51
  >
@@ -128,7 +130,9 @@
128
130
  event_name: "select_content",
129
131
  type: "header menu bar",
130
132
  text: link[:label],
131
- index: 1,
133
+ index: {
134
+ index_section: 1,
135
+ },
132
136
  index_total: 2,
133
137
  section: link[:label]
134
138
  }
@@ -159,7 +163,9 @@
159
163
  "event_name": "select_content",
160
164
  "type": "header menu bar",
161
165
  "text": "Search",
162
- "index": 2,
166
+ "index": {
167
+ "index_section": 2,
168
+ },
163
169
  "index_total": 2,
164
170
  "section": "Search"
165
171
  }.to_json %>"
@@ -238,7 +244,11 @@
238
244
  ga4_link: {
239
245
  "event_name": "navigation",
240
246
  "type": "header menu bar",
241
- "index": "1.#{column_index + 1}.#{index + 1}",
247
+ "index": {
248
+ "index_section": column_index + 1,
249
+ "index_link": index + 1,
250
+ "index_section_count": 4,
251
+ },
242
252
  "index_total": navigation_links_length,
243
253
  "section": column[:label],
244
254
  }
@@ -308,7 +318,11 @@
308
318
  ga4_link: {
309
319
  "event_name": "navigation",
310
320
  "type": "header menu bar",
311
- "index": "2.2.#{index + 1}",
321
+ "index": {
322
+ "index_section": 4,
323
+ "index_link": index + 1,
324
+ "index_section_count": 4,
325
+ },
312
326
  "index_total": navigation_links_length,
313
327
  "section": popular_links_heading,
314
328
  }
@@ -22,7 +22,7 @@
22
22
  %>
23
23
  <% if steps %>
24
24
  <div
25
- data-module="gemstepnav<% if ga4_tracking %> ga4-event-tracker ga4-link-tracker<% end %>"
25
+ data-module="gemstepnav<% if ga4_tracking %> ga4-event-tracker<% end %>"
26
26
  <%= "data-ga4-expandable" if ga4_tracking %>
27
27
  class="gem-c-step-nav js-hidden <% if small %>govuk-!-display-none-print<% end %> <% unless small %>gem-c-step-nav--large<% end %>"
28
28
  <%= "data-remember" if remember_last_step %>
@@ -73,7 +73,27 @@
73
73
  <% end %>
74
74
  </div>
75
75
 
76
- <div class="gem-c-step-nav__panel js-panel" id="step-panel-<%= id %>-<%= step_index + 1 %>">
76
+ <%
77
+ ga4_link_data = {}
78
+
79
+ if ga4_tracking
80
+ ga4_link_data = {
81
+ "module": "ga4-link-tracker",
82
+ "ga4-track-links-only": "",
83
+ "ga4-set-indexes": "",
84
+ "ga4-link": {
85
+ "event_name": "navigation",
86
+ "type": "step by step",
87
+ "index": {
88
+ "index_section": step_index + 1
89
+ },
90
+ "section": step[:title]
91
+ }.to_json
92
+ }
93
+ end
94
+ %>
95
+
96
+ <%= tag.div(class: "gem-c-step-nav__panel js-panel", id: "step-panel-#{id}-#{step_index + 1}", data: ga4_link_data) do %>
77
97
  <%
78
98
  in_substep = false
79
99
  options[:step_nav_content_id] = step_nav_content_id
@@ -91,7 +111,7 @@
91
111
  end
92
112
  %>
93
113
  <% end %>
94
- </div>
114
+ <% end %>
95
115
 
96
116
  </li>
97
117
  <% end %>
@@ -23,8 +23,18 @@
23
23
  data-track-dimension="<%= links[0][:text] %>"
24
24
  data-track-dimension-index="29"
25
25
  data-track-options='{"dimension96" : "<%= links[0][:tracking_id] %>" }'
26
- <% if ga4_tracking %>
27
- data-ga4-link='{"event_name":"navigation", "type":"related content", "index":{"index_link": "1"}, "index_total":"1"}'
26
+ <% if ga4_tracking
27
+ ga4_attributes = {
28
+ event_name: "navigation",
29
+ type: "related content",
30
+ index:{
31
+ "index_link": "1"
32
+ },
33
+ index_total: "1",
34
+ section: "Part of",
35
+ }.to_json
36
+ %>
37
+ data-ga4-link="<%= ga4_attributes %>"
28
38
  <% end %>
29
39
  >
30
40
  <%= links[0][:text] %>
@@ -43,8 +53,18 @@
43
53
  data-track-dimension="<%= link[:text] %>"
44
54
  data-track-dimension-index="29"
45
55
  data-track-options='{"dimension96" : "<%= link[:tracking_id] %>" }'
46
- <% if ga4_tracking %>
47
- data-ga4-link='{"event_name":"navigation", "type":"related content", "index":{"index_link": "<%= index + 1 %>"}, "index_total": "<%= links.length %>"}'
56
+ <% if ga4_tracking
57
+ ga4_attributes = {
58
+ event_name: "navigation",
59
+ type: "related content",
60
+ index:{
61
+ "index_link": (index + 1).to_s
62
+ },
63
+ index_total: (links.length).to_s,
64
+ section: "Part of",
65
+ }.to_json
66
+ %>
67
+ data-ga4-link="<%= ga4_attributes %>"
48
68
  <% end %>
49
69
  >
50
70
  <%= link[:text] %>
@@ -6,7 +6,10 @@ body: |
6
6
  that would be useful to them. This component would be used to add this personalised content and would
7
7
  indicate to the user that this is not normally part of the page, but has been added for them specifically.
8
8
 
9
- The dismiss link points to the current URL with the "hide-intervention" query string parameter set to "true". The backend should check for this string in order to render the same page without the intervention.
9
+ The dismiss link works without Javascript by pointing to the current URL with the "hide-intervention"
10
+ query string parameter set to "true". It's progressively enhanced and sets a cookie to remember that
11
+ the user has dismissed the banner before. The cookie requires a "name" parameter, the value of which
12
+ is stored in the cookie to distinguish which campaign banner the user has dismissed.
10
13
 
11
14
  accessibility_criteria: |
12
15
  The intervention component must:
@@ -30,20 +33,20 @@ examples:
30
33
  suggestion_link_url: /travel-abroad
31
34
 
32
35
  with_dismiss_link:
36
+ description: |
37
+ Name is required in order to set a cookie. The name value should be distinct to the campaign for the banner,
38
+ so that other banners using this component are not hidden by accident.
33
39
  data:
34
40
  suggestion_text: You should renew your permit every 6 months.
35
41
  dismiss_text: Hide this suggestion
36
-
37
- with_suggestion_link_only:
38
- data:
39
- suggestion_link_text: You can now apply for a permit online.
40
- suggestion_link_url: /permit
42
+ name: campaign-name
41
43
 
42
44
  with_hide:
43
45
  description: |
44
46
  This example is for when we want to hide by default and display to the user based on some logic,
45
47
  either in the backend or with Javascript.
46
48
  data:
49
+ suggestion_text: You should renew your permit every 6 months.
47
50
  suggestion_link_text: You may be invited to fill in a questionnaire
48
51
  suggestion_link_url: /questionnaire
49
52
  hide: true
@@ -55,6 +58,7 @@ examples:
55
58
  Link text should tell the user that the link opens in a new tab.
56
59
  Note: "(opens in a new tab)" is added to link text if the phrase isn't included.
57
60
  data:
61
+ suggestion_text: You should renew your permit every 6 months.
58
62
  suggestion_link_text: You can now apply for a permit online
59
63
  suggestion_link_url: www.google.com/permit
60
64
  new_tab: true
@@ -76,6 +80,7 @@ examples:
76
80
  track-dimension-index: 29
77
81
  track-label: clicked suggestion
78
82
  dismiss_text: Hide this suggestion
83
+ name: another-campaign-name
79
84
  dismiss_data_attributes:
80
85
  track-category: interventionBanner
81
86
  track-action: interventionDismissed
@@ -5,6 +5,7 @@ module GovukPublishingComponents
5
5
  @options = options
6
6
 
7
7
  check_id_is_valid(@options[:id]) if @options.include?(:id)
8
+ check_data_attributes_are_valid(@options[:data_attributes]) if @options.include?(:data_attributes)
8
9
  check_classes_are_valid(@options[:classes]) if @options.include?(:classes)
9
10
  check_aria_is_valid(@options[:aria]) if @options.include?(:aria)
10
11
  check_role_is_valid(@options[:role]) if @options.include?(:role)
@@ -13,11 +14,11 @@ module GovukPublishingComponents
13
14
  def all_attributes
14
15
  attributes = {}
15
16
 
16
- attributes[:id] = @options[:id] if @options[:id]
17
- attributes[:data] = @options[:data_attributes] if @options[:data_attributes]
18
- attributes[:aria] = @options[:aria] if @options[:aria]
19
- attributes[:class] = @options[:classes] if @options[:classes]
20
- attributes[:role] = @options[:role] if @options[:role]
17
+ attributes[:id] = @options[:id] unless @options[:id].blank?
18
+ attributes[:data] = @options[:data_attributes] unless @options[:data_attributes].blank?
19
+ attributes[:aria] = @options[:aria] unless @options[:aria].blank?
20
+ attributes[:class] = @options[:classes] unless @options[:classes].blank?
21
+ attributes[:role] = @options[:role] unless @options[:role].blank?
21
22
 
22
23
  attributes
23
24
  end
@@ -33,6 +34,7 @@ module GovukPublishingComponents
33
34
  end
34
35
 
35
36
  def add_data_attribute(attributes)
37
+ check_data_attributes_are_valid(attributes)
36
38
  extend_object(:data_attributes, attributes)
37
39
  end
38
40
 
@@ -49,29 +51,50 @@ module GovukPublishingComponents
49
51
  private
50
52
 
51
53
  def check_id_is_valid(id)
52
- raise(ArgumentError, "Id cannot start with a number or contain whitespace and can only contain letters, digits, `_` and `-`") unless /^[a-zA-Z][\w:-]*$/.match?(id)
54
+ return if id.blank?
55
+
56
+ raise(ArgumentError, "Id (#{id}) cannot start with a number or contain whitespace and can only contain letters, digits, `_` and `-`") unless /^[a-zA-Z][\w:-]*$/.match?(id)
57
+ end
58
+
59
+ def check_data_attributes_are_valid(attributes)
60
+ return if attributes.blank?
61
+
62
+ attributes_keys = attributes.map { |key, _| key.to_s }
63
+ invalid_attributes = attributes_keys.map { |a| a if /^(xml)/.match?(a) || /[A-Z :]+/.match?(a) }.compact
64
+
65
+ raise(ArgumentError, "Data attributes (#{invalid_attributes.join(', ')}) cannot contain capitals, spaces or colons, or start with 'xml'") if invalid_attributes.any?
53
66
  end
54
67
 
55
68
  def check_classes_are_valid(classes)
56
- classes = classes.split(" ")
57
- unless classes.all? { |c| c.start_with?("js-", "gem-c-", "govuk-", "brand--") }
58
- raise(ArgumentError, "Passed classes must be prefixed with `js-`")
69
+ return if classes.blank?
70
+
71
+ class_array = classes.split(" ")
72
+ unless class_array.all? { |c| c.start_with?("js-", "gem-c-", "govuk-", "brand--") }
73
+ raise(ArgumentError, "Classes (#{classes}) must be prefixed with `js-`")
59
74
  end
60
75
  end
61
76
 
62
77
  def check_aria_is_valid(attributes)
78
+ return if attributes.blank?
79
+
63
80
  arias = %w[activedescendant atomic autocomplete busy checked colcount colindex colspan controls current describedby description details disabled dropeffect errormessage expanded flowto grabbed haspopup hidden invalid keyshortcuts label labelledby level live modal multiline multiselectable orientation owns placeholder posinset pressed readonly relevant required roledescription rowcount rowindex rowspan selected setsize sort valuemax valuemin valuenow valuetext]
64
81
 
65
- unless attributes.all? { |key, _value| arias.include? key.to_s }
66
- raise(ArgumentError, "Aria attribute is not recognised")
82
+ # array keys are immutable so we have to do this to make a copy, in order to
83
+ # subtract valid aria attributes from invalid in the error message below
84
+ attributes_keys = attributes.map { |key, _| key.to_s }
85
+
86
+ unless attributes_keys.all? { |key| arias.include? key }
87
+ raise(ArgumentError, "Aria attribute (#{(attributes_keys - arias).join(', ')}) not recognised")
67
88
  end
68
89
  end
69
90
 
70
91
  def check_role_is_valid(role)
92
+ return if role.blank?
93
+
71
94
  roles = %w[alert alertdialog application article associationlist associationlistitemkey associationlistitemvalue banner blockquote caption cell code columnheader combobox complementary contentinfo definition deletion dialog directory document emphasis feed figure form group heading img insertion list listitem log main marquee math menu menubar meter navigation none note paragraph presentation region row rowgroup rowheader scrollbar search searchbox separator separator slider spinbutton status strong subscript superscript switch tab table tablist tabpanel term time timer toolbar tooltip tree treegrid treeitem]
72
95
  role = role.split(" ") # can have more than one role
73
96
  unless role.all? { |r| roles.include? r }
74
- raise(ArgumentError, "Role attribute is not recognised")
97
+ raise(ArgumentError, "Role attribute (#{(role - roles).join(', ')}) is not recognised")
75
98
  end
76
99
  end
77
100
 
@@ -1,11 +1,15 @@
1
1
  module GovukPublishingComponents
2
2
  module Presenters
3
3
  class InterventionHelper
4
- def initialize(local_assigns)
4
+ def initialize(options = {})
5
+ @name = options[:name]
6
+ @dismiss_text = options[:dismiss_text]
5
7
  @accessible_text_suffix = I18n.t("components.intervention.accessible_link_text_suffix")
6
- @query_string = local_assigns[:query_string]
7
- @suggestion_link_text = local_assigns[:suggestion_link_text]
8
- @suggestion_link_url = local_assigns[:suggestion_link_url]
8
+ @params = options[:params]
9
+ @query_string = options[:query_string]
10
+ @suggestion_text = options[:suggestion_text]
11
+ @suggestion_link_text = options[:suggestion_link_text]
12
+ @suggestion_link_url = options[:suggestion_link_url]
9
13
  end
10
14
 
11
15
  def accessible_text
@@ -29,9 +33,16 @@ module GovukPublishingComponents
29
33
  rel
30
34
  end
31
35
 
36
+ def show?
37
+ return false if params["hide-intervention"] == "true"
38
+ return false if @dismiss_text && @name.blank?
39
+
40
+ @suggestion_text || (@suggestion_link_text && @suggestion_link_url)
41
+ end
42
+
32
43
  private
33
44
 
34
- attr_reader :accessible_text_suffix, :query_string, :suggestion_link_text, :suggestion_link_url
45
+ attr_reader :accessible_text_suffix, :query_string, :params, :suggestion_text, :suggestion_link_text, :suggestion_link_url
35
46
  end
36
47
  end
37
48
  end
@@ -46,7 +46,6 @@ module GovukPublishingComponents
46
46
  :li,
47
47
  class: "gem-c-step-nav__list-item js-list-item #{link_active(contents[:active])}",
48
48
  ) do
49
- @options[:ga4_index_total] = element[:contents].length if @options[:ga4_tracking]
50
49
  create_list_item_content(contents)
51
50
  end,
52
51
  )
@@ -65,26 +64,11 @@ module GovukPublishingComponents
65
64
  concat create_context(link[:context])
66
65
  end
67
66
 
68
- ga4_link_data ||= nil
69
- if @options[:ga4_tracking]
70
- ga4_link_data = {
71
- "event_name": "navigation",
72
- "type": "step by step",
73
- "index": {
74
- "index_section": (@options[:step_index] + 1).to_s,
75
- "index_link": @link_index.to_s,
76
- },
77
- "index_total": @options[:ga4_index_total].to_s,
78
- "section": @options[:step_title],
79
- }.to_json
80
- end
81
-
82
67
  link_to(
83
68
  href,
84
69
  rel: ("external" if href.start_with?("http")),
85
70
  data: {
86
71
  position: "#{@options[:step_index] + 1}.#{@link_index}",
87
- ga4_link: ga4_link_data,
88
72
  },
89
73
  class: "gem-c-step-nav__link js-link",
90
74
  ) do
@@ -1,3 +1,3 @@
1
1
  module GovukPublishingComponents
2
- VERSION = "35.1.1".freeze
2
+ VERSION = "35.3.0".freeze
3
3
  end