govuk_publishing_components 21.16.3 → 21.17.0

Sign up to get free protection for your applications and to get access to all the features.
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);