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,5 @@
|
|
|
1
1
|
// Select and textarea is always allowed
|
|
2
|
-
if (
|
|
2
|
+
if (virtualNode.props.nodeName !== 'input') {
|
|
3
3
|
return true;
|
|
4
4
|
}
|
|
5
5
|
|
|
@@ -34,7 +34,7 @@ if (typeof options === 'object') {
|
|
|
34
34
|
});
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
const autocomplete =
|
|
37
|
+
const autocomplete = virtualNode.attr('autocomplete');
|
|
38
38
|
const autocompleteTerms = autocomplete
|
|
39
39
|
.split(/\s+/g)
|
|
40
40
|
.map(term => term.toLowerCase());
|
|
@@ -55,8 +55,8 @@ const allowedTypes = allowedTypesMap[purposeTerm];
|
|
|
55
55
|
* Reference HTML Spec - https://html.spec.whatwg.org/multipage/input.html#the-input-element to filter allowed values for `type`
|
|
56
56
|
* and sanitize (https://html.spec.whatwg.org/multipage/input.html#value-sanitization-algorithm)
|
|
57
57
|
*/
|
|
58
|
-
let type =
|
|
59
|
-
? axe.commons.text.sanitize(
|
|
58
|
+
let type = virtualNode.hasAttr('type')
|
|
59
|
+
? axe.commons.text.sanitize(virtualNode.attr('type')).toLowerCase()
|
|
60
60
|
: 'text';
|
|
61
61
|
type = axe.utils.validInputTypes().includes(type) ? type : 'text';
|
|
62
62
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const autocomplete =
|
|
1
|
+
const autocomplete = virtualNode.attr('autocomplete') || '';
|
|
2
2
|
return axe.commons.text.isValidAutocomplete(autocomplete, options);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Note:
|
|
3
|
+
* Check if given node contains focusable elements (excluding thyself)
|
|
4
|
+
*/
|
|
5
|
+
const tabbableElements = virtualNode.tabbableElements;
|
|
6
|
+
|
|
7
|
+
if (!tabbableElements) {
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// remove thyself from tabbable elements (if exists)
|
|
12
|
+
const tabbableContentElements = tabbableElements.filter(
|
|
13
|
+
el => el !== virtualNode
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
return tabbableContentElements.length > 0;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Note:
|
|
3
|
+
* Check
|
|
4
|
+
* - if element is focusable
|
|
5
|
+
* - if element is in focus order via `tabindex`
|
|
6
|
+
*/
|
|
7
|
+
const isFocusable = virtualNode.isFocusable;
|
|
8
|
+
|
|
9
|
+
let tabIndex = parseInt(virtualNode.actualNode.getAttribute('tabindex'), 10);
|
|
10
|
+
tabIndex = !isNaN(tabIndex) ? tabIndex : null;
|
|
11
|
+
|
|
12
|
+
return tabIndex ? isFocusable && tabIndex >= 0 : isFocusable;
|
|
@@ -1 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
const tabIndex = parseInt(node.getAttribute('tabindex'), 10);
|
|
2
|
+
|
|
3
|
+
// an invalid tabindex will either return 0 or -1 (based on the element) so
|
|
4
|
+
// will never be above 0
|
|
5
|
+
// @see https://www.w3.org/TR/html51/editing.html#the-tabindex-attribute
|
|
6
|
+
return isNaN(tabIndex) ? true : tabIndex <= 0;
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
const
|
|
2
|
-
|
|
1
|
+
const alt = virtualNode.attr('alt');
|
|
2
|
+
const isOnlySpace = /^\s+$/;
|
|
3
|
+
return typeof alt === 'string' && isOnlySpace.test(alt);
|
|
@@ -1,19 +1,22 @@
|
|
|
1
|
-
const text = axe.commons
|
|
2
|
-
|
|
1
|
+
const { aria, text, dom } = axe.commons;
|
|
2
|
+
|
|
3
|
+
if (['none', 'presentation'].includes(aria.getRole(node))) {
|
|
3
4
|
return false;
|
|
4
5
|
}
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
// Ignore hidden or role=none/presentation images
|
|
10
|
-
.filter(
|
|
11
|
-
({ actualNode }) =>
|
|
12
|
-
axe.commons.dom.isVisible(actualNode) &&
|
|
13
|
-
!['none', 'presentation'].includes(actualNode.getAttribute('role'))
|
|
14
|
-
);
|
|
15
|
-
|
|
16
|
-
// See if any of the images duplicate the node's text
|
|
17
|
-
return images.some(
|
|
18
|
-
img => text === axe.commons.text.accessibleTextVirtual(img).toLowerCase()
|
|
7
|
+
const parent = dom.findUpVirtual(
|
|
8
|
+
virtualNode,
|
|
9
|
+
'button, [role="button"], a[href], p, li, td, th'
|
|
19
10
|
);
|
|
11
|
+
|
|
12
|
+
if (!parent) {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const parentVNode = axe.utils.getNodeFromTree(parent);
|
|
17
|
+
const visibleText = text.visibleVirtual(parentVNode, true).toLowerCase();
|
|
18
|
+
if (visibleText === '') {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return visibleText === text.accessibleTextVirtual(virtualNode).toLowerCase();
|
|
@@ -1,13 +1,23 @@
|
|
|
1
1
|
const { text } = axe.commons;
|
|
2
|
+
const { pixelThreshold, occuranceThreshold } = options || {};
|
|
2
3
|
|
|
3
4
|
const accText = text.accessibleText(node).toLowerCase();
|
|
4
5
|
if (text.isHumanInterpretable(accText) < 1) {
|
|
5
6
|
return undefined;
|
|
6
7
|
}
|
|
7
8
|
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
.
|
|
9
|
+
const textVNodes = text.visibleTextNodes(virtualNode);
|
|
10
|
+
const nonLigatureText = textVNodes
|
|
11
|
+
.filter(
|
|
12
|
+
textVNode =>
|
|
13
|
+
!text.isIconLigature(textVNode, pixelThreshold, occuranceThreshold)
|
|
14
|
+
)
|
|
15
|
+
.map(textVNode => textVNode.actualNode.nodeValue)
|
|
16
|
+
.join('');
|
|
17
|
+
const visibleText = text.sanitize(nonLigatureText).toLowerCase();
|
|
18
|
+
if (!visibleText) {
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
11
21
|
if (text.isHumanInterpretable(visibleText) < 1) {
|
|
12
22
|
if (isStringContained(visibleText, accText)) {
|
|
13
23
|
return true;
|
|
@@ -1,18 +1,12 @@
|
|
|
1
1
|
const id = axe.utils.escapeSelector(node.getAttribute('id'));
|
|
2
|
-
let labels = Array.from(document.querySelectorAll(`label[for="${id}"]`));
|
|
3
2
|
let parent = node.parentNode;
|
|
3
|
+
let root = axe.commons.dom.getRootNode(node);
|
|
4
|
+
root = root.documentElement || root;
|
|
5
|
+
let labels = Array.from(root.querySelectorAll(`label[for="${id}"]`));
|
|
4
6
|
|
|
5
7
|
if (labels.length) {
|
|
6
|
-
// filter out hidden labels because they're fine
|
|
7
|
-
|
|
8
|
-
labels = labels.filter(function(label, index) {
|
|
9
|
-
if (
|
|
10
|
-
(index === 0 && !axe.commons.dom.isVisible(label, true)) ||
|
|
11
|
-
axe.commons.dom.isVisible(label, true)
|
|
12
|
-
) {
|
|
13
|
-
return label;
|
|
14
|
-
}
|
|
15
|
-
});
|
|
8
|
+
// filter out CSS hidden labels because they're fine
|
|
9
|
+
labels = labels.filter(label => axe.commons.dom.isVisible(label));
|
|
16
10
|
}
|
|
17
11
|
|
|
18
12
|
while (parent) {
|
|
@@ -26,4 +20,20 @@ while (parent) {
|
|
|
26
20
|
}
|
|
27
21
|
|
|
28
22
|
this.relatedNodes(labels);
|
|
29
|
-
|
|
23
|
+
|
|
24
|
+
// more than 1 CSS visible label
|
|
25
|
+
if (labels.length > 1) {
|
|
26
|
+
const ATVisibleLabels = labels.filter(label =>
|
|
27
|
+
axe.commons.dom.isVisible(label, true)
|
|
28
|
+
);
|
|
29
|
+
// more than 1 AT visible label will fail IOS/Safari/VO even with aria-labelledby
|
|
30
|
+
if (ATVisibleLabels.length > 1) {
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
// make sure the ONE AT visible label is in the list of idRefs of aria-labelledby
|
|
34
|
+
const labelledby = axe.commons.dom.idrefs(node, 'aria-labelledby');
|
|
35
|
+
return !labelledby.includes(ATVisibleLabels[0]) ? undefined : false;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// only 1 CSS visible label
|
|
39
|
+
return false;
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"impact": "moderate",
|
|
6
6
|
"messages": {
|
|
7
7
|
"pass": "Form field does not have multiple label elements",
|
|
8
|
-
"
|
|
8
|
+
"incomplete": "Multiple label elements is not widely supported in assistive technologies. Ensure the first label contains all necessary information."
|
|
9
9
|
}
|
|
10
10
|
}
|
|
11
11
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
var uniqueLandmarks = [];
|
|
2
|
+
|
|
3
|
+
// filter out landmark elements that share the same role and accessible text
|
|
4
|
+
// so every non-unique landmark isn't reported as a failure (just the first)
|
|
5
|
+
return results.filter(currentResult => {
|
|
6
|
+
var findMatch = someResult => {
|
|
7
|
+
return (
|
|
8
|
+
currentResult.data.role === someResult.data.role &&
|
|
9
|
+
currentResult.data.accessibleText === someResult.data.accessibleText
|
|
10
|
+
);
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
var matchedResult = uniqueLandmarks.find(findMatch);
|
|
14
|
+
if (matchedResult) {
|
|
15
|
+
matchedResult.result = false;
|
|
16
|
+
matchedResult.relatedNodes.push(currentResult.relatedNodes[0]);
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
uniqueLandmarks.push(currentResult);
|
|
21
|
+
currentResult.relatedNodes = [];
|
|
22
|
+
return true;
|
|
23
|
+
});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
var role = axe.commons.aria.getRole(node);
|
|
2
|
+
var accessibleText = axe.commons.text.accessibleTextVirtual(virtualNode);
|
|
3
|
+
accessibleText = accessibleText ? accessibleText.toLowerCase() : null;
|
|
4
|
+
this.data({ role: role, accessibleText: accessibleText });
|
|
5
|
+
this.relatedNodes([node]);
|
|
6
|
+
|
|
7
|
+
return true;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "landmark-is-unique",
|
|
3
|
+
"evaluate": "landmark-is-unique.js",
|
|
4
|
+
"after": "landmark-is-unique-after.js",
|
|
5
|
+
"metadata": {
|
|
6
|
+
"impact": "moderate",
|
|
7
|
+
"messages": {
|
|
8
|
+
"pass": "Landmarks must have a unique role or role/label/title (i.e. accessible name) combination",
|
|
9
|
+
"fail": "The landmark must have a unique aria-label, aria-labelledby, or title to make landmarks distinguishable"
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"impact": "serious",
|
|
6
6
|
"messages": {
|
|
7
7
|
"pass": "List item has a <ul>, <ol> or role=\"list\" parent element",
|
|
8
|
-
"fail": "List item does not have a <ul>, <ol> or role=\"list\" parent element"
|
|
8
|
+
"fail": "List item does not have a <ul>, <ol>{{? it.data === 'roleNotValid'}} without a role, or a role=\"list\"{{?}} parent element"
|
|
9
9
|
}
|
|
10
10
|
}
|
|
11
11
|
}
|
|
@@ -16,10 +16,6 @@ let base = {
|
|
|
16
16
|
};
|
|
17
17
|
|
|
18
18
|
let out = virtualNode.children.reduce((out, { actualNode }) => {
|
|
19
|
-
/*eslint
|
|
20
|
-
max-statements: ["error", 20]
|
|
21
|
-
complexity: ["error", 12]
|
|
22
|
-
*/
|
|
23
19
|
const tagName = actualNode.nodeName.toUpperCase();
|
|
24
20
|
|
|
25
21
|
if (actualNode.nodeType === 1 && dom.isVisible(actualNode, true, false)) {
|
|
@@ -61,8 +61,8 @@ Object.keys(rulesGroupByDocumentFragment).forEach(key => {
|
|
|
61
61
|
// eg: screen and (max-width: 767px) and (min-width: 320px) and (orientation: landscape)
|
|
62
62
|
const cssText = r.cssText;
|
|
63
63
|
return (
|
|
64
|
-
/orientation:\s
|
|
65
|
-
/orientation:\s
|
|
64
|
+
/orientation:\s*landscape/i.test(cssText) ||
|
|
65
|
+
/orientation:\s*portrait/i.test(cssText)
|
|
66
66
|
);
|
|
67
67
|
});
|
|
68
68
|
if (!orientationRules || !orientationRules.length) {
|
|
@@ -78,8 +78,6 @@ Object.keys(rulesGroupByDocumentFragment).forEach(key => {
|
|
|
78
78
|
// a media query has framents of css styles applied to various selectors
|
|
79
79
|
// iteration through cssRules and see if orientation lock has been applied
|
|
80
80
|
Array.from(r.cssRules).forEach(cssRule => {
|
|
81
|
-
/* eslint max-statements: ["error", 20], complexity: ["error", 15] */
|
|
82
|
-
|
|
83
81
|
// ensure selectorText exists
|
|
84
82
|
if (!cssRule.selectorText) {
|
|
85
83
|
return;
|
|
@@ -89,8 +87,12 @@ Object.keys(rulesGroupByDocumentFragment).forEach(key => {
|
|
|
89
87
|
return;
|
|
90
88
|
}
|
|
91
89
|
|
|
92
|
-
// check if transform style exists
|
|
93
|
-
const transformStyleValue =
|
|
90
|
+
// check if transform style exists (don't forget vendor prefixes)
|
|
91
|
+
const transformStyleValue =
|
|
92
|
+
cssRule.style.transform ||
|
|
93
|
+
cssRule.style.webkitTransform ||
|
|
94
|
+
cssRule.style.msTransform ||
|
|
95
|
+
false;
|
|
94
96
|
// transformStyleValue -> is the value applied to property
|
|
95
97
|
// eg: "rotate(-90deg)"
|
|
96
98
|
if (!transformStyleValue) {
|
|
@@ -1,17 +1,4 @@
|
|
|
1
1
|
const { dom, aria } = axe.commons;
|
|
2
|
-
|
|
3
|
-
// Return the skplink, if any
|
|
4
|
-
function getSkiplink(virtualNode) {
|
|
5
|
-
const firstLink = axe.utils.querySelectorAll(virtualNode, 'a[href]')[0];
|
|
6
|
-
if (
|
|
7
|
-
firstLink &&
|
|
8
|
-
axe.commons.dom.getElementByReference(firstLink.actualNode, 'href')
|
|
9
|
-
) {
|
|
10
|
-
return firstLink.actualNode;
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const skipLink = getSkiplink(virtualNode);
|
|
15
2
|
const landmarkRoles = aria.getRolesByType('landmark');
|
|
16
3
|
|
|
17
4
|
// Create a list of nodeNames that have a landmark as an implicit role
|
|
@@ -19,11 +6,6 @@ const implicitLandmarks = landmarkRoles
|
|
|
19
6
|
.reduce((arr, role) => arr.concat(aria.implicitNodes(role)), [])
|
|
20
7
|
.filter(r => r !== null);
|
|
21
8
|
|
|
22
|
-
// Check if the current element is the skiplink
|
|
23
|
-
function isSkipLink(vNode) {
|
|
24
|
-
return skipLink && skipLink === vNode.actualNode;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
9
|
// Check if the current element is a landmark
|
|
28
10
|
function isRegion(virtualNode) {
|
|
29
11
|
const node = virtualNode.actualNode;
|
|
@@ -61,7 +43,8 @@ function findRegionlessElms(virtualNode) {
|
|
|
61
43
|
// End recursion if the element is a landmark, skiplink, or hidden content
|
|
62
44
|
if (
|
|
63
45
|
isRegion(virtualNode) ||
|
|
64
|
-
isSkipLink(virtualNode)
|
|
46
|
+
(dom.isSkipLink(virtualNode.actualNode) &&
|
|
47
|
+
dom.getElementByReference(virtualNode.actualNode, 'href')) ||
|
|
65
48
|
!dom.isVisible(node, true)
|
|
66
49
|
) {
|
|
67
50
|
return [];
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const inlineSpacingCssProperties = [
|
|
2
|
+
'line-height',
|
|
3
|
+
'letter-spacing',
|
|
4
|
+
'word-spacing'
|
|
5
|
+
];
|
|
6
|
+
|
|
7
|
+
const overriddenProperties = inlineSpacingCssProperties.filter(property => {
|
|
8
|
+
if (node.style.getPropertyPriority(property) === `important`) {
|
|
9
|
+
return property;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
if (overriddenProperties.length > 0) {
|
|
14
|
+
this.data(overriddenProperties);
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return true;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "avoid-inline-spacing",
|
|
3
|
+
"evaluate": "avoid-inline-spacing.js",
|
|
4
|
+
"metadata": {
|
|
5
|
+
"impact": "serious",
|
|
6
|
+
"messages": {
|
|
7
|
+
"pass": "No inline styles with '!important' that affect text spacing has been specified",
|
|
8
|
+
"fail": "Remove '!important' from inline style{{=it.data && it.data.length > 1 ? 's' : ''}} {{=it.data.join(', ')}}, as overriding this is not supported by most browsers"
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
return
|
|
1
|
+
return undefined;
|