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,7 @@
1
1
  (function(axe) {
2
2
  var parser = new axe.imports.CssSelectorParser();
3
+ parser.registerSelectorPseudos('not');
3
4
  parser.registerNestingOperators('>');
5
+ parser.registerAttrEqualityMods('^', '$', '*');
4
6
  axe.utils.cssParser = parser;
5
7
  })(axe);
@@ -34,6 +34,10 @@ axe.utils.matchesSelector = (function() {
34
34
  method = getMethod(node);
35
35
  }
36
36
 
37
- return node[method](selector);
37
+ if (node[method]) {
38
+ return node[method](selector);
39
+ }
40
+
41
+ return false;
38
42
  };
39
43
  })();
@@ -7,8 +7,7 @@
7
7
  */
8
8
  axe.utils.escapeSelector = function(value) {
9
9
  'use strict';
10
- /*eslint no-bitwise: 0, eqeqeq: 0, complexity: ["error",27],
11
- max-statements:["error", 25], one-var: 0, -W041: 0 */
10
+ /*eslint no-bitwise: 0, eqeqeq: 0, one-var: 0 */
12
11
  var string = String(value);
13
12
  var length = string.length;
14
13
  var index = -1;
@@ -1,3 +1,4 @@
1
+ /* global VirtualNode */
1
2
  /*eslint no-use-before-define: 0*/
2
3
  var axe = axe || { utils: {} };
3
4
 
@@ -19,36 +20,6 @@ var axe = axe || { utils: {} };
19
20
  * the spec for this)
20
21
  */
21
22
 
22
- /**
23
- * Wrap the real node and provide list of the flattened children
24
- *
25
- * @param node {Node} - the node in question
26
- * @param shadowId {String} - the ID of the shadow DOM to which this node belongs
27
- * @return {Object} - the wrapped node
28
- */
29
- function virtualDOMfromNode(node, shadowId) {
30
- const vNodeCache = {};
31
- return {
32
- shadowId: shadowId,
33
- children: [],
34
- actualNode: node,
35
- get isFocusable() {
36
- if (!vNodeCache._isFocusable) {
37
- vNodeCache._isFocusable = axe.commons.dom.isFocusable(node);
38
- }
39
- return vNodeCache._isFocusable;
40
- },
41
- get tabbableElements() {
42
- if (!vNodeCache._tabbableElements) {
43
- vNodeCache._tabbableElements = axe.commons.dom.getTabbableElements(
44
- this
45
- );
46
- }
47
- return vNodeCache._tabbableElements;
48
- }
49
- };
50
- }
51
-
52
23
  /**
53
24
  * find all the fallback content for a <slot> and return these as an array
54
25
  * this array will also include any #text nodes
@@ -74,13 +45,13 @@ function getSlotChildren(node) {
74
45
  * @param {Node} node the current node
75
46
  * @param {String} shadowId, optional ID of the shadow DOM that is the closest shadow
76
47
  * ancestor of the node
48
+ * @param {VirtualNode} parent the parent VirtualNode
77
49
  */
78
- axe.utils.getFlattenedTree = function(node, shadowId) {
50
+ function flattenTree(node, shadowId, parent) {
79
51
  // using a closure here and therefore cannot easily refactor toreduce the statements
80
- /*eslint max-statements: ["error", 31] */
81
52
  var retVal, realArray, nodeName;
82
- function reduceShadowDOM(res, child) {
83
- var replacements = axe.utils.getFlattenedTree(child, shadowId);
53
+ function reduceShadowDOM(res, child, parent) {
54
+ var replacements = flattenTree(child, shadowId, parent);
84
55
  if (replacements) {
85
56
  res = res.concat(replacements);
86
57
  }
@@ -96,19 +67,27 @@ axe.utils.getFlattenedTree = function(node, shadowId) {
96
67
  if (axe.utils.isShadowRoot(node)) {
97
68
  // generate an ID for this shadow root and overwrite the current
98
69
  // closure shadowId with this value so that it cascades down the tree
99
- retVal = virtualDOMfromNode(node, shadowId);
70
+ retVal = new VirtualNode(node, parent, shadowId);
100
71
  shadowId =
101
72
  'a' +
102
73
  Math.random()
103
74
  .toString()
104
75
  .substring(2);
105
76
  realArray = Array.from(node.shadowRoot.childNodes);
106
- retVal.children = realArray.reduce(reduceShadowDOM, []);
77
+ retVal.children = realArray.reduce((res, child) => {
78
+ return reduceShadowDOM(res, child, retVal);
79
+ }, []);
80
+
107
81
  return [retVal];
108
82
  } else {
109
- if (nodeName === 'content') {
83
+ if (
84
+ nodeName === 'content' &&
85
+ typeof node.getDistributedNodes === 'function'
86
+ ) {
110
87
  realArray = Array.from(node.getDistributedNodes());
111
- return realArray.reduce(reduceShadowDOM, []);
88
+ return realArray.reduce((res, child) => {
89
+ return reduceShadowDOM(res, child, parent);
90
+ }, []);
112
91
  } else if (
113
92
  nodeName === 'slot' &&
114
93
  typeof node.assignedNodes === 'function'
@@ -123,48 +102,55 @@ axe.utils.getFlattenedTree = function(node, shadowId) {
123
102
  if (false && styl.display !== 'contents') {
124
103
  // intentionally commented out
125
104
  // has a box
126
- retVal = virtualDOMfromNode(node, shadowId);
127
- retVal.children = realArray.reduce(reduceShadowDOM, []);
105
+ retVal = new VirtualNode(node, parent, shadowId);
106
+ retVal.children = realArray.reduce((res, child) => {
107
+ return reduceShadowDOM(res, child, retVal);
108
+ }, []);
109
+
128
110
  return [retVal];
129
111
  } else {
130
- return realArray.reduce(reduceShadowDOM, []);
112
+ return realArray.reduce((res, child) => {
113
+ return reduceShadowDOM(res, child, parent);
114
+ }, []);
131
115
  }
132
116
  } else {
133
117
  if (node.nodeType === 1) {
134
- retVal = virtualDOMfromNode(node, shadowId);
118
+ retVal = new VirtualNode(node, parent, shadowId);
135
119
  realArray = Array.from(node.childNodes);
136
- retVal.children = realArray.reduce(reduceShadowDOM, []);
120
+ retVal.children = realArray.reduce((res, child) => {
121
+ return reduceShadowDOM(res, child, retVal);
122
+ }, []);
123
+
137
124
  return [retVal];
138
125
  } else if (node.nodeType === 3) {
139
126
  // text
140
- return [virtualDOMfromNode(node)];
127
+ return [new VirtualNode(node, parent)];
141
128
  }
142
129
  return undefined;
143
130
  }
144
131
  }
132
+ }
133
+
134
+ /**
135
+ * Recursvely returns an array of the virtual DOM nodes at this level
136
+ * excluding comment nodes and the shadow DOM nodes <content> and <slot>
137
+ *
138
+ * @param {Node} node the current node
139
+ * @param {String} shadowId, optional ID of the shadow DOM that is the closest shadow
140
+ * ancestor of the node
141
+ */
142
+ axe.utils.getFlattenedTree = function(node, shadowId) {
143
+ axe._cache.set('nodeMap', new WeakMap());
144
+ return flattenTree(node, shadowId);
145
145
  };
146
146
 
147
147
  /**
148
- * Recursively return a single node from a virtual dom tree
148
+ * Return a single node from the virtual dom tree
149
149
  *
150
150
  * @param {Object} vNode The flattened, virtual DOM tree
151
151
  * @param {Node} node The HTML DOM node
152
152
  */
153
153
  axe.utils.getNodeFromTree = function(vNode, node) {
154
- var found;
155
-
156
- if (vNode.actualNode === node) {
157
- return vNode;
158
- }
159
- vNode.children.forEach(candidate => {
160
- if (found) {
161
- return;
162
- }
163
- if (candidate.actualNode === node) {
164
- found = candidate;
165
- } else {
166
- found = axe.utils.getNodeFromTree(candidate, node);
167
- }
168
- });
169
- return found;
154
+ const el = node || vNode;
155
+ return axe._cache.get('nodeMap') ? axe._cache.get('nodeMap').get(el) : null;
170
156
  };
@@ -1,4 +1,3 @@
1
- /*eslint complexity: ["error", 12]*/
2
1
  /**
3
2
  * Determines which CheckOption to use, either defined on the rule options, global check options or the check itself
4
3
  * @param {Check} check The Check object
@@ -1,4 +1,4 @@
1
- /* eslint max-statements:["error",18], complexity:["error",27], no-script-url:0 */
1
+ /* eslint no-script-url:0 */
2
2
  /**
3
3
  * Check if a string contains mostly numbers
4
4
  */
@@ -0,0 +1,21 @@
1
+ /* global axe */
2
+
3
+ /**
4
+ * Return the list of attributes of a node.
5
+ * @method getNodeAttributes
6
+ * @memberof axe.utils
7
+ * @param {Element} node
8
+ * @returns {NamedNodeMap}
9
+ */
10
+ axe.utils.getNodeAttributes = function getNodeAttributes(node) {
11
+ // eslint-disable-next-line no-restricted-syntax
12
+ if (node.attributes instanceof window.NamedNodeMap) {
13
+ // eslint-disable-next-line no-restricted-syntax
14
+ return node.attributes;
15
+ }
16
+
17
+ // if the attributes property is not of type NamedNodeMap then the DOM
18
+ // has been clobbered. E.g. <form><input name="attributes"></form>.
19
+ // We can clone the node to isolate it and then return the attributes
20
+ return node.cloneNode(false).attributes;
21
+ };
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Get the scroll position of given element
3
+ * @method getScroll
4
+ * @memberof axe.utils
5
+ * @param {Element} node
6
+ * @param {buffer} (Optional) allowed negligence in overflow
7
+ * @returns {Object | undefined}
8
+ */
9
+ axe.utils.getScroll = function getScroll(elm, buffer = 0) {
10
+ const overflowX = elm.scrollWidth > elm.clientWidth + buffer;
11
+ const overflowY = elm.scrollHeight > elm.clientHeight + buffer;
12
+
13
+ /**
14
+ * if there is neither `overflow-x` or `overflow-y`
15
+ * -> return
16
+ */
17
+ if (!(overflowX || overflowY)) {
18
+ return;
19
+ }
20
+
21
+ const style = window.getComputedStyle(elm);
22
+ const overflowXStyle = style.getPropertyValue('overflow-x');
23
+ const overflowYStyle = style.getPropertyValue('overflow-y');
24
+ const scrollableX =
25
+ overflowXStyle !== 'visible' && overflowXStyle !== 'hidden';
26
+ const scrollableY =
27
+ overflowYStyle !== 'visible' && overflowYStyle !== 'hidden';
28
+
29
+ /**
30
+ * check direction of `overflow` and `scrollable`
31
+ */
32
+ if ((overflowX && scrollableX) || (overflowY && scrollableY)) {
33
+ return {
34
+ elm,
35
+ top: elm.scrollTop,
36
+ left: elm.scrollLeft
37
+ };
38
+ }
39
+ };
@@ -79,7 +79,7 @@ function filterAttributes(at) {
79
79
  * the counts for how many elements with that feature exist
80
80
  */
81
81
  axe.utils.getSelectorData = function(domTree) {
82
- /* eslint max-statements:["error", 22], no-loop-func:0*/
82
+ /* eslint no-loop-func:0*/
83
83
 
84
84
  // Initialize the return structure with the three maps
85
85
  let data = {
@@ -119,8 +119,8 @@ axe.utils.getSelectorData = function(domTree) {
119
119
  }
120
120
 
121
121
  // count all the filtered attributes
122
- if (node.attributes) {
123
- Array.from(node.attributes)
122
+ if (node.hasAttributes()) {
123
+ Array.from(axe.utils.getNodeAttributes(node))
124
124
  .filter(filterAttributes)
125
125
  .forEach(at => {
126
126
  let atnv = getAttributeNameValue(node, at);
@@ -238,8 +238,8 @@ function uncommonAttributes(node, selectorData) {
238
238
  let attData = selectorData.attributes;
239
239
  let tagData = selectorData.tags;
240
240
 
241
- if (node.attributes) {
242
- Array.from(node.attributes)
241
+ if (node.hasAttributes()) {
242
+ Array.from(axe.utils.getNodeAttributes(node))
243
243
  .filter(filterAttributes)
244
244
  .forEach(at => {
245
245
  const atnv = getAttributeNameValue(node, at);
@@ -334,7 +334,7 @@ function getThreeLeastCommonFeatures(elm, selectorData) {
334
334
  */
335
335
 
336
336
  function generateSelector(elm, options, doc) {
337
- /*eslint max-statements:["error", 22], no-loop-func:0*/
337
+ /*eslint no-loop-func:0*/
338
338
  if (!axe._selectorData) {
339
339
  throw new Error('Expect axe._selectorData to be set up');
340
340
  }
@@ -392,6 +392,9 @@ axe.utils.getSelector = function createUniqueSelector(elm, options = {}) {
392
392
  // DOCUMENT_FRAGMENT
393
393
  let stack = [];
394
394
  while (doc.nodeType === 11) {
395
+ if (!doc.host) {
396
+ return '';
397
+ }
395
398
  stack.push({ elm: elm, doc: doc });
396
399
  elm = doc.host;
397
400
  doc = elm.getRootNode();
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Function which converts given text to `CSSStyleSheet`
3
+ * - used in `CSSOM` computation.
4
+ * - factory (closure) function, initialized with `document.implementation.createHTMLDocument()`, which uses DOM API for creating `style` elements.
5
+ *
6
+ * @method axe.utils.getStyleSheetFactory
7
+ * @memberof axe.utils
8
+ * @param {Object} dynamicDoc `document.implementation.createHTMLDocument()
9
+ * @param {Object} options an object with properties to construct stylesheet
10
+ * @property {String} options.data text content of the stylesheet
11
+ * @property {Boolean} options.isCrossOrigin flag to notify if the resource was fetched from the network
12
+ * @property {String} options.shadowId (Optional) shadowId if shadowDOM
13
+ * @property {Object} options.root implementation document to create style elements
14
+ * @property {String} options.priority a number indicating the loaded priority of CSS, to denote specificity of styles contained in the sheet.
15
+ * @returns {Function}
16
+ */
17
+ axe.utils.getStyleSheetFactory = function getStyleSheetFactory(dynamicDoc) {
18
+ if (!dynamicDoc) {
19
+ throw new Error(
20
+ 'axe.utils.getStyleSheetFactory should be invoked with an argument'
21
+ );
22
+ }
23
+
24
+ return options => {
25
+ const {
26
+ data,
27
+ isCrossOrigin = false,
28
+ shadowId,
29
+ root,
30
+ priority,
31
+ isLink = false
32
+ } = options;
33
+ const style = dynamicDoc.createElement('style');
34
+ if (isLink) {
35
+ // as creating a stylesheet as link will need to be awaited
36
+ // till `onload`, it is wise to convert link href to @import statement
37
+ const text = dynamicDoc.createTextNode(`@import "${data.href}"`);
38
+ style.appendChild(text);
39
+ } else {
40
+ style.appendChild(dynamicDoc.createTextNode(data));
41
+ }
42
+ dynamicDoc.head.appendChild(style);
43
+ return {
44
+ sheet: style.sheet,
45
+ isCrossOrigin,
46
+ shadowId,
47
+ root,
48
+ priority
49
+ };
50
+ };
51
+ };
@@ -1,6 +1,5 @@
1
1
  /*global axe */
2
2
 
3
- /*eslint max-statements: ["error", 36], complexity: ["error", 22]*/
4
3
  function getXPathArray(node, path) {
5
4
  var sibling, count;
6
5
  // Gets an XPath for an element which describes its hierarchical location.
@@ -8,7 +8,7 @@
8
8
  */
9
9
  axe.utils.isHidden = function isHidden(el, recursed) {
10
10
  'use strict';
11
- var parent;
11
+ const node = axe.utils.getNodeFromTree(el);
12
12
 
13
13
  // 9 === Node.DOCUMENT
14
14
  if (el.nodeType === 9) {
@@ -20,7 +20,11 @@ axe.utils.isHidden = function isHidden(el, recursed) {
20
20
  el = el.host; // grab the host Node
21
21
  }
22
22
 
23
- var style = window.getComputedStyle(el, null);
23
+ if (node && node._isHidden !== null) {
24
+ return node._isHidden;
25
+ }
26
+
27
+ const style = window.getComputedStyle(el, null);
24
28
 
25
29
  if (
26
30
  !style ||
@@ -34,7 +38,15 @@ axe.utils.isHidden = function isHidden(el, recursed) {
34
38
  return true;
35
39
  }
36
40
 
37
- parent = el.assignedSlot ? el.assignedSlot : el.parentNode;
41
+ const parent = el.assignedSlot ? el.assignedSlot : el.parentNode;
42
+ const isHidden = axe.utils.isHidden(parent, true);
43
+
44
+ // cache the results of the isHidden check on the parent tree
45
+ // so we don't have to look at the parent tree again for all its
46
+ // descendants
47
+ if (node) {
48
+ node._isHidden = isHidden;
49
+ }
38
50
 
39
- return axe.utils.isHidden(parent, true);
51
+ return isHidden;
40
52
  };
@@ -127,9 +127,9 @@ const htmlTags = [
127
127
  * @return {Boolean} true/ false
128
128
  */
129
129
  axe.utils.isHtmlElement = function isHtmlElement(node) {
130
- const tagName = node.nodeName.toLowerCase();
131
- return (
132
- htmlTags.includes(tagName) &&
133
- node.namespaceURI !== 'http://www.w3.org/2000/svg'
134
- );
130
+ if (node.namespaceURI === 'http://www.w3.org/2000/svg') {
131
+ return false;
132
+ }
133
+
134
+ return htmlTags.includes(node.nodeName.toLowerCase());
135
135
  };
@@ -27,11 +27,11 @@ const possibleShadowRoots = [
27
27
  * @return {Boolean}
28
28
  */
29
29
  axe.utils.isShadowRoot = function isShadowRoot(node) {
30
- const nodeName = node.nodeName.toLowerCase();
31
30
  if (node.shadowRoot) {
31
+ const nodeName = node.nodeName.toLowerCase();
32
32
  if (
33
- /^[a-z][a-z0-9_.-]*-[a-z0-9_.-]*$/.test(nodeName) ||
34
- possibleShadowRoots.includes(nodeName)
33
+ possibleShadowRoots.includes(nodeName) ||
34
+ /^[a-z][a-z0-9_.-]*-[a-z0-9_.-]*$/.test(nodeName)
35
35
  ) {
36
36
  return true;
37
37
  }