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,30 @@
1
1
  /* global axe, color */
2
2
 
3
+ function getOpacity(node) {
4
+ if (!node) {
5
+ return 1;
6
+ }
7
+
8
+ const vNode = axe.utils.getNodeFromTree(node);
9
+
10
+ if (vNode && vNode._opacity !== undefined && vNode._opacity !== null) {
11
+ return vNode._opacity;
12
+ }
13
+
14
+ const nodeStyle = window.getComputedStyle(node);
15
+ const opacity = nodeStyle.getPropertyValue('opacity');
16
+ const finalOpacity = opacity * getOpacity(node.parentElement);
17
+
18
+ // cache the results of the getOpacity check on the parent tree
19
+ // so we don't have to look at the parent tree again for all its
20
+ // descendants
21
+ if (vNode) {
22
+ vNode._opacity = finalOpacity;
23
+ }
24
+
25
+ return finalOpacity;
26
+ }
27
+
3
28
  /**
4
29
  * Returns the flattened foreground color of an element, or null if it can't be determined because
5
30
  * of transparency
@@ -8,22 +33,26 @@
8
33
  * @instance
9
34
  * @param {Element} node
10
35
  * @param {Boolean} noScroll (default false)
36
+ * @param {Color} bgColor
11
37
  * @return {Color|null}
12
38
  */
13
- color.getForegroundColor = function(node, noScroll) {
14
- var nodeStyle = window.getComputedStyle(node);
39
+ color.getForegroundColor = function(node, noScroll, bgColor) {
40
+ const nodeStyle = window.getComputedStyle(node);
15
41
 
16
- var fgColor = new color.Color();
42
+ const fgColor = new color.Color();
17
43
  fgColor.parseRgbString(nodeStyle.getPropertyValue('color'));
18
- var opacity = nodeStyle.getPropertyValue('opacity');
44
+ const opacity = getOpacity(node);
19
45
  fgColor.alpha = fgColor.alpha * opacity;
20
46
  if (fgColor.alpha === 1) {
21
47
  return fgColor;
22
48
  }
23
49
 
24
- var bgColor = color.getBackgroundColor(node, [], noScroll);
50
+ if (!bgColor) {
51
+ bgColor = color.getBackgroundColor(node, [], noScroll);
52
+ }
53
+
25
54
  if (bgColor === null) {
26
- var reason = axe.commons.color.incompleteData.get('bgColor');
55
+ const reason = axe.commons.color.incompleteData.get('bgColor');
27
56
  axe.commons.color.incompleteData.set('fgColor', reason);
28
57
  return null;
29
58
  }
@@ -0,0 +1,22 @@
1
+ /* global color */
2
+
3
+ /**
4
+ * Returns the non-alpha-blended background color of an element
5
+ *
6
+ * @method getOwnBackgroundColor
7
+ * @memberof axe.commons.color
8
+ *
9
+ * @param {Object} elmStyle style of the element
10
+ * @return {Color}
11
+ */
12
+ color.getOwnBackgroundColor = function getOwnBackgroundColor(elmStyle) {
13
+ const bgColor = new color.Color();
14
+ bgColor.parseRgbString(elmStyle.getPropertyValue('background-color'));
15
+
16
+ if (bgColor.alpha !== 0) {
17
+ const opacity = elmStyle.getPropertyValue('opacity');
18
+ bgColor.alpha = bgColor.alpha * opacity;
19
+ }
20
+
21
+ return bgColor;
22
+ };
@@ -11,10 +11,7 @@
11
11
  * @return {HTMLElement|null} Either the matching HTMLElement or `null` if there was no match
12
12
  */
13
13
  dom.findUp = function(element, target) {
14
- return dom.findUpVirtual(
15
- axe.utils.getNodeFromTree(axe._tree[0], element),
16
- target
17
- );
14
+ return dom.findUpVirtual(axe.utils.getNodeFromTree(element), target);
18
15
  };
19
16
 
20
17
  /**
@@ -29,7 +26,6 @@ dom.findUp = function(element, target) {
29
26
  * @return {HTMLElement|null} Either the matching HTMLElement or `null` if there was no match
30
27
  */
31
28
  dom.findUpVirtual = function(element, target) {
32
- /*eslint complexity: ["error", 12]*/
33
29
  let parent;
34
30
 
35
31
  parent = element.actualNode;
@@ -56,6 +52,10 @@ dom.findUpVirtual = function(element, target) {
56
52
  parent !== document.documentElement
57
53
  );
58
54
 
55
+ if (!parent) {
56
+ return null;
57
+ }
58
+
59
59
  if (!axe.utils.matchesSelector(parent, target)) {
60
60
  return null;
61
61
  }
@@ -1,5 +1,4 @@
1
1
  /* global dom */
2
- /*eslint complexity: ["error", 14]*/
3
2
  /**
4
3
  * Get the scroll offset of the document passed in
5
4
  * @method getScrollOffset
@@ -1,7 +1,7 @@
1
1
  /* global dom */
2
2
 
3
3
  /**
4
- * Get all elements (including given node) that are part if the tab order
4
+ * Get all elements (including given node) that are part of the tab order
5
5
  * @method getTabbableElements
6
6
  * @memberof axe.commons.dom
7
7
  * @instance
@@ -29,16 +29,17 @@ function hasChildTextNodes(elm) {
29
29
  * @instance
30
30
  * @param {VirtualNode} elm Virtual Node to search
31
31
  * @param {Boolean} noRecursion If true, only the element is checked, otherwise it will search all child nodes
32
+ * @param {Boolean} ignoreAria if true, ignores `aria label` computation for content deduction
32
33
  * @return {Boolean}
33
34
  */
34
- dom.hasContentVirtual = function(elm, noRecursion) {
35
+ dom.hasContentVirtual = function(elm, noRecursion, ignoreAria) {
35
36
  return (
36
37
  // It has text
37
38
  hasChildTextNodes(elm) ||
38
39
  // It is a graphical element
39
40
  dom.isVisualContent(elm.actualNode) ||
40
41
  // It has an ARIA label
41
- !!aria.labelVirtual(elm) ||
42
+ (!ignoreAria && !!aria.labelVirtual(elm)) ||
42
43
  // or one of it's descendants does
43
44
  (!noRecursion &&
44
45
  elm.children.some(
@@ -56,11 +57,12 @@ dom.hasContentVirtual = function(elm, noRecursion) {
56
57
  * @instance
57
58
  * @param {DOMNode} elm DOMNode element to check
58
59
  * @param {Boolean} noRecursion If true, only the element is checked, otherwise it will search all child nodes
60
+ * @param {Boolean} ignoreAria if true, ignores `aria label` computation for content deduction
59
61
  * @return {Boolean}
60
62
  */
61
- dom.hasContent = function hasContent(elm, noRecursion) {
62
- elm = axe.utils.getNodeFromTree(axe._tree[0], elm);
63
- return dom.hasContentVirtual(elm, noRecursion);
63
+ dom.hasContent = function hasContent(elm, noRecursion, ignoreAria) {
64
+ elm = axe.utils.getNodeFromTree(elm);
65
+ return dom.hasContentVirtual(elm, noRecursion, ignoreAria);
64
66
  };
65
67
 
66
68
  /**
@@ -1,5 +1,4 @@
1
1
  /* global dom */
2
- /* eslint complexity: ["error",20] */
3
2
 
4
3
  /**
5
4
  * Determines if focusing has been disabled on an element.
@@ -9,7 +8,7 @@
9
8
  function focusDisabled(el) {
10
9
  return (
11
10
  el.disabled ||
12
- (dom.isHiddenWithCSS(el) && el.nodeName.toUpperCase() !== 'AREA')
11
+ (el.nodeName.toUpperCase() !== 'AREA' && dom.isHiddenWithCSS(el))
13
12
  );
14
13
  }
15
14
 
@@ -84,7 +83,11 @@ dom.isNativelyFocusable = function(el) {
84
83
  * if its tabindex were removed. Else, false.
85
84
  */
86
85
  dom.insertedIntoFocusOrder = function(el) {
87
- return (
88
- el.tabIndex > -1 && dom.isFocusable(el) && !dom.isNativelyFocusable(el)
89
- );
86
+ let tabIndex = parseInt(el.getAttribute('tabindex'), 10);
87
+
88
+ // an element that has an invalid tabindex will return 0 or -1 based on
89
+ // if it is natively focusable or not, which will always be false for this
90
+ // check as NaN is not > 1
91
+ // @see https://www.w3.org/TR/html51/editing.html#the-tabindex-attribute
92
+ return tabIndex > -1 && dom.isFocusable(el) && !dom.isNativelyFocusable(el);
90
93
  };
@@ -1,4 +1,3 @@
1
- /* eslint complexity: ["error", 13], max-statements: ["error", 25] */
2
1
  /* global dom */
3
2
 
4
3
  /**
@@ -11,6 +10,20 @@
11
10
  * @return {Boolean} the element's hidden status
12
11
  */
13
12
  dom.isHiddenWithCSS = function isHiddenWithCSS(el, descendentVisibilityValue) {
13
+ const vNode = axe.utils.getNodeFromTree(el);
14
+
15
+ if (!vNode) {
16
+ return _isHiddenWithCSS(el, descendentVisibilityValue);
17
+ }
18
+
19
+ if (vNode._isHiddenWithCSS === void 0) {
20
+ vNode._isHiddenWithCSS = _isHiddenWithCSS(el, descendentVisibilityValue);
21
+ }
22
+
23
+ return vNode._isHiddenWithCSS;
24
+ };
25
+
26
+ function _isHiddenWithCSS(el, descendentVisibilityValue) {
14
27
  if (el.nodeType === 9) {
15
28
  // 9 === Node.DOCUMENT
16
29
  return false;
@@ -57,4 +70,4 @@ dom.isHiddenWithCSS = function isHiddenWithCSS(el, descendentVisibilityValue) {
57
70
  return dom.isHiddenWithCSS(parent, visibilityValue);
58
71
  }
59
72
  return false;
60
- };
73
+ }
@@ -17,7 +17,7 @@ function getBlockParent(node) {
17
17
  while (parentBlock && !isBlock(parentBlock)) {
18
18
  parentBlock = dom.getComposedParent(parentBlock);
19
19
  }
20
- return axe.utils.getNodeFromTree(axe._tree[0], parentBlock);
20
+ return axe.utils.getNodeFromTree(parentBlock);
21
21
  }
22
22
 
23
23
  /**
@@ -26,7 +26,6 @@ function getBlockParent(node) {
26
26
  * @return {Boolean} [description]
27
27
  */
28
28
  dom.isInTextBlock = function isInTextBlock(node) {
29
- /* eslint complexity: ["error",17]*/
30
29
  if (isBlock(node)) {
31
30
  // Ignore if the link is a block
32
31
  return false;
@@ -0,0 +1,45 @@
1
+ /* global dom */
2
+
3
+ // test for hrefs that start with # or /# (for angular)
4
+ const isInternalLinkRegex = /^\/?#[^/!]/;
5
+
6
+ /**
7
+ * Determines if element is a skip link
8
+ * @method isSkipLink
9
+ * @memberof axe.commons.dom
10
+ * @instance
11
+ * @param {Element} element
12
+ * @return {Boolean}
13
+ */
14
+ dom.isSkipLink = function(element) {
15
+ if (!isInternalLinkRegex.test(element.getAttribute('href'))) {
16
+ return false;
17
+ }
18
+
19
+ let firstPageLink;
20
+ if (typeof axe._cache.get('firstPageLink') !== 'undefined') {
21
+ firstPageLink = axe._cache.get('firstPageLink');
22
+ } else {
23
+ // define a skip link as any anchor element whose href starts with `#...`
24
+ // and which precedes the first anchor element whose href doesn't start
25
+ // with `#...` (that is, a link to a page)
26
+ firstPageLink = axe.utils.querySelectorAll(
27
+ axe._tree,
28
+ 'a:not([href^="#"]):not([href^="/#"]):not([href^="javascript"])'
29
+ )[0];
30
+
31
+ // null will signify no first page link
32
+ axe._cache.set('firstPageLink', firstPageLink || null);
33
+ }
34
+
35
+ // if there are no page links then all all links will need to be
36
+ // considered as skip links
37
+ if (!firstPageLink) {
38
+ return true;
39
+ }
40
+
41
+ return (
42
+ element.compareDocumentPosition(firstPageLink.actualNode) ===
43
+ element.DOCUMENT_POSITION_FOLLOWING
44
+ );
45
+ };
@@ -1,22 +1,39 @@
1
1
  /* global dom */
2
- /* eslint complexity: ["error", 20] */
2
+ const clipRegex = /rect\s*\(([0-9]+)px,?\s*([0-9]+)px,?\s*([0-9]+)px,?\s*([0-9]+)px\s*\)/;
3
+ const clipPathRegex = /(\w+)\((\d+)/;
3
4
 
4
5
  /**
5
- * Determines if an element is hidden with the clip rect technique
6
+ * Determines if an element is hidden with a clip or clip-path technique
6
7
  * @method isClipped
7
8
  * @memberof axe.commons.dom
8
9
  * @private
9
- * @param {String} clip Computed property value of clip
10
+ * @param {CSSStyleDeclaration} style Computed style
10
11
  * @return {Boolean}
11
12
  */
12
- function isClipped(clip) {
13
+ function isClipped(style) {
13
14
  'use strict';
14
15
 
15
- var matches = clip.match(
16
- /rect\s*\(([0-9]+)px,?\s*([0-9]+)px,?\s*([0-9]+)px,?\s*([0-9]+)px\s*\)/
17
- );
18
- if (matches && matches.length === 5) {
19
- return matches[3] - matches[1] <= 0 && matches[2] - matches[4] <= 0;
16
+ const matchesClip = style.getPropertyValue('clip').match(clipRegex);
17
+ const matchesClipPath = style
18
+ .getPropertyValue('clip-path')
19
+ .match(clipPathRegex);
20
+ if (matchesClip && matchesClip.length === 5) {
21
+ return (
22
+ matchesClip[3] - matchesClip[1] <= 0 &&
23
+ matchesClip[2] - matchesClip[4] <= 0
24
+ );
25
+ }
26
+ if (matchesClipPath) {
27
+ const type = matchesClipPath[1];
28
+ const value = parseInt(matchesClipPath[2], 10);
29
+
30
+ switch (type) {
31
+ case 'inset':
32
+ return value >= 50;
33
+ case 'circle':
34
+ return value === 0;
35
+ default:
36
+ }
20
37
  }
21
38
 
22
39
  return false;
@@ -33,9 +50,9 @@ function isClipped(clip) {
33
50
  * @return {Boolean} The element's visibilty status
34
51
  */
35
52
  dom.isVisible = function(el, screenReader, recursed) {
36
- //eslint complexity: 13
37
53
  'use strict';
38
- var style, nodeName, parent;
54
+ const node = axe.utils.getNodeFromTree(el);
55
+ const cacheName = '_isVisible' + (screenReader ? 'ScreenReader' : '');
39
56
 
40
57
  // 9 === Node.DOCUMENT
41
58
  if (el.nodeType === 9) {
@@ -47,17 +64,21 @@ dom.isVisible = function(el, screenReader, recursed) {
47
64
  el = el.host; // grab the host Node
48
65
  }
49
66
 
50
- style = window.getComputedStyle(el, null);
67
+ if (node && typeof node[cacheName] !== 'undefined') {
68
+ return node[cacheName];
69
+ }
70
+
71
+ const style = window.getComputedStyle(el, null);
51
72
  if (style === null) {
52
73
  return false;
53
74
  }
54
75
 
55
- nodeName = el.nodeName.toUpperCase();
76
+ const nodeName = el.nodeName.toUpperCase();
56
77
 
57
78
  if (
58
79
  style.getPropertyValue('display') === 'none' ||
59
80
  ['STYLE', 'SCRIPT', 'NOSCRIPT', 'TEMPLATE'].includes(nodeName) ||
60
- (!screenReader && isClipped(style.getPropertyValue('clip'))) ||
81
+ (!screenReader && isClipped(style)) ||
61
82
  (!recursed &&
62
83
  // visibility is only accurate on the first element
63
84
  (style.getPropertyValue('visibility') === 'hidden' ||
@@ -68,10 +89,15 @@ dom.isVisible = function(el, screenReader, recursed) {
68
89
  return false;
69
90
  }
70
91
 
71
- parent = el.assignedSlot ? el.assignedSlot : el.parentNode;
92
+ const parent = el.assignedSlot ? el.assignedSlot : el.parentNode;
93
+ let isVisible = false;
72
94
  if (parent) {
73
- return dom.isVisible(parent, screenReader, true);
95
+ isVisible = dom.isVisible(parent, screenReader, true);
74
96
  }
75
97
 
76
- return false;
98
+ if (node) {
99
+ node[cacheName] = isVisible;
100
+ }
101
+
102
+ return isVisible;
77
103
  };
@@ -1,5 +1,4 @@
1
1
  /*global dom */
2
- /*eslint complexity: ["error",20] */
3
2
 
4
3
  const visualRoles = [
5
4
  'checkbox',
@@ -1,5 +1,4 @@
1
1
  /* global dom */
2
- /* eslint complexity: ["error",17] */
3
2
 
4
3
  /**
5
4
  * Checks whether a parent element visually contains its child, either directly or via scrolling.
@@ -1,5 +1,4 @@
1
1
  /* global dom */
2
- /* eslint complexity: ["error",15] */
3
2
 
4
3
  /**
5
4
  * Checks whether a parent element visually overlaps a rectangle, either directly or via scrolling.
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Namespace for forms-related utilities.
3
+ * @namespace commons.forms
4
+ * @memberof axe
5
+ */
6
+
7
+ var forms = {};
8
+ commons.forms = forms;
@@ -0,0 +1,13 @@
1
+ /* global forms */
2
+
3
+ /**
4
+ * Determines if an element is an aria combobox element
5
+ * @method isAriaCombobox
6
+ * @memberof axe.commons.forms
7
+ * @param {Element} node Node to determine if aria combobox
8
+ * @returns {Bool}
9
+ */
10
+ forms.isAriaCombobox = function(node) {
11
+ const role = axe.commons.aria.getRole(node, { noImplicit: true });
12
+ return role === 'combobox';
13
+ };
@@ -0,0 +1,13 @@
1
+ /* global forms */
2
+
3
+ /**
4
+ * Determines if an element is an aria listbox element
5
+ * @method isAriaListbox
6
+ * @memberof axe.commons.forms
7
+ * @param {Element} node Node to determine if aria listbox
8
+ * @returns {Bool}
9
+ */
10
+ forms.isAriaListbox = function(node) {
11
+ const role = axe.commons.aria.getRole(node, { noImplicit: true });
12
+ return role === 'listbox';
13
+ };