govuk_publishing_components 21.27.1 → 21.28.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +9 -9
  3. data/app/assets/stylesheets/govuk_publishing_components/components/_previous-and-next-navigation.scss +17 -2
  4. data/app/controllers/govuk_publishing_components/component_guide_controller.rb +6 -6
  5. data/app/models/govuk_publishing_components/component_doc.rb +1 -1
  6. data/app/models/govuk_publishing_components/component_docs.rb +2 -2
  7. data/app/models/govuk_publishing_components/component_example.rb +4 -4
  8. data/app/views/govuk_publishing_components/components/_input.html.erb +11 -0
  9. data/app/views/govuk_publishing_components/components/_previous_and_next_navigation.html.erb +2 -2
  10. data/app/views/govuk_publishing_components/components/docs/button.yml +9 -1
  11. data/app/views/govuk_publishing_components/components/docs/input.yml +7 -0
  12. data/config/routes.rb +5 -5
  13. data/lib/generators/govuk_publishing_components/component_generator.rb +7 -7
  14. data/lib/govuk_publishing_components.rb +2 -2
  15. data/lib/govuk_publishing_components/app_helpers/taxon_breadcrumbs.rb +1 -1
  16. data/lib/govuk_publishing_components/engine.rb +1 -1
  17. data/lib/govuk_publishing_components/minitest/component_guide_test.rb +4 -4
  18. data/lib/govuk_publishing_components/presenters/breadcrumbs.rb +9 -9
  19. data/lib/govuk_publishing_components/presenters/button_helper.rb +20 -10
  20. data/lib/govuk_publishing_components/presenters/checkboxes_helper.rb +2 -2
  21. data/lib/govuk_publishing_components/presenters/content_breadcrumbs_based_on_parent.rb +1 -1
  22. data/lib/govuk_publishing_components/presenters/content_breadcrumbs_based_on_taxons.rb +3 -3
  23. data/lib/govuk_publishing_components/presenters/contents_list_helper.rb +5 -5
  24. data/lib/govuk_publishing_components/presenters/contextual_navigation.rb +5 -5
  25. data/lib/govuk_publishing_components/presenters/curated_taxonomy_sidebar_links.rb +5 -5
  26. data/lib/govuk_publishing_components/presenters/image_card_helper.rb +3 -3
  27. data/lib/govuk_publishing_components/presenters/machine_readable/article_schema.rb +1 -1
  28. data/lib/govuk_publishing_components/presenters/machine_readable/creative_work_schema.rb +9 -9
  29. data/lib/govuk_publishing_components/presenters/machine_readable/dataset_schema.rb +2 -2
  30. data/lib/govuk_publishing_components/presenters/machine_readable/faq_page_schema.rb +3 -3
  31. data/lib/govuk_publishing_components/presenters/machine_readable/government_service_schema.rb +10 -10
  32. data/lib/govuk_publishing_components/presenters/machine_readable/has_part_schema.rb +1 -1
  33. data/lib/govuk_publishing_components/presenters/machine_readable/is_part_of_schema.rb +1 -1
  34. data/lib/govuk_publishing_components/presenters/machine_readable/organisation_schema.rb +5 -5
  35. data/lib/govuk_publishing_components/presenters/machine_readable/person_schema.rb +3 -3
  36. data/lib/govuk_publishing_components/presenters/machine_readable/potential_search_action_schema.rb +3 -3
  37. data/lib/govuk_publishing_components/presenters/meta_tags.rb +6 -6
  38. data/lib/govuk_publishing_components/presenters/organisation_logo_helper.rb +1 -1
  39. data/lib/govuk_publishing_components/presenters/page_with_step_by_step_navigation.rb +3 -3
  40. data/lib/govuk_publishing_components/presenters/related_navigation_helper.rb +32 -32
  41. data/lib/govuk_publishing_components/presenters/schema_org.rb +13 -13
  42. data/lib/govuk_publishing_components/presenters/select.rb +1 -1
  43. data/lib/govuk_publishing_components/presenters/step_by_step_nav_helper.rb +9 -9
  44. data/lib/govuk_publishing_components/presenters/taxonomy_list_helper.rb +1 -1
  45. data/lib/govuk_publishing_components/version.rb +1 -1
  46. data/lib/tasks/govuk_publishing_components_tasks.rake +7 -7
  47. data/node_modules/axe-core/CHANGELOG.md +18 -0
  48. data/node_modules/axe-core/README.md +9 -6
  49. data/node_modules/axe-core/axe.js +71 -20
  50. data/node_modules/axe-core/axe.min.js +2 -2
  51. data/node_modules/axe-core/bower.json +1 -1
  52. data/node_modules/axe-core/doc/API.md +4 -7
  53. data/node_modules/axe-core/doc/backwards-compatibility-doc.md +2 -1
  54. data/node_modules/axe-core/doc/rule-descriptions.md +129 -91
  55. data/node_modules/axe-core/lib/checks/aria/invalidrole.js +12 -9
  56. data/node_modules/axe-core/lib/checks/keyboard/page-has-elm.js +1 -1
  57. data/node_modules/axe-core/lib/checks/language/has-lang.js +10 -5
  58. data/node_modules/axe-core/lib/checks/navigation/region.js +7 -2
  59. data/node_modules/axe-core/lib/commons/aria/index.js +6 -11
  60. data/node_modules/axe-core/lib/commons/dom/url-props-from-attribute.js +15 -6
  61. data/node_modules/axe-core/lib/core/utils/get-check-message.js +21 -0
  62. data/node_modules/axe-core/lib/rules/area-alt.json +2 -0
  63. data/node_modules/axe-core/lib/rules/aria-roles.json +1 -0
  64. data/node_modules/axe-core/lib/rules/color-contrast-matches.js +26 -0
  65. data/node_modules/axe-core/lib/rules/label-content-name-mismatch-matches.js +4 -1
  66. data/node_modules/axe-core/lib/rules/no-empty-role-matches.js +9 -0
  67. data/node_modules/axe-core/lib/rules/skip-link-matches.js +1 -1
  68. data/node_modules/axe-core/package.json +12 -12
  69. data/node_modules/axe-core/sri-history.json +4 -0
  70. data/node_modules/govuk-frontend/govuk/all.js +21 -31
  71. data/node_modules/govuk-frontend/govuk/components/button/template.njk +1 -1
  72. data/node_modules/govuk-frontend/govuk/components/character-count/macro-options.json +1 -1
  73. data/node_modules/govuk-frontend/govuk/components/checkboxes/macro-options.json +1 -1
  74. data/node_modules/govuk-frontend/govuk/components/date-input/macro-options.json +1 -1
  75. data/node_modules/govuk-frontend/govuk/components/error-summary/error-summary.js +1 -1
  76. data/node_modules/govuk-frontend/govuk/components/file-upload/macro-options.json +1 -1
  77. data/node_modules/govuk-frontend/govuk/components/footer/template.njk +1 -1
  78. data/node_modules/govuk-frontend/govuk/components/header/template.njk +1 -1
  79. data/node_modules/govuk-frontend/govuk/components/input/macro-options.json +1 -1
  80. data/node_modules/govuk-frontend/govuk/components/radios/macro-options.json +1 -1
  81. data/node_modules/govuk-frontend/govuk/components/select/macro-options.json +1 -1
  82. data/node_modules/govuk-frontend/govuk/components/skip-link/macro-options.json +2 -2
  83. data/node_modules/govuk-frontend/govuk/components/tabs/tabs.js +20 -30
  84. data/node_modules/govuk-frontend/govuk/components/tabs/template.njk +2 -2
  85. data/node_modules/govuk-frontend/govuk/components/tag/_tag.scss +47 -0
  86. data/node_modules/govuk-frontend/govuk/components/textarea/macro-options.json +1 -1
  87. data/node_modules/govuk-frontend/govuk/helpers/_spacing.scss +4 -4
  88. data/node_modules/govuk-frontend/govuk/helpers/_typography.scss +5 -5
  89. data/node_modules/govuk-frontend/govuk/helpers/_visually-hidden.scss +29 -29
  90. data/node_modules/govuk-frontend/govuk/overrides/_display.scss +6 -0
  91. data/node_modules/govuk-frontend/govuk/tools/_iff.scss +3 -1
  92. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element/prototype/closest.js +1 -1
  93. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element/prototype/nextElementSibling.js +10 -16
  94. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element/prototype/previousElementSibling.js +10 -14
  95. data/node_modules/govuk-frontend/package.json +10 -10
  96. metadata +32 -16
@@ -21,7 +21,7 @@ module GovukPublishingComponents
21
21
  if image
22
22
  image_tag(logo_image_src, alt: logo_image_alt, class: "gem-c-organisation-logo__image")
23
23
  else
24
- content_tag('span', name, class: "gem-c-organisation-logo__name")
24
+ content_tag("span", name, class: "gem-c-organisation-logo__name")
25
25
  end
26
26
  end
27
27
 
@@ -85,7 +85,7 @@ module GovukPublishingComponents
85
85
  {
86
86
  title: current_step_nav.title,
87
87
  path: current_step_nav.base_path,
88
- tracking_id: current_step_nav.content_id
88
+ tracking_id: current_step_nav.content_id,
89
89
  }
90
90
  else
91
91
  {}
@@ -137,7 +137,7 @@ module GovukPublishingComponents
137
137
  end
138
138
 
139
139
  def active_step_nav_content_id
140
- @active_step_nav_content_id ||= @query_parameters['step-by-step-nav'].present? ? @query_parameters['step-by-step-nav'] : nil
140
+ @active_step_nav_content_id ||= @query_parameters["step-by-step-nav"].present? ? @query_parameters["step-by-step-nav"] : nil
141
141
  end
142
142
 
143
143
  def steps
@@ -185,7 +185,7 @@ module GovukPublishingComponents
185
185
  {
186
186
  href: step_nav.base_path,
187
187
  text: step_nav.title,
188
- tracking_id: step_nav.content_id
188
+ tracking_id: step_nav.content_id,
189
189
  }
190
190
  end
191
191
  end
@@ -13,11 +13,11 @@ module GovukPublishingComponents
13
13
  statistical_data_sets
14
14
  ).freeze
15
15
  WORLD_LOCATION_SPECIAL_CASES = {
16
- 'UK Mission to the European Union' => 'uk-mission-to-the-eu',
16
+ "UK Mission to the European Union" => "uk-mission-to-the-eu",
17
17
  }.freeze
18
18
 
19
19
  def initialize(options = {})
20
- @content_item = options.fetch(:content_item) { raise ArgumentError, 'missing argument: content_item' }
20
+ @content_item = options.fetch(:content_item) { raise ArgumentError, "missing argument: content_item" }
21
21
  @context = options.fetch(:context, nil)
22
22
  end
23
23
 
@@ -57,8 +57,8 @@ module GovukPublishingComponents
57
57
  unless section_title === "related_items"
58
58
  I18n.t("components.related_#{@context}_navigation." + section_title,
59
59
  default: [
60
- I18n.t('components.related_navigation.' + section_title),
61
- section_title.tr('_', ' '),
60
+ I18n.t("components.related_navigation." + section_title),
61
+ section_title.tr("_", " "),
62
62
  ])
63
63
  end
64
64
  end
@@ -72,15 +72,15 @@ module GovukPublishingComponents
72
72
  css_classes << " #{css_class}--other"
73
73
  end
74
74
 
75
- css_classes.join(' ')
75
+ css_classes.join(" ")
76
76
  end
77
77
 
78
78
  def section_data_track_count(section_title)
79
- String(@context || 'sidebar') + String(section_title).camelcase
79
+ String(@context || "sidebar") + String(section_title).camelcase
80
80
  end
81
81
 
82
82
  def section_heading_level
83
- @context == :footer ? 'h2' : 'h3'
83
+ @context == :footer ? "h2" : "h3"
84
84
  end
85
85
 
86
86
  def calculate_section_link_limit(links)
@@ -129,26 +129,26 @@ module GovukPublishingComponents
129
129
  private
130
130
 
131
131
  def translation_present?(content)
132
- default_string = 'This is a string to act as a default for the `I18n.translate` method. Comparing the result reveals if there is a translation in the i18n files.'
132
+ default_string = "This is a string to act as a default for the `I18n.translate` method. Comparing the result reveals if there is a translation in the i18n files."
133
133
  I18n.translate(
134
134
  content,
135
135
  default: default_string,
136
- fallback: false
136
+ fallback: false,
137
137
  ) != default_string
138
138
  end
139
139
 
140
140
  def related_items
141
- related_quick_links = content_item_details_for('quick_links')
141
+ related_quick_links = content_item_details_for("quick_links")
142
142
 
143
143
  if related_quick_links.any?
144
144
  related_quick_links + related_mainstream_content
145
145
  else
146
- content_item_links_for('ordered_related_items') + related_mainstream_content
146
+ content_item_links_for("ordered_related_items") + related_mainstream_content
147
147
  end
148
148
  end
149
149
 
150
150
  def related_world_locations
151
- content_item_links_for('world_locations')
151
+ content_item_links_for("world_locations")
152
152
  .map do |link|
153
153
  slug = WORLD_LOCATION_SPECIAL_CASES[link[:text]] || link[:text].parameterize
154
154
  link.merge(path: "/world/#{slug}/news")
@@ -156,11 +156,11 @@ module GovukPublishingComponents
156
156
  end
157
157
 
158
158
  def related_statistical_data_sets
159
- content_item_links_for('related_statistical_data_sets', only: 'statistical_data_set')
159
+ content_item_links_for("related_statistical_data_sets", only: "statistical_data_set")
160
160
  end
161
161
 
162
162
  def related_taxons
163
- content_item_links_for('taxons', only: 'taxon')
163
+ content_item_links_for("taxons", only: "taxon")
164
164
  end
165
165
 
166
166
  def related_topics
@@ -174,8 +174,8 @@ module GovukPublishingComponents
174
174
  end
175
175
 
176
176
  def related_legacy_topics
177
- mainstream_browse_page_links = content_item_links_for('mainstream_browse_pages', only: 'mainstream_browse_page')
178
- topic_links = content_item_links_for('topics', only: 'topic')
177
+ mainstream_browse_page_links = content_item_links_for("mainstream_browse_pages", only: "mainstream_browse_page")
178
+ topic_links = content_item_links_for("topics", only: "topic")
179
179
 
180
180
  mainstream_browse_page_links + topic_links.find_all do |topic_link|
181
181
  mainstream_browse_page_links.none? do |mainstream_browse_page_link|
@@ -185,58 +185,58 @@ module GovukPublishingComponents
185
185
  end
186
186
 
187
187
  def related_topical_events
188
- content_item_links_for('topical_events', only: 'topical_event')
188
+ content_item_links_for("topical_events", only: "topical_event")
189
189
  end
190
190
 
191
191
  def related_contacts
192
- content_item_links_for('related', only: 'contact')
192
+ content_item_links_for("related", only: "contact")
193
193
  end
194
194
 
195
195
  def related_external_links
196
- content_item_details_for('external_related_links')
196
+ content_item_details_for("external_related_links")
197
197
  end
198
198
 
199
199
  def related_mainstream_content
200
200
  return [] unless detailed_guide?
201
201
 
202
- content_item_links_for('related_mainstream_content')
202
+ content_item_links_for("related_mainstream_content")
203
203
  end
204
204
 
205
205
  def related_guides
206
206
  return [] unless detailed_guide?
207
207
 
208
- content_item_links_for('related_guides')
208
+ content_item_links_for("related_guides")
209
209
  end
210
210
 
211
211
  def related_document_collections
212
- content_item_links_for('document_collections', only: 'document_collection')
212
+ content_item_links_for("document_collections", only: "document_collection")
213
213
  end
214
214
 
215
215
  def detailed_guide?
216
- @content_item['document_type'] == 'detailed_guide'
216
+ @content_item["document_type"] == "detailed_guide"
217
217
  end
218
218
 
219
219
  def content_item_details_for(key)
220
- Array(@content_item.dig('details', key))
221
- .map { |link| { path: link['url'], text: link['title'], rel: 'external' } }
220
+ Array(@content_item.dig("details", key))
221
+ .map { |link| { path: link["url"], text: link["title"], rel: "external" } }
222
222
  end
223
223
 
224
224
  def content_item_links_for(key, only: nil)
225
- links = Array(@content_item.dig('links', key))
225
+ links = Array(@content_item.dig("links", key))
226
226
 
227
- if key == 'taxons'
228
- links = links.find_all { |link| link['phase'] == 'live' }
227
+ if key == "taxons"
228
+ links = links.find_all { |link| link["phase"] == "live" }
229
229
  end
230
230
 
231
231
  if only.present?
232
- links = links.find_all { |link| link['document_type'] == only }
232
+ links = links.find_all { |link| link["document_type"] == only }
233
233
  end
234
234
 
235
235
  links.map { |link|
236
236
  {
237
- path: link['base_path'],
238
- text: link['title'],
239
- locale: link['locale'],
237
+ path: link["base_path"],
238
+ text: link["title"],
239
+ locale: link["locale"],
240
240
  }
241
241
  }
242
242
  end
@@ -1,16 +1,16 @@
1
- require 'govuk_publishing_components/presenters/machine_readable/page'
2
- require 'govuk_publishing_components/presenters/machine_readable/article_schema'
3
- require 'govuk_publishing_components/presenters/machine_readable/creative_work_schema'
4
- require 'govuk_publishing_components/presenters/machine_readable/faq_page_schema'
5
- require 'govuk_publishing_components/presenters/machine_readable/government_service_schema'
6
- require 'govuk_publishing_components/presenters/machine_readable/has_part_schema'
7
- require 'govuk_publishing_components/presenters/machine_readable/is_part_of_schema'
8
- require 'govuk_publishing_components/presenters/machine_readable/news_article_schema'
9
- require 'govuk_publishing_components/presenters/machine_readable/organisation_schema'
10
- require 'govuk_publishing_components/presenters/machine_readable/person_schema'
11
- require 'govuk_publishing_components/presenters/machine_readable/potential_search_action_schema'
12
- require 'govuk_publishing_components/presenters/machine_readable/search_results_page_schema'
13
- require 'govuk_publishing_components/presenters/machine_readable/dataset_schema'
1
+ require "govuk_publishing_components/presenters/machine_readable/page"
2
+ require "govuk_publishing_components/presenters/machine_readable/article_schema"
3
+ require "govuk_publishing_components/presenters/machine_readable/creative_work_schema"
4
+ require "govuk_publishing_components/presenters/machine_readable/faq_page_schema"
5
+ require "govuk_publishing_components/presenters/machine_readable/government_service_schema"
6
+ require "govuk_publishing_components/presenters/machine_readable/has_part_schema"
7
+ require "govuk_publishing_components/presenters/machine_readable/is_part_of_schema"
8
+ require "govuk_publishing_components/presenters/machine_readable/news_article_schema"
9
+ require "govuk_publishing_components/presenters/machine_readable/organisation_schema"
10
+ require "govuk_publishing_components/presenters/machine_readable/person_schema"
11
+ require "govuk_publishing_components/presenters/machine_readable/potential_search_action_schema"
12
+ require "govuk_publishing_components/presenters/machine_readable/search_results_page_schema"
13
+ require "govuk_publishing_components/presenters/machine_readable/dataset_schema"
14
14
 
15
15
  module GovukPublishingComponents
16
16
  module Presenters
@@ -22,7 +22,7 @@ module GovukPublishingComponents
22
22
  [
23
23
  option[:text],
24
24
  option[:value],
25
- options_data_attribute(option[:data_attributes])
25
+ options_data_attribute(option[:data_attributes]),
26
26
  ]
27
27
  }
28
28
  end
@@ -28,7 +28,7 @@ module GovukPublishingComponents
28
28
  content_tag(
29
29
  :p,
30
30
  text,
31
- class: "gem-c-step-nav__paragraph"
31
+ class: "gem-c-step-nav__paragraph",
32
32
  )
33
33
  end
34
34
 
@@ -37,17 +37,17 @@ module GovukPublishingComponents
37
37
  get_list_element(element[:style]),
38
38
  class: "gem-c-step-nav__list #{get_list_style(element[:style])}",
39
39
  data: {
40
- length: element[:contents].length
41
- }
40
+ length: element[:contents].length,
41
+ },
42
42
  ) do
43
43
  element[:contents].collect { |contents|
44
44
  concat(
45
45
  content_tag(
46
46
  :li,
47
- class: "gem-c-step-nav__list-item js-list-item #{link_active(contents[:active])}"
47
+ class: "gem-c-step-nav__list-item js-list-item #{link_active(contents[:active])}",
48
48
  ) do
49
49
  create_list_item_content(contents)
50
- end
50
+ end,
51
51
  )
52
52
  }
53
53
  end
@@ -66,11 +66,11 @@ module GovukPublishingComponents
66
66
 
67
67
  link_to(
68
68
  href,
69
- rel: ("external" if href.start_with?('http')),
69
+ rel: ("external" if href.start_with?("http")),
70
70
  data: {
71
- position: "#{@options[:step_index] + 1}.#{@link_index}"
71
+ position: "#{@options[:step_index] + 1}.#{@link_index}",
72
72
  },
73
- class: "gem-c-step-nav__link js-link"
73
+ class: "gem-c-step-nav__link js-link",
74
74
  ) do
75
75
  text
76
76
  end
@@ -99,7 +99,7 @@ module GovukPublishingComponents
99
99
  end
100
100
 
101
101
  def external_url?(href)
102
- href.start_with?('http')
102
+ href.start_with?("http")
103
103
  end
104
104
 
105
105
  def link_with_step_nav_query_parameter(href)
@@ -14,7 +14,7 @@ module GovukPublishingComponents
14
14
  image_src: image_card[:image][:url],
15
15
  image_alt: image_card[:image][:alt],
16
16
  heading_level: image_card[:link][:heading_level],
17
- href_data_attributes: image_card[:link][:data_attributes]
17
+ href_data_attributes: image_card[:link][:data_attributes],
18
18
  }
19
19
  end
20
20
  end
@@ -1,3 +1,3 @@
1
1
  module GovukPublishingComponents
2
- VERSION = '21.27.1'.freeze
2
+ VERSION = "21.28.0".freeze
3
3
  end
@@ -1,12 +1,12 @@
1
1
  namespace :component do
2
- desc 'warns if component view files exist without corresponding documentation'
2
+ desc "warns if component view files exist without corresponding documentation"
3
3
  task :validate_documentation_exists do
4
4
  print "Validating that each component has documentation... "
5
5
  components_missing_docs = []
6
6
  component_views = Dir["app/views/#{GovukPublishingComponents::Config.component_directory_name}/**/*.html.erb"]
7
7
  component_views.each do |partial|
8
- expected_component_docs_file = partial.split('/')[-1].gsub('html.erb', 'yml')
9
- expected_component_docs_file.sub!(/^_/, '')
8
+ expected_component_docs_file = partial.split("/")[-1].gsub("html.erb", "yml")
9
+ expected_component_docs_file.sub!(/^_/, "")
10
10
 
11
11
  expected_component_docs_path = "app/views/#{GovukPublishingComponents::Config.component_directory_name}/docs/#{expected_component_docs_file}"
12
12
  components_missing_docs << partial unless File.exist?(expected_component_docs_path)
@@ -21,7 +21,7 @@ namespace :component do
21
21
  puts "✔︎"
22
22
  end
23
23
 
24
- desc 'warns if component is missing accessibility criteria'
24
+ desc "warns if component is missing accessibility criteria"
25
25
  task :validate_accessibility_criteria_exist do
26
26
  print "Validating that each component has accessibility criteria... "
27
27
  errors = []
@@ -30,8 +30,8 @@ namespace :component do
30
30
  component_docs.each do |doc_file|
31
31
  file = YAML.load_file(doc_file)
32
32
 
33
- if file['accessibility_criteria'].nil? && file['shared_accessibility_criteria'].nil?
34
- errors << file['name']
33
+ if file["accessibility_criteria"].nil? && file["shared_accessibility_criteria"].nil?
34
+ errors << file["name"]
35
35
  end
36
36
  end
37
37
  if errors.any?
@@ -41,7 +41,7 @@ namespace :component do
41
41
  puts "✔︎"
42
42
  end
43
43
 
44
- desc 'warns if component view files exist without corresponding documentation or accessibility critera'
44
+ desc "warns if component view files exist without corresponding documentation or accessibility critera"
45
45
  task :validate_documentation do
46
46
  Rake::Task["component:validate_documentation_exists"].invoke
47
47
  Rake::Task["component:validate_accessibility_criteria_exist"].invoke
@@ -2,6 +2,24 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ### [3.5.2](https://github.com/dequelabs/axe-core/compare/v3.5.1...v3.5.2) (2020-03-06)
6
+
7
+ ### Bug Fixes
8
+
9
+ - **aria-allowed-role:** allow role=spinbutton on input[type=tel](<[635445b](https://github.com/dequelabs/axe-core/commit/635445ba6da7bc197bcdee6fb1a9d9dc81e43941)>)
10
+ - **color-contrast:** ignore form elements that move text outside of node using text-indent ([#2044](https://github.com/dequelabs/axe-core/issues/2044)) ([85cc6ab](https://github.com/dequelabs/axe-core/commit/85cc6abd7f919a7311c6da01a41853cbfd539508))
11
+ - **commons:** handle node(s) contained by SVG document when de… ([#2054](https://github.com/dequelabs/axe-core/issues/2054)) ([bf4c9bf](https://github.com/dequelabs/axe-core/commit/bf4c9bff2953b1ac7f40dbb1d0bd1986c1caa673))
12
+ - **getCheckMessage:** add API to return check message ([#2066](https://github.com/dequelabs/axe-core/issues/2066)) ([e216322](https://github.com/dequelabs/axe-core/commit/e216322183c8b064ebfd748fea785b8c2fe78b16))
13
+ - **has-lang:** fail check when `xml:lang` is used in HTML docum… ([#2053](https://github.com/dequelabs/axe-core/issues/2053)) ([e07aaea](https://github.com/dequelabs/axe-core/commit/e07aaea86bc9460a2d9f568637b4a77d33094ed6))
14
+ - **label-content-name-mismatch:** ignore non `widget` aria role(s) & do not use deprecated `lookupTable.rolesOfType` ([#2022](https://github.com/dequelabs/axe-core/issues/2022)) ([89bd84c](https://github.com/dequelabs/axe-core/commit/89bd84c4a9846dc31a660eda6b274329e7ac70b5))
15
+ - **package-lock:** change @deque/doT from agora to npm ([#2058](https://github.com/dequelabs/axe-core/issues/2058)) ([c03c0e5](https://github.com/dequelabs/axe-core/commit/c03c0e5ffc3ea1b49607355fa9d6f2e2faf0ebd1))
16
+ - **page-has-heading-one:** find screen-reader only headings ([#2065](https://github.com/dequelabs/axe-core/issues/2065)) ([f808a12](https://github.com/dequelabs/axe-core/commit/f808a12261269719534ae52c878d1700fb70053e))
17
+ - **region:** ignore direct child text nodes of body ([#2050](https://github.com/dequelabs/axe-core/issues/2050)) ([fde31d0](https://github.com/dequelabs/axe-core/commit/fde31d03d24820f681b257c4c42b98f25b2877ec))
18
+ - **skip-link:** identify as skip-link only if the link is offscreen ([#2079](https://github.com/dequelabs/axe-core/issues/2079)) ([241e1d0](https://github.com/dequelabs/axe-core/commit/241e1d0715398a39c2e502ddb781f5fc29987dde))
19
+ - check `invaildrole` fails only when all roles are invalid ([#2075](https://github.com/dequelabs/axe-core/issues/2075)) ([989b317](https://github.com/dequelabs/axe-core/commit/989b31788b08b6514dd4b606162193d4dd168be9))
20
+ - ignore empty, whitespace or undefined `role` for rule `ari… ([#2077](https://github.com/dequelabs/axe-core/issues/2077)) ([dbd3c02](https://github.com/dequelabs/axe-core/commit/dbd3c0211b05641f366dfe2fe9c2124cad9e5e3a))
21
+ - update tags for rule `area-alt` ([#2051](https://github.com/dequelabs/axe-core/issues/2051)) ([7db231f](https://github.com/dequelabs/axe-core/commit/7db231f2ff2b70a4e8e6f7aababe0871764ece96))
22
+
5
23
  ### [3.5.1](https://github.com/dequelabs/axe-core/compare/v3.5.0...v3.5.1) (2020-02-12)
6
24
 
7
25
  ### Bug Fixes
@@ -50,12 +50,15 @@ Now include the javascript file in each of your iframes in your fixtures or test
50
50
  Now insert calls at each point in your tests where a new piece of UI becomes visible or exposed:
51
51
 
52
52
  ```js
53
- axe.run(function (err, results) {
54
- if (err) throw err;
55
- ok(results.violations.length === 0, 'Should be no accessibility issues');
56
- // complete the async call
57
- ...
58
- });
53
+ axe.run()
54
+ .then(results => {
55
+ if (results.violations.length) {
56
+ throw new Error('Accessibility issues found')
57
+ }
58
+ })
59
+ .catch(err => {
60
+ console.error('Something bad happened:', err.message)
61
+ })
59
62
  ```
60
63
 
61
64
  ## Supported Browsers
@@ -1,4 +1,4 @@
1
- /*! axe v3.5.1
1
+ /*! axe v3.5.2
2
2
  * Copyright (c) 2020 Deque Systems, Inc.
3
3
  *
4
4
  * Your use of this Source Code Form is subject to the terms of the Mozilla Public
@@ -27,7 +27,7 @@
27
27
  return _typeof(obj);
28
28
  }
29
29
  var axe = axe || {};
30
- axe.version = '3.5.1';
30
+ axe.version = '3.5.2';
31
31
  if (typeof define === 'function' && define.amd) {
32
32
  define('axe-core', [], function() {
33
33
  'use strict';
@@ -11283,6 +11283,17 @@
11283
11283
  return lang.trim().split('-')[0].toLowerCase();
11284
11284
  };
11285
11285
  'use strict';
11286
+ axe.utils.getCheckMessage = function getCheckMessage(checkId, type, data) {
11287
+ var check = axe._audit.data.checks[checkId];
11288
+ if (!check) {
11289
+ throw new Error('Cannot get message for unknown check: '.concat(checkId, '.'));
11290
+ }
11291
+ if (!check.messages[type]) {
11292
+ throw new Error('Check "'.concat(checkId, '"" does not have a "').concat(type, '" message.'));
11293
+ }
11294
+ return axe.utils.processMessage(check.messages[type], data);
11295
+ };
11296
+ 'use strict';
11286
11297
  axe.utils.getCheckOption = function(check, ruleID, options) {
11287
11298
  var ruleCheckOption = ((options.rules && options.rules[ruleID] || {}).checks || {})[check.id];
11288
11299
  var checkOption = (options.checks || {})[check.id];
@@ -14880,7 +14891,7 @@
14880
14891
  id: 'area-alt',
14881
14892
  selector: 'map area[href]',
14882
14893
  excludeHidden: false,
14883
- tags: [ 'cat.text-alternatives', 'wcag2a', 'wcag111', 'section508', 'section508.22.a' ],
14894
+ tags: [ 'cat.text-alternatives', 'wcag2a', 'wcag111', 'wcag244', 'wcag412', 'section508', 'section508.22.a' ],
14884
14895
  all: [],
14885
14896
  any: [ 'non-empty-alt', 'non-empty-title', 'aria-label', 'aria-labelledby' ],
14886
14897
  none: []
@@ -15035,6 +15046,15 @@
15035
15046
  }, {
15036
15047
  id: 'aria-roles',
15037
15048
  selector: '[role]',
15049
+ matches: function matches(node, virtualNode, context) {
15050
+ if (!virtualNode.hasAttr('role')) {
15051
+ return false;
15052
+ }
15053
+ if (!virtualNode.attr('role').trim()) {
15054
+ return false;
15055
+ }
15056
+ return true;
15057
+ },
15038
15058
  tags: [ 'cat.aria', 'wcag2a', 'wcag412' ],
15039
15059
  all: [],
15040
15060
  any: [],
@@ -15206,6 +15226,23 @@
15206
15226
  if (node.getAttribute('aria-disabled') === 'true' || axe.commons.dom.findUpVirtual(virtualNode, '[aria-disabled="true"]')) {
15207
15227
  return false;
15208
15228
  }
15229
+ var formElements = [ 'INPUT', 'SELECT', 'TEXTAREA' ];
15230
+ if (formElements.includes(nodeName)) {
15231
+ var style = window.getComputedStyle(node);
15232
+ var textIndent = parseInt(style.getPropertyValue('text-indent'), 10);
15233
+ if (textIndent) {
15234
+ var rect = node.getBoundingClientRect();
15235
+ rect = {
15236
+ top: rect.top,
15237
+ bottom: rect.bottom,
15238
+ left: rect.left + textIndent,
15239
+ right: rect.right + textIndent
15240
+ };
15241
+ if (!axe.commons.dom.visuallyOverlaps(rect, node)) {
15242
+ return false;
15243
+ }
15244
+ }
15245
+ }
15209
15246
  if (nodeName === 'INPUT') {
15210
15247
  return [ 'hidden', 'range', 'color', 'checkbox', 'radio', 'image' ].indexOf(nodeType) === -1 && !node.disabled;
15211
15248
  }
@@ -15567,7 +15604,10 @@
15567
15604
  if (!role) {
15568
15605
  return false;
15569
15606
  }
15570
- var isWidgetType = aria.lookupTable.rolesOfType.widget.includes(role);
15607
+ var widgetRoles = Object.keys(aria.lookupTable.role).filter(function(key) {
15608
+ return aria.lookupTable.role[key].type === 'widget';
15609
+ });
15610
+ var isWidgetType = widgetRoles.includes(role);
15571
15611
  if (!isWidgetType) {
15572
15612
  return false;
15573
15613
  }
@@ -15983,7 +16023,7 @@
15983
16023
  id: 'skip-link',
15984
16024
  selector: 'a[href^="#"], a[href^="/#"]',
15985
16025
  matches: function matches(node, virtualNode, context) {
15986
- return axe.commons.dom.isSkipLink(node);
16026
+ return axe.commons.dom.isSkipLink(node) && axe.commons.dom.isOffscreen(node);
15987
16027
  },
15988
16028
  tags: [ 'cat.keyboard', 'best-practice' ],
15989
16029
  all: [],
@@ -16224,13 +16264,16 @@
16224
16264
  }, {
16225
16265
  id: 'invalidrole',
16226
16266
  evaluate: function evaluate(node, options, virtualNode, context) {
16227
- var invalidRoles = axe.utils.tokenList(virtualNode.attr('role')).filter(function(role) {
16228
- return !axe.commons.aria.isValidRole(role, {
16267
+ var tokenList = axe.utils.tokenList;
16268
+ var aria = axe.commons.aria;
16269
+ var allRoles = tokenList(virtualNode.attr('role'));
16270
+ var allInvalid = allRoles.every(function(role) {
16271
+ return !aria.isValidRole(role, {
16229
16272
  allowAbstract: true
16230
16273
  });
16231
16274
  });
16232
- if (invalidRoles.length > 0) {
16233
- this.data(invalidRoles);
16275
+ if (allInvalid) {
16276
+ this.data(allRoles);
16234
16277
  return true;
16235
16278
  }
16236
16279
  return false;
@@ -17108,7 +17151,7 @@
17108
17151
  throw new TypeError('visible-in-page requires options.selector to be a string');
17109
17152
  }
17110
17153
  var matchingElms = axe.utils.querySelectorAllFilter(virtualNode, options.selector, function(vNode) {
17111
- return axe.commons.dom.isVisible(vNode.actualNode);
17154
+ return axe.commons.dom.isVisible(vNode.actualNode, true);
17112
17155
  });
17113
17156
  this.relatedNodes(matchingElms.map(function(vNode) {
17114
17157
  return vNode.actualNode;
@@ -17136,7 +17179,7 @@
17136
17179
  throw new TypeError('visible-in-page requires options.selector to be a string');
17137
17180
  }
17138
17181
  var matchingElms = axe.utils.querySelectorAllFilter(virtualNode, options.selector, function(vNode) {
17139
- return axe.commons.dom.isVisible(vNode.actualNode);
17182
+ return axe.commons.dom.isVisible(vNode.actualNode, true);
17140
17183
  });
17141
17184
  this.relatedNodes(matchingElms.map(function(vNode) {
17142
17185
  return vNode.actualNode;
@@ -17470,7 +17513,13 @@
17470
17513
  }, {
17471
17514
  id: 'has-lang',
17472
17515
  evaluate: function evaluate(node, options, virtualNode, context) {
17473
- return !!(node.getAttribute('lang') || node.getAttribute('xml:lang') || '').trim();
17516
+ var isXHTML = axe.utils.isXHTML;
17517
+ var langValue = (node.getAttribute('lang') || '').trim();
17518
+ var xmlLangValue = (node.getAttribute('xml:lang') || '').trim();
17519
+ if (!langValue && !isXHTML(document)) {
17520
+ return false;
17521
+ }
17522
+ return !!(langValue || xmlLangValue);
17474
17523
  }
17475
17524
  }, {
17476
17525
  id: 'valid-lang',
@@ -18253,7 +18302,7 @@
18253
18302
  vNode = vNode.parent;
18254
18303
  }
18255
18304
  return [];
18256
- } else if (dom.hasContent(node, true)) {
18305
+ } else if (node !== document.body && dom.hasContent(node, true)) {
18257
18306
  return [ virtualNode ];
18258
18307
  } else {
18259
18308
  return virtualNode.children.filter(function(_ref20) {
@@ -20186,7 +20235,7 @@
20186
20235
  allowedElements: {
20187
20236
  nodeName: 'input',
20188
20237
  properties: {
20189
- type: 'text'
20238
+ type: [ 'text', 'tel' ]
20190
20239
  }
20191
20240
  }
20192
20241
  },
@@ -20333,7 +20382,7 @@
20333
20382
  allowedElements: [ 'ol', 'ul' ]
20334
20383
  },
20335
20384
  tooltip: {
20336
- type: 'widget',
20385
+ type: 'structure',
20337
20386
  attributes: {
20338
20387
  allowed: [ 'aria-expanded', 'aria-errormessage' ]
20339
20388
  },
@@ -20502,6 +20551,8 @@
20502
20551
  return role === 'combobox' || role === 'searchbox' || role === 'spinbutton';
20503
20552
 
20504
20553
  case 'tel':
20554
+ return role === 'combobox' || role === 'spinbutton';
20555
+
20505
20556
  case 'url':
20506
20557
  case 'search':
20507
20558
  case 'email':
@@ -22141,18 +22192,18 @@
22141
22192
  }, []);
22142
22193
  };
22143
22194
  dom.urlPropsFromAttribute = function urlPropsFromAttribute(node, attribute) {
22144
- var value = node[attribute];
22145
- if (!value) {
22195
+ if (!node.hasAttribute(attribute)) {
22146
22196
  return undefined;
22147
22197
  }
22148
22198
  var nodeName = node.nodeName.toUpperCase();
22149
22199
  var parser = node;
22150
- if (![ 'A', 'AREA' ].includes(nodeName)) {
22200
+ if (![ 'A', 'AREA' ].includes(nodeName) || node.ownerSVGElement) {
22151
22201
  parser = document.createElement('a');
22152
- parser.href = value;
22202
+ parser.href = node.getAttribute(attribute);
22153
22203
  }
22154
22204
  var protocol = [ 'https:', 'ftps:' ].includes(parser.protocol) ? parser.protocol.replace(/s:$/, ':') : parser.protocol;
22155
- var _getPathnameOrFilenam = getPathnameOrFilename(parser.pathname), pathname = _getPathnameOrFilenam.pathname, filename = _getPathnameOrFilenam.filename;
22205
+ var parserPathname = /^\//.test(parser.pathname) ? parser.pathname : '/'.concat(parser.pathname);
22206
+ var _getPathnameOrFilenam = getPathnameOrFilename(parserPathname), pathname = _getPathnameOrFilenam.pathname, filename = _getPathnameOrFilenam.filename;
22156
22207
  return {
22157
22208
  protocol: protocol,
22158
22209
  hostname: parser.hostname,