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.
- checksums.yaml +4 -4
- data/app/assets/javascripts/component_guide/accessibility-test.js +0 -6
- data/app/views/govuk_publishing_components/components/docs/machine_readable_metadata.yml +7 -0
- data/lib/govuk_publishing_components/presenters/machine_readable/dataset_schema.rb +34 -0
- data/lib/govuk_publishing_components/presenters/schema_org.rb +3 -0
- data/lib/govuk_publishing_components/version.rb +1 -1
- data/node_modules/axe-core/CHANGELOG.md +166 -2
- data/node_modules/axe-core/CONTRIBUTING.md +5 -5
- data/node_modules/axe-core/README.md +4 -4
- data/node_modules/axe-core/axe.d.ts +27 -11
- data/node_modules/axe-core/axe.js +9597 -2431
- data/node_modules/axe-core/axe.min.js +2 -2
- data/node_modules/axe-core/bower.json +1 -1
- data/node_modules/axe-core/doc/API.md +211 -128
- data/node_modules/axe-core/doc/accessibility-supported.md +1 -1
- data/node_modules/axe-core/doc/aria-supported.md +4 -13
- data/node_modules/axe-core/doc/backwards-compatibility-doc.md +93 -0
- data/node_modules/axe-core/doc/code-submission-guidelines.md +4 -4
- data/node_modules/axe-core/doc/developer-guide.md +27 -13
- data/node_modules/axe-core/doc/examples/chrome-debugging-protocol/package.json +5 -2
- data/node_modules/axe-core/doc/examples/jasmine/README.md +3 -5
- data/node_modules/axe-core/doc/examples/jasmine/karma.conf.js +29 -0
- data/node_modules/axe-core/doc/examples/jasmine/package.json +6 -5
- data/node_modules/axe-core/doc/examples/jest_react/README.md +1 -1
- data/node_modules/axe-core/doc/examples/jest_react/link.test.js +3 -3
- data/node_modules/axe-core/doc/examples/jest_react/package.json +9 -9
- data/node_modules/axe-core/doc/examples/jsdom/package.json +15 -0
- data/node_modules/axe-core/doc/examples/mocha/README.md +5 -7
- data/node_modules/axe-core/doc/examples/mocha/karma.conf.js +29 -0
- data/node_modules/axe-core/doc/examples/mocha/package.json +7 -6
- data/node_modules/axe-core/doc/examples/phantomjs/README.md +3 -3
- data/node_modules/axe-core/doc/examples/phantomjs/axe-phantom.js +4 -2
- data/node_modules/axe-core/doc/examples/phantomjs/package.json +3 -3
- data/node_modules/axe-core/doc/examples/puppeteer/package.json +5 -2
- data/node_modules/axe-core/doc/examples/qunit/README.md +2 -2
- data/node_modules/axe-core/doc/examples/qunit/package.json +2 -2
- data/node_modules/axe-core/doc/examples/test-examples.js +32 -0
- data/node_modules/axe-core/doc/plugins.md +10 -10
- data/node_modules/axe-core/doc/projects.md +12 -8
- data/node_modules/axe-core/doc/rule-descriptions.md +87 -79
- data/node_modules/axe-core/doc/rule-development.md +30 -2
- data/node_modules/axe-core/lib/checks/aria/allowed-attr.js +1 -1
- data/node_modules/axe-core/lib/checks/aria/aria-roledescription.js +14 -0
- data/node_modules/axe-core/lib/checks/aria/aria-roledescription.json +23 -0
- data/node_modules/axe-core/lib/checks/aria/no-implicit-explicit-label.js +21 -0
- data/node_modules/axe-core/lib/checks/aria/no-implicit-explicit-label.json +11 -0
- data/node_modules/axe-core/lib/checks/aria/required-attr.js +32 -7
- data/node_modules/axe-core/lib/checks/aria/required-children.js +40 -14
- data/node_modules/axe-core/lib/checks/aria/required-children.json +12 -1
- data/node_modules/axe-core/lib/checks/aria/required-parent.js +1 -1
- data/node_modules/axe-core/lib/checks/aria/unsupportedattr.js +1 -1
- data/node_modules/axe-core/lib/checks/aria/valid-attr-value.js +50 -17
- data/node_modules/axe-core/lib/checks/aria/valid-attr-value.json +2 -1
- data/node_modules/axe-core/lib/checks/aria/valid-attr.js +1 -1
- data/node_modules/axe-core/lib/checks/color/color-contrast.js +2 -2
- data/node_modules/axe-core/lib/checks/forms/autocomplete-appropriate.js +4 -4
- data/node_modules/axe-core/lib/checks/forms/autocomplete-valid.js +1 -1
- data/node_modules/axe-core/lib/checks/forms/fieldset.json +1 -0
- data/node_modules/axe-core/lib/checks/forms/group-labelledby.json +1 -0
- data/node_modules/axe-core/lib/checks/keyboard/focusable-content.js +16 -0
- data/node_modules/axe-core/lib/checks/keyboard/focusable-content.json +11 -0
- data/node_modules/axe-core/lib/checks/keyboard/focusable-element.js +12 -0
- data/node_modules/axe-core/lib/checks/keyboard/focusable-element.json +11 -0
- data/node_modules/axe-core/lib/checks/keyboard/tabindex.js +6 -1
- data/node_modules/axe-core/lib/checks/label/alt-space-value.js +3 -2
- data/node_modules/axe-core/lib/checks/label/duplicate-img-label.js +18 -15
- data/node_modules/axe-core/lib/checks/label/label-content-name-mismatch.js +13 -3
- data/node_modules/axe-core/lib/checks/label/label-content-name-mismatch.json +4 -0
- data/node_modules/axe-core/lib/checks/label/multiple-label.js +22 -12
- data/node_modules/axe-core/lib/checks/label/multiple-label.json +1 -1
- data/node_modules/axe-core/lib/checks/landmarks/landmark-is-unique-after.js +23 -0
- data/node_modules/axe-core/lib/checks/landmarks/landmark-is-unique.js +7 -0
- data/node_modules/axe-core/lib/checks/landmarks/landmark-is-unique.json +12 -0
- data/node_modules/axe-core/lib/checks/lists/listitem.js +1 -0
- data/node_modules/axe-core/lib/checks/lists/listitem.json +1 -1
- data/node_modules/axe-core/lib/checks/lists/only-listitems.js +0 -4
- data/node_modules/axe-core/lib/checks/mobile/css-orientation-lock.js +8 -6
- data/node_modules/axe-core/lib/checks/navigation/region.js +2 -19
- data/node_modules/axe-core/lib/checks/shared/avoid-inline-spacing.js +18 -0
- data/node_modules/axe-core/lib/checks/shared/avoid-inline-spacing.json +11 -0
- data/node_modules/axe-core/lib/checks/shared/exists.js +1 -1
- data/node_modules/axe-core/lib/checks/shared/exists.json +1 -1
- data/node_modules/axe-core/lib/checks/shared/has-alt.js +6 -4
- data/node_modules/axe-core/lib/checks/shared/non-empty-alt.js +1 -1
- data/node_modules/axe-core/lib/checks/tables/caption-faked.json +1 -1
- data/node_modules/axe-core/lib/checks/tables/td-has-header.js +5 -4
- data/node_modules/axe-core/lib/checks/tables/th-has-data-cells.js +19 -29
- data/node_modules/axe-core/lib/commons/aria/get-owned-virtual.js +1 -1
- data/node_modules/axe-core/lib/commons/aria/index.js +50 -46
- data/node_modules/axe-core/lib/commons/aria/is-accessible-ref.js +41 -37
- data/node_modules/axe-core/lib/commons/aria/label-virtual.js +2 -2
- data/node_modules/axe-core/lib/commons/aria/roles.js +1 -1
- data/node_modules/axe-core/lib/commons/aria/validate-attr-value.js +0 -1
- data/node_modules/axe-core/lib/commons/color/center-point-of-rect.js +30 -0
- data/node_modules/axe-core/lib/commons/color/contrast.js +7 -1
- data/node_modules/axe-core/lib/commons/color/element-has-image.js +36 -0
- data/node_modules/axe-core/lib/commons/color/get-background-color.js +332 -306
- data/node_modules/axe-core/lib/commons/color/get-foreground-color.js +35 -6
- data/node_modules/axe-core/lib/commons/color/get-own-background-color.js +22 -0
- data/node_modules/axe-core/lib/commons/dom/find-up.js +5 -5
- data/node_modules/axe-core/lib/commons/dom/get-scroll-offset.js +0 -1
- data/node_modules/axe-core/lib/commons/dom/get-tabbable-elements.js +1 -1
- data/node_modules/axe-core/lib/commons/dom/has-content-virtual.js +7 -5
- data/node_modules/axe-core/lib/commons/dom/is-focusable.js +8 -5
- data/node_modules/axe-core/lib/commons/dom/is-hidden-with-css.js +15 -2
- data/node_modules/axe-core/lib/commons/dom/is-in-text-block.js +1 -2
- data/node_modules/axe-core/lib/commons/dom/is-skip-link.js +45 -0
- data/node_modules/axe-core/lib/commons/dom/is-visible.js +43 -17
- data/node_modules/axe-core/lib/commons/dom/is-visual-content.js +0 -1
- data/node_modules/axe-core/lib/commons/dom/visually-contains.js +0 -1
- data/node_modules/axe-core/lib/commons/dom/visually-overlaps.js +0 -1
- data/node_modules/axe-core/lib/commons/forms/index.js +8 -0
- data/node_modules/axe-core/lib/commons/forms/is-aria-combobox.js +13 -0
- data/node_modules/axe-core/lib/commons/forms/is-aria-listbox.js +13 -0
- data/node_modules/axe-core/lib/commons/forms/is-aria-range.js +14 -0
- data/node_modules/axe-core/lib/commons/forms/is-aria-textbox.js +13 -0
- data/node_modules/axe-core/lib/commons/forms/is-native-select.js +13 -0
- data/node_modules/axe-core/lib/commons/forms/is-native-textbox.js +28 -0
- data/node_modules/axe-core/lib/commons/table/get-cell-position.js +2 -2
- data/node_modules/axe-core/lib/commons/table/get-headers.js +55 -11
- data/node_modules/axe-core/lib/commons/table/get-scope.js +1 -1
- data/node_modules/axe-core/lib/commons/table/is-data-table.js +0 -1
- data/node_modules/axe-core/lib/commons/table/to-grid.js +2 -2
- data/node_modules/axe-core/lib/commons/text/accessible-text-virtual.js +5 -5
- data/node_modules/axe-core/lib/commons/text/form-control-value.js +18 -30
- data/node_modules/axe-core/lib/commons/text/is-icon-ligature.js +210 -0
- data/node_modules/axe-core/lib/commons/text/is-valid-autocomplete.js +0 -1
- data/node_modules/axe-core/lib/commons/text/label-text.js +1 -1
- data/node_modules/axe-core/lib/commons/text/label-virtual.js +1 -1
- data/node_modules/axe-core/lib/commons/text/native-text-methods.js +1 -1
- data/node_modules/axe-core/lib/commons/text/subtree-text.js +3 -3
- data/node_modules/axe-core/lib/commons/text/unicode.js +15 -0
- data/node_modules/axe-core/lib/commons/text/visible-text-nodes.js +25 -0
- data/node_modules/axe-core/lib/commons/text/visible-virtual.js +1 -1
- data/node_modules/axe-core/lib/core/base/audit.js +90 -15
- data/node_modules/axe-core/lib/core/base/cache.js +33 -0
- data/node_modules/axe-core/lib/core/base/check.js +48 -1
- data/node_modules/axe-core/lib/core/base/context.js +15 -14
- data/node_modules/axe-core/lib/core/base/rule.js +223 -46
- data/node_modules/axe-core/lib/core/base/virtual-node/abstract-virtual-node.js +40 -0
- data/node_modules/axe-core/lib/core/base/virtual-node/serial-virtual-node.js +86 -0
- data/node_modules/axe-core/lib/core/base/virtual-node/virtual-node.js +85 -0
- data/node_modules/axe-core/lib/core/constants.js +10 -2
- data/node_modules/axe-core/lib/core/imports/index.js +28 -3
- data/node_modules/axe-core/lib/core/index.js +2 -4
- data/node_modules/axe-core/lib/core/public/configure.js +28 -1
- data/node_modules/axe-core/lib/core/public/run-rules.js +2 -0
- data/node_modules/axe-core/lib/core/public/run-virtual-rule.js +50 -0
- data/node_modules/axe-core/lib/core/public/run.js +13 -2
- data/node_modules/axe-core/lib/core/reporters/helpers/process-aggregate.js +1 -1
- data/node_modules/axe-core/lib/core/reporters/na.js +4 -0
- data/node_modules/axe-core/lib/core/reporters/raw-env.js +12 -0
- data/node_modules/axe-core/lib/core/reporters/raw.js +25 -1
- data/node_modules/axe-core/lib/core/utils/are-styles-set.js +4 -7
- data/node_modules/axe-core/lib/core/utils/assert.js +12 -0
- data/node_modules/axe-core/lib/core/utils/collect-results-from-frames.js +2 -2
- data/node_modules/axe-core/lib/core/utils/contains.js +27 -13
- data/node_modules/axe-core/lib/core/utils/css-parser.js +2 -0
- data/node_modules/axe-core/lib/core/utils/element-matches.js +5 -1
- data/node_modules/axe-core/lib/core/utils/escape-selector.js +1 -2
- data/node_modules/axe-core/lib/core/utils/flattened-tree.js +47 -61
- data/node_modules/axe-core/lib/core/utils/get-check-option.js +0 -1
- data/node_modules/axe-core/lib/core/utils/get-friendly-uri-end.js +1 -1
- data/node_modules/axe-core/lib/core/utils/get-node-attributes.js +21 -0
- data/node_modules/axe-core/lib/core/utils/get-scroll.js +39 -0
- data/node_modules/axe-core/lib/core/utils/get-selector.js +9 -6
- data/node_modules/axe-core/lib/core/utils/get-stylesheet-factory.js +51 -0
- data/node_modules/axe-core/lib/core/utils/get-xpath.js +0 -1
- data/node_modules/axe-core/lib/core/utils/is-hidden.js +16 -4
- data/node_modules/axe-core/lib/core/utils/is-html-element.js +5 -5
- data/node_modules/axe-core/lib/core/utils/is-shadow-root.js +3 -3
- data/node_modules/axe-core/lib/core/utils/memoize.js +17 -0
- data/node_modules/axe-core/lib/core/utils/parse-crossorigin-stylesheet.js +53 -0
- data/node_modules/axe-core/lib/core/utils/parse-sameorigin-stylesheet.js +96 -0
- data/node_modules/axe-core/lib/core/utils/parse-stylesheet.js +70 -0
- data/node_modules/axe-core/lib/core/utils/performance-timer.js +7 -2
- data/node_modules/axe-core/lib/core/utils/preload-cssom.js +77 -281
- data/node_modules/axe-core/lib/core/utils/preload.js +49 -23
- data/node_modules/axe-core/lib/core/utils/qsa.js +39 -50
- data/node_modules/axe-core/lib/core/utils/respondable.js +20 -3
- data/node_modules/axe-core/lib/core/utils/rule-should-run.js +0 -1
- data/node_modules/axe-core/lib/core/utils/scroll-state.js +12 -25
- data/node_modules/axe-core/lib/core/utils/select.js +12 -23
- data/node_modules/axe-core/lib/core/utils/uuid.js +1 -2
- data/node_modules/axe-core/lib/intro.stub +1 -1
- data/node_modules/axe-core/lib/misc/incomplete-fallback.json +1 -1
- data/node_modules/axe-core/lib/rules/aria-allowed-attr-matches.js +1 -1
- data/node_modules/axe-core/lib/rules/aria-form-field-name-matches.js +50 -0
- data/node_modules/axe-core/lib/rules/aria-has-attr-matches.js +1 -1
- data/node_modules/axe-core/lib/rules/aria-hidden-focus.json +1 -1
- data/node_modules/axe-core/lib/rules/aria-input-field-name.json +13 -0
- data/node_modules/axe-core/lib/rules/aria-roledescription.json +12 -0
- data/node_modules/axe-core/lib/rules/aria-toggle-field-name.json +18 -0
- data/node_modules/axe-core/lib/rules/autocomplete-matches.js +14 -10
- data/node_modules/axe-core/lib/rules/avoid-inline-spacing.json +12 -0
- data/node_modules/axe-core/lib/rules/button-name.json +3 -5
- data/node_modules/axe-core/lib/rules/checkboxgroup.json +2 -1
- data/node_modules/axe-core/lib/rules/color-contrast-matches.js +37 -22
- data/node_modules/axe-core/lib/rules/duplicate-id-active-matches.js +1 -1
- data/node_modules/axe-core/lib/rules/duplicate-id-misc-matches.js +2 -2
- data/node_modules/axe-core/lib/rules/form-field-multiple-labels.json +1 -1
- data/node_modules/axe-core/lib/rules/html-has-lang.json +1 -0
- data/node_modules/axe-core/lib/rules/image-alt.json +1 -1
- data/node_modules/axe-core/lib/rules/img-redundant-alt.json +3 -3
- data/node_modules/axe-core/lib/rules/input-button-name.json +26 -0
- data/node_modules/axe-core/lib/rules/landmark-unique-matches.js +41 -0
- data/node_modules/axe-core/lib/rules/landmark-unique.json +13 -0
- data/node_modules/axe-core/lib/rules/link-name.json +5 -4
- data/node_modules/axe-core/lib/rules/meta-refresh.json +8 -1
- data/node_modules/axe-core/lib/rules/radiogroup.json +2 -1
- data/node_modules/axe-core/lib/rules/role-img-alt.json +18 -0
- data/node_modules/axe-core/lib/rules/scrollable-region-focusable-matches.js +30 -0
- data/node_modules/axe-core/lib/rules/scrollable-region-focusable.json +12 -0
- data/node_modules/axe-core/lib/rules/skip-link-matches.js +1 -1
- data/node_modules/axe-core/lib/rules/skip-link.json +1 -1
- data/node_modules/axe-core/lib/rules/video-description.json +3 -1
- data/node_modules/axe-core/locales/de.json +1 -5
- data/node_modules/axe-core/locales/es.json +773 -0
- data/node_modules/axe-core/locales/fr.json +15 -19
- data/node_modules/axe-core/locales/ja.json +65 -11
- data/node_modules/axe-core/locales/ko.json +777 -0
- data/node_modules/axe-core/locales/nl.json +35 -35
- data/node_modules/axe-core/locales/pt_BR.json +773 -0
- data/node_modules/axe-core/package.json +56 -52
- data/node_modules/axe-core/sri-history.json +20 -0
- data/node_modules/axe-core/typings/axe-core/axe-core-tests.ts +5 -15
- data/node_modules/govuk-frontend/package.json +10 -10
- metadata +62 -4
- data/node_modules/axe-core/doc/axelogo2018.png +0 -0
- 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
|
-
|
|
39
|
+
color.getForegroundColor = function(node, noScroll, bgColor) {
|
|
40
|
+
const nodeStyle = window.getComputedStyle(node);
|
|
15
41
|
|
|
16
|
-
|
|
42
|
+
const fgColor = new color.Color();
|
|
17
43
|
fgColor.parseRgbString(nodeStyle.getPropertyValue('color'));
|
|
18
|
-
|
|
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
|
-
|
|
50
|
+
if (!bgColor) {
|
|
51
|
+
bgColor = color.getBackgroundColor(node, [], noScroll);
|
|
52
|
+
}
|
|
53
|
+
|
|
25
54
|
if (bgColor === null) {
|
|
26
|
-
|
|
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
|
}
|
|
@@ -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(
|
|
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
|
-
(
|
|
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
|
-
|
|
88
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
|
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 {
|
|
10
|
+
* @param {CSSStyleDeclaration} style Computed style
|
|
10
11
|
* @return {Boolean}
|
|
11
12
|
*/
|
|
12
|
-
function isClipped(
|
|
13
|
+
function isClipped(style) {
|
|
13
14
|
'use strict';
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
95
|
+
isVisible = dom.isVisible(parent, screenReader, true);
|
|
74
96
|
}
|
|
75
97
|
|
|
76
|
-
|
|
98
|
+
if (node) {
|
|
99
|
+
node[cacheName] = isVisible;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return isVisible;
|
|
77
103
|
};
|
|
@@ -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
|
+
};
|