govuk_publishing_components 21.16.3 → 21.17.0

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 (230) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/component_guide/accessibility-test.js +0 -6
  3. data/app/views/govuk_publishing_components/components/docs/machine_readable_metadata.yml +7 -0
  4. data/lib/govuk_publishing_components/presenters/machine_readable/dataset_schema.rb +34 -0
  5. data/lib/govuk_publishing_components/presenters/schema_org.rb +3 -0
  6. data/lib/govuk_publishing_components/version.rb +1 -1
  7. data/node_modules/axe-core/CHANGELOG.md +166 -2
  8. data/node_modules/axe-core/CONTRIBUTING.md +5 -5
  9. data/node_modules/axe-core/README.md +4 -4
  10. data/node_modules/axe-core/axe.d.ts +27 -11
  11. data/node_modules/axe-core/axe.js +9597 -2431
  12. data/node_modules/axe-core/axe.min.js +2 -2
  13. data/node_modules/axe-core/bower.json +1 -1
  14. data/node_modules/axe-core/doc/API.md +211 -128
  15. data/node_modules/axe-core/doc/accessibility-supported.md +1 -1
  16. data/node_modules/axe-core/doc/aria-supported.md +4 -13
  17. data/node_modules/axe-core/doc/backwards-compatibility-doc.md +93 -0
  18. data/node_modules/axe-core/doc/code-submission-guidelines.md +4 -4
  19. data/node_modules/axe-core/doc/developer-guide.md +27 -13
  20. data/node_modules/axe-core/doc/examples/chrome-debugging-protocol/package.json +5 -2
  21. data/node_modules/axe-core/doc/examples/jasmine/README.md +3 -5
  22. data/node_modules/axe-core/doc/examples/jasmine/karma.conf.js +29 -0
  23. data/node_modules/axe-core/doc/examples/jasmine/package.json +6 -5
  24. data/node_modules/axe-core/doc/examples/jest_react/README.md +1 -1
  25. data/node_modules/axe-core/doc/examples/jest_react/link.test.js +3 -3
  26. data/node_modules/axe-core/doc/examples/jest_react/package.json +9 -9
  27. data/node_modules/axe-core/doc/examples/jsdom/package.json +15 -0
  28. data/node_modules/axe-core/doc/examples/mocha/README.md +5 -7
  29. data/node_modules/axe-core/doc/examples/mocha/karma.conf.js +29 -0
  30. data/node_modules/axe-core/doc/examples/mocha/package.json +7 -6
  31. data/node_modules/axe-core/doc/examples/phantomjs/README.md +3 -3
  32. data/node_modules/axe-core/doc/examples/phantomjs/axe-phantom.js +4 -2
  33. data/node_modules/axe-core/doc/examples/phantomjs/package.json +3 -3
  34. data/node_modules/axe-core/doc/examples/puppeteer/package.json +5 -2
  35. data/node_modules/axe-core/doc/examples/qunit/README.md +2 -2
  36. data/node_modules/axe-core/doc/examples/qunit/package.json +2 -2
  37. data/node_modules/axe-core/doc/examples/test-examples.js +32 -0
  38. data/node_modules/axe-core/doc/plugins.md +10 -10
  39. data/node_modules/axe-core/doc/projects.md +12 -8
  40. data/node_modules/axe-core/doc/rule-descriptions.md +87 -79
  41. data/node_modules/axe-core/doc/rule-development.md +30 -2
  42. data/node_modules/axe-core/lib/checks/aria/allowed-attr.js +1 -1
  43. data/node_modules/axe-core/lib/checks/aria/aria-roledescription.js +14 -0
  44. data/node_modules/axe-core/lib/checks/aria/aria-roledescription.json +23 -0
  45. data/node_modules/axe-core/lib/checks/aria/no-implicit-explicit-label.js +21 -0
  46. data/node_modules/axe-core/lib/checks/aria/no-implicit-explicit-label.json +11 -0
  47. data/node_modules/axe-core/lib/checks/aria/required-attr.js +32 -7
  48. data/node_modules/axe-core/lib/checks/aria/required-children.js +40 -14
  49. data/node_modules/axe-core/lib/checks/aria/required-children.json +12 -1
  50. data/node_modules/axe-core/lib/checks/aria/required-parent.js +1 -1
  51. data/node_modules/axe-core/lib/checks/aria/unsupportedattr.js +1 -1
  52. data/node_modules/axe-core/lib/checks/aria/valid-attr-value.js +50 -17
  53. data/node_modules/axe-core/lib/checks/aria/valid-attr-value.json +2 -1
  54. data/node_modules/axe-core/lib/checks/aria/valid-attr.js +1 -1
  55. data/node_modules/axe-core/lib/checks/color/color-contrast.js +2 -2
  56. data/node_modules/axe-core/lib/checks/forms/autocomplete-appropriate.js +4 -4
  57. data/node_modules/axe-core/lib/checks/forms/autocomplete-valid.js +1 -1
  58. data/node_modules/axe-core/lib/checks/forms/fieldset.json +1 -0
  59. data/node_modules/axe-core/lib/checks/forms/group-labelledby.json +1 -0
  60. data/node_modules/axe-core/lib/checks/keyboard/focusable-content.js +16 -0
  61. data/node_modules/axe-core/lib/checks/keyboard/focusable-content.json +11 -0
  62. data/node_modules/axe-core/lib/checks/keyboard/focusable-element.js +12 -0
  63. data/node_modules/axe-core/lib/checks/keyboard/focusable-element.json +11 -0
  64. data/node_modules/axe-core/lib/checks/keyboard/tabindex.js +6 -1
  65. data/node_modules/axe-core/lib/checks/label/alt-space-value.js +3 -2
  66. data/node_modules/axe-core/lib/checks/label/duplicate-img-label.js +18 -15
  67. data/node_modules/axe-core/lib/checks/label/label-content-name-mismatch.js +13 -3
  68. data/node_modules/axe-core/lib/checks/label/label-content-name-mismatch.json +4 -0
  69. data/node_modules/axe-core/lib/checks/label/multiple-label.js +22 -12
  70. data/node_modules/axe-core/lib/checks/label/multiple-label.json +1 -1
  71. data/node_modules/axe-core/lib/checks/landmarks/landmark-is-unique-after.js +23 -0
  72. data/node_modules/axe-core/lib/checks/landmarks/landmark-is-unique.js +7 -0
  73. data/node_modules/axe-core/lib/checks/landmarks/landmark-is-unique.json +12 -0
  74. data/node_modules/axe-core/lib/checks/lists/listitem.js +1 -0
  75. data/node_modules/axe-core/lib/checks/lists/listitem.json +1 -1
  76. data/node_modules/axe-core/lib/checks/lists/only-listitems.js +0 -4
  77. data/node_modules/axe-core/lib/checks/mobile/css-orientation-lock.js +8 -6
  78. data/node_modules/axe-core/lib/checks/navigation/region.js +2 -19
  79. data/node_modules/axe-core/lib/checks/shared/avoid-inline-spacing.js +18 -0
  80. data/node_modules/axe-core/lib/checks/shared/avoid-inline-spacing.json +11 -0
  81. data/node_modules/axe-core/lib/checks/shared/exists.js +1 -1
  82. data/node_modules/axe-core/lib/checks/shared/exists.json +1 -1
  83. data/node_modules/axe-core/lib/checks/shared/has-alt.js +6 -4
  84. data/node_modules/axe-core/lib/checks/shared/non-empty-alt.js +1 -1
  85. data/node_modules/axe-core/lib/checks/tables/caption-faked.json +1 -1
  86. data/node_modules/axe-core/lib/checks/tables/td-has-header.js +5 -4
  87. data/node_modules/axe-core/lib/checks/tables/th-has-data-cells.js +19 -29
  88. data/node_modules/axe-core/lib/commons/aria/get-owned-virtual.js +1 -1
  89. data/node_modules/axe-core/lib/commons/aria/index.js +50 -46
  90. data/node_modules/axe-core/lib/commons/aria/is-accessible-ref.js +41 -37
  91. data/node_modules/axe-core/lib/commons/aria/label-virtual.js +2 -2
  92. data/node_modules/axe-core/lib/commons/aria/roles.js +1 -1
  93. data/node_modules/axe-core/lib/commons/aria/validate-attr-value.js +0 -1
  94. data/node_modules/axe-core/lib/commons/color/center-point-of-rect.js +30 -0
  95. data/node_modules/axe-core/lib/commons/color/contrast.js +7 -1
  96. data/node_modules/axe-core/lib/commons/color/element-has-image.js +36 -0
  97. data/node_modules/axe-core/lib/commons/color/get-background-color.js +332 -306
  98. data/node_modules/axe-core/lib/commons/color/get-foreground-color.js +35 -6
  99. data/node_modules/axe-core/lib/commons/color/get-own-background-color.js +22 -0
  100. data/node_modules/axe-core/lib/commons/dom/find-up.js +5 -5
  101. data/node_modules/axe-core/lib/commons/dom/get-scroll-offset.js +0 -1
  102. data/node_modules/axe-core/lib/commons/dom/get-tabbable-elements.js +1 -1
  103. data/node_modules/axe-core/lib/commons/dom/has-content-virtual.js +7 -5
  104. data/node_modules/axe-core/lib/commons/dom/is-focusable.js +8 -5
  105. data/node_modules/axe-core/lib/commons/dom/is-hidden-with-css.js +15 -2
  106. data/node_modules/axe-core/lib/commons/dom/is-in-text-block.js +1 -2
  107. data/node_modules/axe-core/lib/commons/dom/is-skip-link.js +45 -0
  108. data/node_modules/axe-core/lib/commons/dom/is-visible.js +43 -17
  109. data/node_modules/axe-core/lib/commons/dom/is-visual-content.js +0 -1
  110. data/node_modules/axe-core/lib/commons/dom/visually-contains.js +0 -1
  111. data/node_modules/axe-core/lib/commons/dom/visually-overlaps.js +0 -1
  112. data/node_modules/axe-core/lib/commons/forms/index.js +8 -0
  113. data/node_modules/axe-core/lib/commons/forms/is-aria-combobox.js +13 -0
  114. data/node_modules/axe-core/lib/commons/forms/is-aria-listbox.js +13 -0
  115. data/node_modules/axe-core/lib/commons/forms/is-aria-range.js +14 -0
  116. data/node_modules/axe-core/lib/commons/forms/is-aria-textbox.js +13 -0
  117. data/node_modules/axe-core/lib/commons/forms/is-native-select.js +13 -0
  118. data/node_modules/axe-core/lib/commons/forms/is-native-textbox.js +28 -0
  119. data/node_modules/axe-core/lib/commons/table/get-cell-position.js +2 -2
  120. data/node_modules/axe-core/lib/commons/table/get-headers.js +55 -11
  121. data/node_modules/axe-core/lib/commons/table/get-scope.js +1 -1
  122. data/node_modules/axe-core/lib/commons/table/is-data-table.js +0 -1
  123. data/node_modules/axe-core/lib/commons/table/to-grid.js +2 -2
  124. data/node_modules/axe-core/lib/commons/text/accessible-text-virtual.js +5 -5
  125. data/node_modules/axe-core/lib/commons/text/form-control-value.js +18 -30
  126. data/node_modules/axe-core/lib/commons/text/is-icon-ligature.js +210 -0
  127. data/node_modules/axe-core/lib/commons/text/is-valid-autocomplete.js +0 -1
  128. data/node_modules/axe-core/lib/commons/text/label-text.js +1 -1
  129. data/node_modules/axe-core/lib/commons/text/label-virtual.js +1 -1
  130. data/node_modules/axe-core/lib/commons/text/native-text-methods.js +1 -1
  131. data/node_modules/axe-core/lib/commons/text/subtree-text.js +3 -3
  132. data/node_modules/axe-core/lib/commons/text/unicode.js +15 -0
  133. data/node_modules/axe-core/lib/commons/text/visible-text-nodes.js +25 -0
  134. data/node_modules/axe-core/lib/commons/text/visible-virtual.js +1 -1
  135. data/node_modules/axe-core/lib/core/base/audit.js +90 -15
  136. data/node_modules/axe-core/lib/core/base/cache.js +33 -0
  137. data/node_modules/axe-core/lib/core/base/check.js +48 -1
  138. data/node_modules/axe-core/lib/core/base/context.js +15 -14
  139. data/node_modules/axe-core/lib/core/base/rule.js +223 -46
  140. data/node_modules/axe-core/lib/core/base/virtual-node/abstract-virtual-node.js +40 -0
  141. data/node_modules/axe-core/lib/core/base/virtual-node/serial-virtual-node.js +86 -0
  142. data/node_modules/axe-core/lib/core/base/virtual-node/virtual-node.js +85 -0
  143. data/node_modules/axe-core/lib/core/constants.js +10 -2
  144. data/node_modules/axe-core/lib/core/imports/index.js +28 -3
  145. data/node_modules/axe-core/lib/core/index.js +2 -4
  146. data/node_modules/axe-core/lib/core/public/configure.js +28 -1
  147. data/node_modules/axe-core/lib/core/public/run-rules.js +2 -0
  148. data/node_modules/axe-core/lib/core/public/run-virtual-rule.js +50 -0
  149. data/node_modules/axe-core/lib/core/public/run.js +13 -2
  150. data/node_modules/axe-core/lib/core/reporters/helpers/process-aggregate.js +1 -1
  151. data/node_modules/axe-core/lib/core/reporters/na.js +4 -0
  152. data/node_modules/axe-core/lib/core/reporters/raw-env.js +12 -0
  153. data/node_modules/axe-core/lib/core/reporters/raw.js +25 -1
  154. data/node_modules/axe-core/lib/core/utils/are-styles-set.js +4 -7
  155. data/node_modules/axe-core/lib/core/utils/assert.js +12 -0
  156. data/node_modules/axe-core/lib/core/utils/collect-results-from-frames.js +2 -2
  157. data/node_modules/axe-core/lib/core/utils/contains.js +27 -13
  158. data/node_modules/axe-core/lib/core/utils/css-parser.js +2 -0
  159. data/node_modules/axe-core/lib/core/utils/element-matches.js +5 -1
  160. data/node_modules/axe-core/lib/core/utils/escape-selector.js +1 -2
  161. data/node_modules/axe-core/lib/core/utils/flattened-tree.js +47 -61
  162. data/node_modules/axe-core/lib/core/utils/get-check-option.js +0 -1
  163. data/node_modules/axe-core/lib/core/utils/get-friendly-uri-end.js +1 -1
  164. data/node_modules/axe-core/lib/core/utils/get-node-attributes.js +21 -0
  165. data/node_modules/axe-core/lib/core/utils/get-scroll.js +39 -0
  166. data/node_modules/axe-core/lib/core/utils/get-selector.js +9 -6
  167. data/node_modules/axe-core/lib/core/utils/get-stylesheet-factory.js +51 -0
  168. data/node_modules/axe-core/lib/core/utils/get-xpath.js +0 -1
  169. data/node_modules/axe-core/lib/core/utils/is-hidden.js +16 -4
  170. data/node_modules/axe-core/lib/core/utils/is-html-element.js +5 -5
  171. data/node_modules/axe-core/lib/core/utils/is-shadow-root.js +3 -3
  172. data/node_modules/axe-core/lib/core/utils/memoize.js +17 -0
  173. data/node_modules/axe-core/lib/core/utils/parse-crossorigin-stylesheet.js +53 -0
  174. data/node_modules/axe-core/lib/core/utils/parse-sameorigin-stylesheet.js +96 -0
  175. data/node_modules/axe-core/lib/core/utils/parse-stylesheet.js +70 -0
  176. data/node_modules/axe-core/lib/core/utils/performance-timer.js +7 -2
  177. data/node_modules/axe-core/lib/core/utils/preload-cssom.js +77 -281
  178. data/node_modules/axe-core/lib/core/utils/preload.js +49 -23
  179. data/node_modules/axe-core/lib/core/utils/qsa.js +39 -50
  180. data/node_modules/axe-core/lib/core/utils/respondable.js +20 -3
  181. data/node_modules/axe-core/lib/core/utils/rule-should-run.js +0 -1
  182. data/node_modules/axe-core/lib/core/utils/scroll-state.js +12 -25
  183. data/node_modules/axe-core/lib/core/utils/select.js +12 -23
  184. data/node_modules/axe-core/lib/core/utils/uuid.js +1 -2
  185. data/node_modules/axe-core/lib/intro.stub +1 -1
  186. data/node_modules/axe-core/lib/misc/incomplete-fallback.json +1 -1
  187. data/node_modules/axe-core/lib/rules/aria-allowed-attr-matches.js +1 -1
  188. data/node_modules/axe-core/lib/rules/aria-form-field-name-matches.js +50 -0
  189. data/node_modules/axe-core/lib/rules/aria-has-attr-matches.js +1 -1
  190. data/node_modules/axe-core/lib/rules/aria-hidden-focus.json +1 -1
  191. data/node_modules/axe-core/lib/rules/aria-input-field-name.json +13 -0
  192. data/node_modules/axe-core/lib/rules/aria-roledescription.json +12 -0
  193. data/node_modules/axe-core/lib/rules/aria-toggle-field-name.json +18 -0
  194. data/node_modules/axe-core/lib/rules/autocomplete-matches.js +14 -10
  195. data/node_modules/axe-core/lib/rules/avoid-inline-spacing.json +12 -0
  196. data/node_modules/axe-core/lib/rules/button-name.json +3 -5
  197. data/node_modules/axe-core/lib/rules/checkboxgroup.json +2 -1
  198. data/node_modules/axe-core/lib/rules/color-contrast-matches.js +37 -22
  199. data/node_modules/axe-core/lib/rules/duplicate-id-active-matches.js +1 -1
  200. data/node_modules/axe-core/lib/rules/duplicate-id-misc-matches.js +2 -2
  201. data/node_modules/axe-core/lib/rules/form-field-multiple-labels.json +1 -1
  202. data/node_modules/axe-core/lib/rules/html-has-lang.json +1 -0
  203. data/node_modules/axe-core/lib/rules/image-alt.json +1 -1
  204. data/node_modules/axe-core/lib/rules/img-redundant-alt.json +3 -3
  205. data/node_modules/axe-core/lib/rules/input-button-name.json +26 -0
  206. data/node_modules/axe-core/lib/rules/landmark-unique-matches.js +41 -0
  207. data/node_modules/axe-core/lib/rules/landmark-unique.json +13 -0
  208. data/node_modules/axe-core/lib/rules/link-name.json +5 -4
  209. data/node_modules/axe-core/lib/rules/meta-refresh.json +8 -1
  210. data/node_modules/axe-core/lib/rules/radiogroup.json +2 -1
  211. data/node_modules/axe-core/lib/rules/role-img-alt.json +18 -0
  212. data/node_modules/axe-core/lib/rules/scrollable-region-focusable-matches.js +30 -0
  213. data/node_modules/axe-core/lib/rules/scrollable-region-focusable.json +12 -0
  214. data/node_modules/axe-core/lib/rules/skip-link-matches.js +1 -1
  215. data/node_modules/axe-core/lib/rules/skip-link.json +1 -1
  216. data/node_modules/axe-core/lib/rules/video-description.json +3 -1
  217. data/node_modules/axe-core/locales/de.json +1 -5
  218. data/node_modules/axe-core/locales/es.json +773 -0
  219. data/node_modules/axe-core/locales/fr.json +15 -19
  220. data/node_modules/axe-core/locales/ja.json +65 -11
  221. data/node_modules/axe-core/locales/ko.json +777 -0
  222. data/node_modules/axe-core/locales/nl.json +35 -35
  223. data/node_modules/axe-core/locales/pt_BR.json +773 -0
  224. data/node_modules/axe-core/package.json +56 -52
  225. data/node_modules/axe-core/sri-history.json +20 -0
  226. data/node_modules/axe-core/typings/axe-core/axe-core-tests.ts +5 -15
  227. data/node_modules/govuk-frontend/package.json +10 -10
  228. metadata +62 -4
  229. data/node_modules/axe-core/doc/axelogo2018.png +0 -0
  230. data/node_modules/axe-core/lib/rules/role-not-button-matches.js +0 -1
@@ -1,5 +1,4 @@
1
- /*eslint no-bitwise: 0, eqeqeq: 0, curly: 0, strict: 0, no-eq-null: 0,
2
- max-statements: 0, complexity: 0, no-shadow: 0, no-undef: 0 */
1
+ /*eslint no-bitwise: 0, eqeqeq: 0, curly: 0, strict: 0, no-eq-null: 0, no-shadow: 0, no-undef: 0 */
3
2
  // uuid.js
4
3
  //
5
4
  // Copyright (c) 2010-2012 Robert Kieffer
@@ -1,4 +1,4 @@
1
- /*! aXe v<%= pkg.version %>
1
+ /*! axe v<%= pkg.version %>
2
2
  * Copyright (c) <%= grunt.template.today("yyyy") %> Deque Systems, Inc.
3
3
  *
4
4
  * Your use of this Source Code Form is subject to the terms of the Mozilla Public
@@ -1,3 +1,3 @@
1
1
  {
2
- "incompleteFallbackMessage": "aXe couldn't tell the reason. Time to break out the element inspector!"
2
+ "incompleteFallbackMessage": "axe couldn't tell the reason. Time to break out the element inspector!"
3
3
  }
@@ -1,6 +1,6 @@
1
1
  const aria = /^aria-/;
2
2
  if (node.hasAttributes()) {
3
- let attrs = node.attributes;
3
+ let attrs = axe.utils.getNodeAttributes(node);
4
4
  for (let i = 0, l = attrs.length; i < l; i++) {
5
5
  if (aria.test(attrs[i].name)) {
6
6
  return true;
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Note:
3
+ * This rule filters elements with 'role=*' attribute via 'selector'
4
+ * see relevant rule spec for details of 'role(s)' being filtered.
5
+ */
6
+ const { aria } = axe.commons;
7
+
8
+ const nodeName = node.nodeName.toUpperCase();
9
+ const role = aria.getRole(node, { noImplicit: true });
10
+
11
+ /**
12
+ * Ignore elements from rule -> 'area-alt'
13
+ */
14
+ if (nodeName === 'AREA' && !!node.getAttribute('href')) {
15
+ return false;
16
+ }
17
+
18
+ /**
19
+ * Ignore elements from rule -> 'label'
20
+ */
21
+ if (['INPUT', 'SELECT', 'TEXTAREA'].includes(nodeName)) {
22
+ return false;
23
+ }
24
+
25
+ /**
26
+ * Ignore elements from rule -> 'image-alt'
27
+ */
28
+ if (nodeName === 'IMG' || (role === 'img' && nodeName !== 'SVG')) {
29
+ return false;
30
+ }
31
+
32
+ /**
33
+ * Ignore elements from rule -> 'button-name'
34
+ */
35
+ if (nodeName === 'BUTTON' || role === 'button') {
36
+ return false;
37
+ }
38
+
39
+ /**
40
+ * Ignore combobox elements if they have a child input
41
+ * (ARIA 1.1 pattern)
42
+ */
43
+ if (
44
+ role === 'combobox' &&
45
+ axe.utils.querySelectorAll(virtualNode, 'input:not([type="hidden"])').length
46
+ ) {
47
+ return false;
48
+ }
49
+
50
+ return true;
@@ -1,6 +1,6 @@
1
1
  var aria = /^aria-/;
2
2
  if (node.hasAttributes()) {
3
- var attrs = node.attributes;
3
+ var attrs = axe.utils.getNodeAttributes(node);
4
4
  for (var i = 0, l = attrs.length; i < l; i++) {
5
5
  if (aria.test(attrs[i].name)) {
6
6
  return true;
@@ -3,7 +3,7 @@
3
3
  "selector": "[aria-hidden=\"true\"]",
4
4
  "matches": "aria-hidden-focus-matches.js",
5
5
  "excludeHidden": false,
6
- "tags": ["cat.name-role-value", "wcag2a", "wcag412"],
6
+ "tags": ["cat.name-role-value", "wcag2a", "wcag412", "wcag131"],
7
7
  "metadata": {
8
8
  "description": "Ensures aria-hidden elements do not contain focusable elements",
9
9
  "help": "ARIA hidden element must not contain focusable elements"
@@ -0,0 +1,13 @@
1
+ {
2
+ "id": "aria-input-field-name",
3
+ "selector": "[role=\"combobox\"], [role=\"listbox\"], [role=\"searchbox\"], [role=\"slider\"], [role=\"spinbutton\"], [role=\"textbox\"]",
4
+ "matches": "aria-form-field-name-matches.js",
5
+ "tags": ["wcag2a", "wcag412"],
6
+ "metadata": {
7
+ "description": "Ensures every ARIA input field has an accessible name",
8
+ "help": "ARIA input fields have an accessible name"
9
+ },
10
+ "all": [],
11
+ "any": ["aria-label", "aria-labelledby", "non-empty-title"],
12
+ "none": ["no-implicit-explicit-label"]
13
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "id": "aria-roledescription",
3
+ "selector": "[aria-roledescription]",
4
+ "tags": ["cat.aria", "wcag2a", "wcag412"],
5
+ "metadata": {
6
+ "description": "Ensure aria-roledescription is only used on elements with an implicit or explicit role",
7
+ "help": "Use aria-roledescription on elements with a semantic role"
8
+ },
9
+ "all": [],
10
+ "any": ["aria-roledescription"],
11
+ "none": []
12
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "id": "aria-toggle-field-name",
3
+ "selector": "[role=\"checkbox\"], [role=\"menuitemcheckbox\"], [role=\"menuitemradio\"], [role=\"radio\"], [role=\"switch\"]",
4
+ "matches": "aria-form-field-name-matches.js",
5
+ "tags": ["wcag2a", "wcag412"],
6
+ "metadata": {
7
+ "description": "Ensures every ARIA toggle field has an accessible name",
8
+ "help": "ARIA toggle fields have an accessible name"
9
+ },
10
+ "all": [],
11
+ "any": [
12
+ "aria-label",
13
+ "aria-labelledby",
14
+ "non-empty-title",
15
+ "has-visible-text"
16
+ ],
17
+ "none": ["no-implicit-explicit-label"]
18
+ }
@@ -1,31 +1,34 @@
1
1
  const { text, aria, dom } = axe.commons;
2
2
 
3
- const autocomplete = node.getAttribute('autocomplete');
3
+ const autocomplete = virtualNode.attr('autocomplete');
4
4
  if (!autocomplete || text.sanitize(autocomplete) === '') {
5
5
  return false;
6
6
  }
7
7
 
8
- const nodeName = node.nodeName.toUpperCase();
9
- if (['TEXTAREA', 'INPUT', 'SELECT'].includes(nodeName) === false) {
8
+ const nodeName = virtualNode.props.nodeName;
9
+ if (['textarea', 'input', 'select'].includes(nodeName) === false) {
10
10
  return false;
11
11
  }
12
12
 
13
13
  // The element is an `input` element a `type` of `hidden`, `button`, `submit` or `reset`
14
14
  const excludedInputTypes = ['submit', 'reset', 'button', 'hidden'];
15
- if (nodeName === 'INPUT' && excludedInputTypes.includes(node.type)) {
15
+ if (
16
+ nodeName === 'input' &&
17
+ excludedInputTypes.includes(virtualNode.props.type)
18
+ ) {
16
19
  return false;
17
20
  }
18
21
 
19
22
  // The element has a `disabled` or `aria-disabled="true"` attribute
20
- const ariaDisabled = node.getAttribute('aria-disabled') || 'false';
21
- if (node.disabled || ariaDisabled.toLowerCase() === 'true') {
23
+ const ariaDisabled = virtualNode.attr('aria-disabled') || 'false';
24
+ if (virtualNode.hasAttr('disabled') || ariaDisabled.toLowerCase() === 'true') {
22
25
  return false;
23
26
  }
24
27
 
25
28
  // The element has `tabindex="-1"` and has a [[semantic role]] that is
26
29
  // not a [widget](https://www.w3.org/TR/wai-aria-1.1/#widget_roles)
27
- const role = node.getAttribute('role');
28
- const tabIndex = node.getAttribute('tabindex');
30
+ const role = virtualNode.attr('role');
31
+ const tabIndex = virtualNode.attr('tabindex');
29
32
  if (tabIndex === '-1' && role) {
30
33
  const roleDef = aria.lookupTable.role[role];
31
34
  if (roleDef === undefined || roleDef.type !== 'widget') {
@@ -36,8 +39,9 @@ if (tabIndex === '-1' && role) {
36
39
  // The element is **not** visible on the page or exposed to assistive technologies
37
40
  if (
38
41
  tabIndex === '-1' &&
39
- !dom.isVisible(node, false) &&
40
- !dom.isVisible(node, true)
42
+ virtualNode.actualNode &&
43
+ !dom.isVisible(virtualNode.actualNode, false) &&
44
+ !dom.isVisible(virtualNode.actualNode, true)
41
45
  ) {
42
46
  return false;
43
47
  }
@@ -0,0 +1,12 @@
1
+ {
2
+ "id": "avoid-inline-spacing",
3
+ "selector": "[style]",
4
+ "tags": ["wcag21aa", "wcag1412"],
5
+ "metadata": {
6
+ "description": "Ensure that text spacing set through style attributes can be adjusted with custom stylesheets",
7
+ "help": "Inline text spacing must be adjustable with custom stylesheets"
8
+ },
9
+ "all": ["avoid-inline-spacing"],
10
+ "any": [],
11
+ "none": []
12
+ }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "id": "button-name",
3
- "selector": "button, [role=\"button\"], input[type=\"button\"], input[type=\"submit\"], input[type=\"reset\"]",
3
+ "selector": "button, [role=\"button\"]:not(input)",
4
4
  "tags": [
5
5
  "cat.name-role-value",
6
6
  "wcag2a",
@@ -14,8 +14,6 @@
14
14
  },
15
15
  "all": [],
16
16
  "any": [
17
- "non-empty-if-present",
18
- "non-empty-value",
19
17
  "button-has-visible-text",
20
18
  "aria-label",
21
19
  "aria-labelledby",
@@ -23,5 +21,5 @@
23
21
  "role-none",
24
22
  "non-empty-title"
25
23
  ],
26
- "none": ["focusable-no-name"]
27
- }
24
+ "none": []
25
+ }
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "id": "checkboxgroup",
3
3
  "selector": "input[type=checkbox][name]",
4
- "tags": ["cat.forms", "best-practice"],
4
+ "tags": ["cat.forms", "best-practice", "deprecated"],
5
5
  "metadata": {
6
6
  "description": "Ensures related <input type=\"checkbox\"> elements have a group and that the group designation is consistent",
7
7
  "help": "Checkbox inputs with the same name attribute value must be part of a group"
8
8
  },
9
+ "enabled": false,
9
10
  "all": [],
10
11
  "any": ["group-labelledby", "fieldset"],
11
12
  "none": []
@@ -1,7 +1,7 @@
1
1
  /* global document */
2
2
 
3
- var nodeName = node.nodeName.toUpperCase(),
4
- nodeType = node.type;
3
+ const nodeName = node.nodeName.toUpperCase();
4
+ const nodeType = node.type;
5
5
 
6
6
  if (
7
7
  node.getAttribute('aria-disabled') === 'true' ||
@@ -45,28 +45,35 @@ if (
45
45
  }
46
46
 
47
47
  // check if the element is a label or label descendant for a disabled control
48
- var nodeParentLabel = axe.commons.dom.findUpVirtual(virtualNode, 'label');
48
+ const nodeParentLabel = axe.commons.dom.findUpVirtual(virtualNode, 'label');
49
49
  if (nodeName === 'LABEL' || nodeParentLabel) {
50
- var relevantNode = node;
51
- var relevantVirtualNode = virtualNode;
50
+ let relevantNode = node;
51
+ let relevantVirtualNode = virtualNode;
52
52
 
53
53
  if (nodeParentLabel) {
54
54
  relevantNode = nodeParentLabel;
55
55
  // we need an input candidate from a parent to account for label children
56
- relevantVirtualNode = axe.utils.getNodeFromTree(
57
- axe._tree[0],
58
- nodeParentLabel
59
- );
56
+ relevantVirtualNode = axe.utils.getNodeFromTree(nodeParentLabel);
60
57
  }
61
58
  // explicit label of disabled input
62
- let doc = axe.commons.dom.getRootNode(relevantNode);
63
- var candidate =
59
+ const doc = axe.commons.dom.getRootNode(relevantNode);
60
+ let candidate =
64
61
  relevantNode.htmlFor && doc.getElementById(relevantNode.htmlFor);
65
- if (candidate && candidate.disabled) {
62
+ const candidateVirtualNode = axe.utils.getNodeFromTree(candidate);
63
+
64
+ if (
65
+ candidate &&
66
+ (candidate.disabled ||
67
+ candidate.getAttribute('aria-disabled') === 'true' ||
68
+ axe.commons.dom.findUpVirtual(
69
+ candidateVirtualNode,
70
+ '[aria-disabled="true"]'
71
+ ))
72
+ ) {
66
73
  return false;
67
74
  }
68
75
 
69
- var candidate = axe.utils.querySelectorAll(
76
+ candidate = axe.utils.querySelectorAll(
70
77
  relevantVirtualNode,
71
78
  'input:not([type="hidden"]):not([type="image"])' +
72
79
  ':not([type="button"]):not([type="submit"]):not([type="reset"]), select, textarea'
@@ -79,22 +86,30 @@ if (nodeName === 'LABEL' || nodeParentLabel) {
79
86
  // label of disabled control associated w/ aria-labelledby
80
87
  if (node.getAttribute('id')) {
81
88
  const id = axe.utils.escapeSelector(node.getAttribute('id'));
82
- let doc = axe.commons.dom.getRootNode(node);
83
- var candidate = doc.querySelector('[aria-labelledby~=' + id + ']');
89
+ const doc = axe.commons.dom.getRootNode(node);
90
+ const candidate = doc.querySelector('[aria-labelledby~=' + id + ']');
84
91
  if (candidate && candidate.disabled) {
85
92
  return false;
86
93
  }
87
94
  }
88
95
 
89
- if (axe.commons.text.visibleVirtual(virtualNode, false, true) === '') {
96
+ const visibleText = axe.commons.text.visibleVirtual(virtualNode, false, true);
97
+ if (
98
+ visibleText === '' ||
99
+ axe.commons.text.removeUnicode(visibleText, {
100
+ emoji: true,
101
+ nonBmp: true,
102
+ punctuations: true
103
+ }) === ''
104
+ ) {
90
105
  return false;
91
106
  }
92
107
 
93
- var range = document.createRange(),
94
- childNodes = virtualNode.children,
95
- length = childNodes.length,
96
- child,
97
- index;
108
+ const range = document.createRange();
109
+ const childNodes = virtualNode.children;
110
+ let length = childNodes.length;
111
+ let child = null;
112
+ let index = 0;
98
113
 
99
114
  for (index = 0; index < length; index++) {
100
115
  child = childNodes[index];
@@ -107,7 +122,7 @@ for (index = 0; index < length; index++) {
107
122
  }
108
123
  }
109
124
 
110
- var rects = range.getClientRects();
125
+ const rects = range.getClientRects();
111
126
  length = rects.length;
112
127
 
113
128
  for (index = 0; index < length; index++) {
@@ -5,4 +5,4 @@ const idMatchingElms = Array.from(
5
5
  dom.getRootNode(node).querySelectorAll(idSelector)
6
6
  );
7
7
 
8
- return idMatchingElms.some(dom.isFocusable) && !aria.isAccessibleRef(node);
8
+ return !aria.isAccessibleRef(node) && idMatchingElms.some(dom.isFocusable);
@@ -6,6 +6,6 @@ const idMatchingElms = Array.from(
6
6
  );
7
7
 
8
8
  return (
9
- idMatchingElms.every(elm => !dom.isFocusable(elm)) &&
10
- !aria.isAccessibleRef(node)
9
+ !aria.isAccessibleRef(node) &&
10
+ idMatchingElms.every(elm => !dom.isFocusable(elm))
11
11
  );
@@ -5,7 +5,7 @@
5
5
  "tags": ["cat.forms", "wcag2a", "wcag332"],
6
6
  "metadata": {
7
7
  "description": "Ensures form field does not have multiple label elements",
8
- "help": "Form field must not have multiple label elements"
8
+ "help": "Form field should not have multiple label elements"
9
9
  },
10
10
  "all": [],
11
11
  "any": [],
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "id": "html-has-lang",
3
3
  "selector": "html",
4
+ "matches": "window-is-top.js",
4
5
  "tags": ["cat.language", "wcag2a", "wcag311"],
5
6
  "metadata": {
6
7
  "description": "Ensures every HTML document has a lang attribute",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "id": "image-alt",
3
- "selector": "img, [role='img']:not(svg)",
3
+ "selector": "img",
4
4
  "tags": [
5
5
  "cat.text-alternatives",
6
6
  "wcag2a",
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "id": "image-redundant-alt",
3
- "selector": "button, [role=\"button\"], a[href], p, li, td, th",
3
+ "selector": "img",
4
4
  "tags": ["cat.text-alternatives", "best-practice"],
5
5
  "metadata": {
6
- "description": "Ensure button and link text is not repeated as image alternative",
7
- "help": "Text of buttons and links should not be repeated in the image alternative"
6
+ "description": "Ensure image alternative is not repeated as text",
7
+ "help": "Alternative text of images should not be repeated as text"
8
8
  },
9
9
  "all": [],
10
10
  "any": [],
@@ -0,0 +1,26 @@
1
+ {
2
+ "id": "input-button-name",
3
+ "selector": "input[type=\"button\"], input[type=\"submit\"], input[type=\"reset\"]",
4
+ "tags": [
5
+ "cat.name-role-value",
6
+ "wcag2a",
7
+ "wcag412",
8
+ "section508",
9
+ "section508.22.a"
10
+ ],
11
+ "metadata": {
12
+ "description": "Ensures input buttons have discernible text",
13
+ "help": "Input buttons must have discernible text"
14
+ },
15
+ "all": [],
16
+ "any": [
17
+ "non-empty-if-present",
18
+ "non-empty-value",
19
+ "aria-label",
20
+ "aria-labelledby",
21
+ "role-presentation",
22
+ "role-none",
23
+ "non-empty-title"
24
+ ],
25
+ "none": []
26
+ }
@@ -0,0 +1,41 @@
1
+ /*
2
+ * Since this is a best-practice rule, we are filtering elements as dictated by ARIA 1.1 Practices regardless of treatment by browser/AT combinations.
3
+ *
4
+ * Info: https://www.w3.org/TR/wai-aria-practices-1.1/#aria_landmark
5
+ */
6
+ var excludedParentsForHeaderFooterLandmarks = [
7
+ 'article',
8
+ 'aside',
9
+ 'main',
10
+ 'nav',
11
+ 'section'
12
+ ].join(',');
13
+ function isHeaderFooterLandmark(headerFooterElement) {
14
+ return !axe.commons.dom.findUpVirtual(
15
+ headerFooterElement,
16
+ excludedParentsForHeaderFooterLandmarks
17
+ );
18
+ }
19
+
20
+ function isLandmarkVirtual(virtualNode) {
21
+ var { actualNode } = virtualNode;
22
+ var landmarkRoles = axe.commons.aria.getRolesByType('landmark');
23
+ var role = axe.commons.aria.getRole(actualNode);
24
+ if (!role) {
25
+ return false;
26
+ }
27
+
28
+ var nodeName = actualNode.nodeName.toUpperCase();
29
+ if (nodeName === 'HEADER' || nodeName === 'FOOTER') {
30
+ return isHeaderFooterLandmark(virtualNode);
31
+ }
32
+
33
+ if (nodeName === 'SECTION' || nodeName === 'FORM') {
34
+ var accessibleText = axe.commons.text.accessibleTextVirtual(virtualNode);
35
+ return !!accessibleText;
36
+ }
37
+
38
+ return landmarkRoles.indexOf(role) >= 0 || role === 'region';
39
+ }
40
+
41
+ return isLandmarkVirtual(virtualNode) && axe.commons.dom.isVisible(node, true);