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,4 +1,6 @@
1
- var nn = node.nodeName.toLowerCase();
2
- return (
3
- node.hasAttribute('alt') && (nn === 'img' || nn === 'input' || nn === 'area')
4
- );
1
+ const { nodeName } = virtualNode.props;
2
+ if (!['img', 'input', 'area'].includes(nodeName)) {
3
+ return false;
4
+ }
5
+
6
+ return virtualNode.hasAttr('alt');
@@ -1,2 +1,2 @@
1
- var label = node.getAttribute('alt');
1
+ const label = virtualNode.attr('alt');
2
2
  return !!(label ? axe.commons.text.sanitize(label).trim() : '');
@@ -5,7 +5,7 @@
5
5
  "impact": "serious",
6
6
  "messages": {
7
7
  "pass": "The first row of a table is not used as a caption",
8
- "fail": "The first row of the table should be a caption instead of a table cell"
8
+ "fail": "The first child of the table should be a caption instead of a table cell"
9
9
  }
10
10
  }
11
11
  }
@@ -1,6 +1,7 @@
1
- var tableUtils = axe.commons.table;
2
- var badCells = [];
3
- var cells = tableUtils.getAllCells(node);
1
+ const tableUtils = axe.commons.table;
2
+ const badCells = [];
3
+ const cells = tableUtils.getAllCells(node);
4
+ const tableGrid = tableUtils.toGrid(node);
4
5
 
5
6
  cells.forEach(cell => {
6
7
  // For each non-empty data cell that doesn't have an aria label
@@ -10,7 +11,7 @@ cells.forEach(cell => {
10
11
  !axe.commons.aria.label(cell)
11
12
  ) {
12
13
  // Check if it has any headers
13
- const hasHeaders = tableUtils.getHeaders(cell).some(header => {
14
+ const hasHeaders = tableUtils.getHeaders(cell, tableGrid).some(header => {
14
15
  return header !== null && !!axe.commons.dom.hasContent(header);
15
16
  });
16
17
 
@@ -1,23 +1,23 @@
1
- var tableUtils = axe.commons.table;
2
- var cells = tableUtils.getAllCells(node);
3
- var checkResult = this;
1
+ const tableUtils = axe.commons.table;
2
+ const cells = tableUtils.getAllCells(node);
3
+ const checkResult = this;
4
4
 
5
5
  // Get a list of all headers reffed to in this rule
6
- var reffedHeaders = [];
6
+ let reffedHeaders = [];
7
7
  cells.forEach(function(cell) {
8
- var headers = cell.getAttribute('headers');
8
+ const headers = cell.getAttribute('headers');
9
9
  if (headers) {
10
10
  reffedHeaders = reffedHeaders.concat(headers.split(/\s+/));
11
11
  }
12
12
 
13
- var ariaLabel = cell.getAttribute('aria-labelledby');
13
+ const ariaLabel = cell.getAttribute('aria-labelledby');
14
14
  if (ariaLabel) {
15
15
  reffedHeaders = reffedHeaders.concat(ariaLabel.split(/\s+/));
16
16
  }
17
17
  });
18
18
 
19
19
  // Get all the headers
20
- var headers = cells.filter(function(cell) {
20
+ const headers = cells.filter(function(cell) {
21
21
  if (axe.commons.text.sanitize(cell.textContent) === '') {
22
22
  return false;
23
23
  }
@@ -27,42 +27,32 @@ var headers = cells.filter(function(cell) {
27
27
  );
28
28
  });
29
29
 
30
- var tableGrid = tableUtils.toGrid(node);
30
+ const tableGrid = tableUtils.toGrid(node);
31
31
 
32
- // Look for all the bad headers
33
- var out = headers.reduce(function(res, header) {
32
+ let out = true;
33
+ headers.forEach(header => {
34
34
  if (
35
35
  header.getAttribute('id') &&
36
36
  reffedHeaders.includes(header.getAttribute('id'))
37
37
  ) {
38
- return !res ? res : true;
38
+ return;
39
39
  }
40
40
 
41
- var hasCell = false;
42
- var pos = tableUtils.getCellPosition(header, tableGrid);
41
+ const pos = tableUtils.getCellPosition(header, tableGrid);
43
42
 
44
- // Look for any data cells or row headers that this might refer to
43
+ // ensure column header has at least 1 non-header cell
44
+ let hasCell = false;
45
45
  if (tableUtils.isColumnHeader(header)) {
46
46
  hasCell = tableUtils
47
47
  .traverse('down', pos, tableGrid)
48
- .reduce((out, cell) => {
49
- return (
50
- out ||
51
- (axe.commons.dom.hasContent(cell) && !tableUtils.isColumnHeader(cell))
52
- );
53
- }, false);
48
+ .find(cell => !tableUtils.isColumnHeader(cell));
54
49
  }
55
50
 
56
- // Look for any data cells or column headers that this might refer to
51
+ // ensure row header has at least 1 non-header cell
57
52
  if (!hasCell && tableUtils.isRowHeader(header)) {
58
53
  hasCell = tableUtils
59
54
  .traverse('right', pos, tableGrid)
60
- .reduce((out, cell) => {
61
- return (
62
- out ||
63
- (axe.commons.dom.hasContent(cell) && !tableUtils.isRowHeader(cell))
64
- );
65
- }, false);
55
+ .find(cell => !tableUtils.isRowHeader(cell));
66
56
  }
67
57
 
68
58
  // report the node as having failed
@@ -70,7 +60,7 @@ var out = headers.reduce(function(res, header) {
70
60
  checkResult.relatedNodes(header);
71
61
  }
72
62
 
73
- return res && hasCell;
74
- }, true);
63
+ out = out && hasCell;
64
+ });
75
65
 
76
66
  return out ? true : undefined;
@@ -16,7 +16,7 @@ aria.getOwnedVirtual = function getOwned({ actualNode, children }) {
16
16
 
17
17
  return dom.idrefs(actualNode, 'aria-owns').reduce((ownedElms, element) => {
18
18
  if (element) {
19
- const virtualNode = axe.utils.getNodeFromTree(axe._tree[0], element);
19
+ const virtualNode = axe.utils.getNodeFromTree(element);
20
20
  ownedElms.push(virtualNode);
21
21
  }
22
22
  return ownedElms;
@@ -198,20 +198,7 @@ lookupTable.attributes = {
198
198
  'aria-roledescription': {
199
199
  type: 'string',
200
200
  allowEmpty: true,
201
- unsupported: {
202
- exceptions: [
203
- 'button',
204
- {
205
- nodeName: 'input',
206
- properties: {
207
- type: ['button', 'checkbox', 'image', 'radio', 'reset', 'submit']
208
- }
209
- },
210
- 'img',
211
- 'select',
212
- 'summary'
213
- ]
214
- }
201
+ unsupported: false
215
202
  },
216
203
  'aria-rowcount': {
217
204
  type: 'int',
@@ -455,7 +442,7 @@ lookupTable.role = {
455
442
  {
456
443
  nodeName: 'input',
457
444
  properties: {
458
- type: 'text'
445
+ type: ['text', 'search', 'tel', 'url', 'email']
459
446
  }
460
447
  }
461
448
  ]
@@ -624,7 +611,9 @@ lookupTable.role = {
624
611
  attributes: {
625
612
  allowed: ['aria-expanded', 'aria-errormessage']
626
613
  },
627
- owned: null,
614
+ owned: {
615
+ one: ['doc-biblioentry']
616
+ },
628
617
  nameFrom: ['author'],
629
618
  context: null,
630
619
  unsupported: false,
@@ -746,7 +735,9 @@ lookupTable.role = {
746
735
  attributes: {
747
736
  allowed: ['aria-expanded', 'aria-errormessage']
748
737
  },
749
- owned: ['doc-endnote'],
738
+ owned: {
739
+ one: ['doc-endnote']
740
+ },
750
741
  namefrom: ['author'],
751
742
  context: null,
752
743
  unsupported: false,
@@ -1024,7 +1015,7 @@ lookupTable.role = {
1024
1015
  },
1025
1016
  figure: {
1026
1017
  type: 'structure',
1027
- unsupported: true
1018
+ unsupported: false
1028
1019
  },
1029
1020
  form: {
1030
1021
  type: 'landmark',
@@ -1174,6 +1165,7 @@ lookupTable.role = {
1174
1165
  allowed: [
1175
1166
  'aria-activedescendant',
1176
1167
  'aria-multiselectable',
1168
+ 'aria-readonly',
1177
1169
  'aria-required',
1178
1170
  'aria-expanded',
1179
1171
  'aria-orientation',
@@ -1280,7 +1272,9 @@ lookupTable.role = {
1280
1272
  'aria-errormessage'
1281
1273
  ]
1282
1274
  },
1283
- owned: null,
1275
+ owned: {
1276
+ one: ['menuitem', 'menuitemradio', 'menuitemcheckbox']
1277
+ },
1284
1278
  nameFrom: ['author'],
1285
1279
  context: null,
1286
1280
  unsupported: false,
@@ -1550,9 +1544,9 @@ lookupTable.role = {
1550
1544
  'aria-posinset',
1551
1545
  'aria-setsize',
1552
1546
  'aria-required',
1553
- 'aria-errormessage'
1554
- ],
1555
- required: ['aria-checked']
1547
+ 'aria-errormessage',
1548
+ 'aria-checked'
1549
+ ]
1556
1550
  },
1557
1551
  owned: null,
1558
1552
  nameFrom: ['author', 'contents'],
@@ -1653,7 +1647,7 @@ lookupTable.role = {
1653
1647
  all: ['row']
1654
1648
  },
1655
1649
  nameFrom: ['author', 'contents'],
1656
- context: ['grid', 'table'],
1650
+ context: ['grid', 'table', 'treegrid'],
1657
1651
  implicit: ['tbody', 'thead', 'tfoot'],
1658
1652
  unsupported: false
1659
1653
  },
@@ -1682,13 +1676,14 @@ lookupTable.role = {
1682
1676
  scrollbar: {
1683
1677
  type: 'widget',
1684
1678
  attributes: {
1685
- required: [
1686
- 'aria-controls',
1687
- 'aria-valuenow',
1679
+ required: ['aria-controls', 'aria-valuenow'],
1680
+ allowed: [
1681
+ 'aria-valuetext',
1682
+ 'aria-orientation',
1683
+ 'aria-errormessage',
1688
1684
  'aria-valuemax',
1689
1685
  'aria-valuemin'
1690
- ],
1691
- allowed: ['aria-valuetext', 'aria-orientation', 'aria-errormessage']
1686
+ ]
1692
1687
  },
1693
1688
  owned: null,
1694
1689
  nameFrom: ['author'],
@@ -1775,9 +1770,11 @@ lookupTable.role = {
1775
1770
  'aria-valuetext',
1776
1771
  'aria-orientation',
1777
1772
  'aria-readonly',
1778
- 'aria-errormessage'
1773
+ 'aria-errormessage',
1774
+ 'aria-valuemax',
1775
+ 'aria-valuemin'
1779
1776
  ],
1780
- required: ['aria-valuenow', 'aria-valuemax', 'aria-valuemin']
1777
+ required: ['aria-valuenow']
1781
1778
  },
1782
1779
  owned: null,
1783
1780
  nameFrom: ['author'],
@@ -1792,9 +1789,11 @@ lookupTable.role = {
1792
1789
  'aria-valuetext',
1793
1790
  'aria-required',
1794
1791
  'aria-readonly',
1795
- 'aria-errormessage'
1792
+ 'aria-errormessage',
1793
+ 'aria-valuemax',
1794
+ 'aria-valuemin'
1796
1795
  ],
1797
- required: ['aria-valuenow', 'aria-valuemax', 'aria-valuemin']
1796
+ required: ['aria-valuenow']
1798
1797
  },
1799
1798
  owned: null,
1800
1799
  nameFrom: ['author'],
@@ -2147,15 +2146,6 @@ lookupTable.elementsAllowedNoRole = [
2147
2146
  ]
2148
2147
  }
2149
2148
  },
2150
- {
2151
- nodeName: 'input',
2152
- attributes: {
2153
- list: isNull
2154
- },
2155
- properties: {
2156
- type: ['email', 'search', 'tel', 'url']
2157
- }
2158
- },
2159
2149
  {
2160
2150
  nodeName: 'link',
2161
2151
  attributes: {
@@ -2244,6 +2234,12 @@ lookupTable.elementsAllowedAnyRole = [
2244
2234
  href: isNull
2245
2235
  }
2246
2236
  },
2237
+ {
2238
+ nodeName: 'img',
2239
+ attributes: {
2240
+ alt: isNull
2241
+ }
2242
+ },
2247
2243
  {
2248
2244
  nodeName: [
2249
2245
  'abbr',
@@ -2311,11 +2307,15 @@ lookupTable.evaluateRoleForElement = {
2311
2307
  }
2312
2308
  return out;
2313
2309
  },
2314
- IMG: ({ node, out }) => {
2315
- if (node.alt) {
2316
- return !out;
2310
+ IMG: ({ node, role, out }) => {
2311
+ switch (node.alt) {
2312
+ case null:
2313
+ return out;
2314
+ case '':
2315
+ return role === 'presentation' || role === 'none';
2316
+ default:
2317
+ return role !== 'presentation' && role !== 'none';
2317
2318
  }
2318
- return out;
2319
2319
  },
2320
2320
  INPUT: ({ node, role, out }) => {
2321
2321
  switch (node.type) {
@@ -2333,6 +2333,11 @@ lookupTable.evaluateRoleForElement = {
2333
2333
  return (
2334
2334
  role === 'combobox' || role === 'searchbox' || role === 'spinbutton'
2335
2335
  );
2336
+ case 'tel':
2337
+ case 'url':
2338
+ case 'search':
2339
+ case 'email':
2340
+ return role === 'combobox';
2336
2341
  default:
2337
2342
  return false;
2338
2343
  }
@@ -2391,7 +2396,6 @@ lookupTable.rolesOfType = {
2391
2396
  'checkbox',
2392
2397
  'dialog',
2393
2398
  'gridcell',
2394
- 'heading',
2395
2399
  'link',
2396
2400
  'log',
2397
2401
  'marquee',
@@ -1,13 +1,33 @@
1
1
  /* global aria, axe, dom */
2
- function findDomNode(node, functor) {
3
- if (functor(node)) {
4
- return node;
2
+ const idRefsRegex = /^idrefs?$/;
3
+
4
+ function cacheIdRefs(node, refAttrs) {
5
+ if (node.hasAttribute) {
6
+ const idRefs = axe._cache.get('idRefs');
7
+
8
+ if (node.nodeName.toUpperCase() === 'LABEL' && node.hasAttribute('for')) {
9
+ idRefs[node.getAttribute('for')] = true;
10
+ }
11
+
12
+ for (let i = 0; i < refAttrs.length; ++i) {
13
+ const attr = refAttrs[i];
14
+
15
+ if (!node.hasAttribute(attr)) {
16
+ continue;
17
+ }
18
+
19
+ const attrValue = node.getAttribute(attr);
20
+
21
+ const tokens = axe.utils.tokenList(attrValue);
22
+
23
+ for (let k = 0; k < tokens.length; ++k) {
24
+ idRefs[tokens[k]] = true;
25
+ }
26
+ }
5
27
  }
28
+
6
29
  for (let i = 0; i < node.children.length; i++) {
7
- const out = findDomNode(node.children[i], functor);
8
- if (out) {
9
- return out;
10
- }
30
+ cacheIdRefs(node.children[i], refAttrs);
11
31
  }
12
32
  }
13
33
 
@@ -22,34 +42,18 @@ aria.isAccessibleRef = function isAccessibleRef(node) {
22
42
  root = root.documentElement || root; // account for shadow roots
23
43
  const id = node.id;
24
44
 
25
- // Get all idref(s) attributes on the lookup table
26
- const refAttrs = Object.keys(aria.lookupTable.attributes).filter(attr => {
27
- const { type } = aria.lookupTable.attributes[attr];
28
- return /^idrefs?$/.test(type);
29
- });
30
-
31
- // Find the first element that IDREF(S) the node
32
- let refElm = findDomNode(root, elm => {
33
- if (elm.nodeType !== 1) {
34
- // Elements only
35
- return;
36
- }
37
- if (
38
- elm.nodeName.toUpperCase() === 'LABEL' &&
39
- elm.getAttribute('for') === id
40
- ) {
41
- return true;
42
- }
43
- // See if there are any aria attributes that reference the node
44
- return refAttrs
45
- .filter(attr => elm.hasAttribute(attr))
46
- .some(attr => {
47
- const attrValue = elm.getAttribute(attr);
48
- if (aria.lookupTable.attributes[attr].type === 'idref') {
49
- return attrValue === id;
50
- }
51
- return axe.utils.tokenList(attrValue).includes(id);
52
- });
53
- });
54
- return typeof refElm !== 'undefined';
45
+ // because axe.commons is not available in axe.utils, we can't do
46
+ // this caching when we build up the virtual tree
47
+ if (!axe._cache.get('idRefs')) {
48
+ axe._cache.set('idRefs', {});
49
+ // Get all idref(s) attributes on the lookup table
50
+ const refAttrs = Object.keys(aria.lookupTable.attributes).filter(attr => {
51
+ const { type } = aria.lookupTable.attributes[attr];
52
+ return idRefsRegex.test(type);
53
+ });
54
+
55
+ cacheIdRefs(root, refAttrs);
56
+ }
57
+
58
+ return axe._cache.get('idRefs')[id] === true;
55
59
  };