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,7 +1,6 @@
|
|
|
1
1
|
/*global RuleResult, createExecutionContext, SupportError */
|
|
2
2
|
|
|
3
3
|
function Rule(spec, parentAudit) {
|
|
4
|
-
/*eslint complexity: ["error", 11] */
|
|
5
4
|
'use strict';
|
|
6
5
|
|
|
7
6
|
this._audit = parentAudit;
|
|
@@ -90,16 +89,48 @@ Rule.prototype.matches = function() {
|
|
|
90
89
|
/**
|
|
91
90
|
* Selects `HTMLElement`s based on configured selector
|
|
92
91
|
* @param {Context} context The resolved Context object
|
|
92
|
+
* @param {Mixed} options Options specific to this rule
|
|
93
93
|
* @return {Array} All matching `HTMLElement`s
|
|
94
94
|
*/
|
|
95
|
-
Rule.prototype.gather = function(context) {
|
|
96
|
-
'
|
|
95
|
+
Rule.prototype.gather = function(context, options = {}) {
|
|
96
|
+
const markStart = 'mark_gather_start_' + this.id;
|
|
97
|
+
const markEnd = 'mark_gather_end_' + this.id;
|
|
98
|
+
const markHiddenStart = 'mark_isHidden_start_' + this.id;
|
|
99
|
+
const markHiddenEnd = 'mark_isHidden_end_' + this.id;
|
|
100
|
+
|
|
101
|
+
if (options.performanceTimer) {
|
|
102
|
+
axe.utils.performanceTimer.mark(markStart);
|
|
103
|
+
}
|
|
104
|
+
|
|
97
105
|
var elements = axe.utils.select(this.selector, context);
|
|
98
106
|
if (this.excludeHidden) {
|
|
99
|
-
|
|
107
|
+
if (options.performanceTimer) {
|
|
108
|
+
axe.utils.performanceTimer.mark(markHiddenStart);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
elements = elements.filter(function(element) {
|
|
100
112
|
return !axe.utils.isHidden(element.actualNode);
|
|
101
113
|
});
|
|
114
|
+
|
|
115
|
+
if (options.performanceTimer) {
|
|
116
|
+
axe.utils.performanceTimer.mark(markHiddenEnd);
|
|
117
|
+
axe.utils.performanceTimer.measure(
|
|
118
|
+
'rule_' + this.id + '#gather_axe.utils.isHidden',
|
|
119
|
+
markHiddenStart,
|
|
120
|
+
markHiddenEnd
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (options.performanceTimer) {
|
|
126
|
+
axe.utils.performanceTimer.mark(markEnd);
|
|
127
|
+
axe.utils.performanceTimer.measure(
|
|
128
|
+
'rule_' + this.id + '#gather',
|
|
129
|
+
markStart,
|
|
130
|
+
markEnd
|
|
131
|
+
);
|
|
102
132
|
}
|
|
133
|
+
|
|
103
134
|
return elements;
|
|
104
135
|
};
|
|
105
136
|
|
|
@@ -135,29 +166,46 @@ Rule.prototype.runChecks = function(
|
|
|
135
166
|
.catch(reject);
|
|
136
167
|
};
|
|
137
168
|
|
|
169
|
+
/**
|
|
170
|
+
* Run a check for a rule synchronously.
|
|
171
|
+
*/
|
|
172
|
+
Rule.prototype.runChecksSync = function(type, node, options, context) {
|
|
173
|
+
'use strict';
|
|
174
|
+
|
|
175
|
+
const self = this;
|
|
176
|
+
let results = [];
|
|
177
|
+
|
|
178
|
+
this[type].forEach(function(c) {
|
|
179
|
+
const check = self._audit.checks[c.id || c];
|
|
180
|
+
const option = axe.utils.getCheckOption(check, self.id, options);
|
|
181
|
+
results.push(check.runSync(node, option, context));
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
results = results.filter(function(check) {
|
|
185
|
+
return check;
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
return { type: type, results: results };
|
|
189
|
+
};
|
|
190
|
+
|
|
138
191
|
/**
|
|
139
192
|
* Runs the Rule's `evaluate` function
|
|
140
193
|
* @param {Context} context The resolved Context object
|
|
141
194
|
* @param {Mixed} options Options specific to this rule
|
|
142
195
|
* @param {Function} callback Function to call when evaluate is complete; receives a RuleResult instance
|
|
143
196
|
*/
|
|
144
|
-
Rule.prototype.run = function(context, options, resolve, reject) {
|
|
145
|
-
|
|
197
|
+
Rule.prototype.run = function(context, options = {}, resolve, reject) {
|
|
198
|
+
if (options.performanceTimer) {
|
|
199
|
+
this._trackPerformance();
|
|
200
|
+
}
|
|
146
201
|
|
|
147
202
|
const q = axe.utils.queue();
|
|
148
203
|
const ruleResult = new RuleResult(this);
|
|
149
|
-
const markStart = 'mark_rule_start_' + this.id;
|
|
150
|
-
const markEnd = 'mark_rule_end_' + this.id;
|
|
151
|
-
const markChecksStart = 'mark_runchecks_start_' + this.id;
|
|
152
|
-
const markChecksEnd = 'mark_runchecks_end_' + this.id;
|
|
153
|
-
|
|
154
204
|
let nodes;
|
|
155
205
|
|
|
156
206
|
try {
|
|
157
207
|
// Matches throws an error when it lacks support for document methods
|
|
158
|
-
nodes = this.
|
|
159
|
-
this.matches(node.actualNode, node, context)
|
|
160
|
-
);
|
|
208
|
+
nodes = this.gatherAndMatchNodes(context, options);
|
|
161
209
|
} catch (error) {
|
|
162
210
|
// Exit the rule execution if matches fails
|
|
163
211
|
reject(new SupportError({ cause: error, ruleId: this.id }));
|
|
@@ -165,13 +213,7 @@ Rule.prototype.run = function(context, options, resolve, reject) {
|
|
|
165
213
|
}
|
|
166
214
|
|
|
167
215
|
if (options.performanceTimer) {
|
|
168
|
-
|
|
169
|
-
'gather (',
|
|
170
|
-
nodes.length,
|
|
171
|
-
'):',
|
|
172
|
-
axe.utils.performanceTimer.timeElapsed() + 'ms'
|
|
173
|
-
);
|
|
174
|
-
axe.utils.performanceTimer.mark(markChecksStart);
|
|
216
|
+
this._logGatherPerformance(nodes);
|
|
175
217
|
}
|
|
176
218
|
|
|
177
219
|
nodes.forEach(node => {
|
|
@@ -186,22 +228,10 @@ Rule.prototype.run = function(context, options, resolve, reject) {
|
|
|
186
228
|
|
|
187
229
|
checkQueue
|
|
188
230
|
.then(function(results) {
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
var res = r.results.filter(function(result) {
|
|
194
|
-
return result;
|
|
195
|
-
});
|
|
196
|
-
result[r.type] = res;
|
|
197
|
-
if (res.length) {
|
|
198
|
-
hasResults = true;
|
|
199
|
-
}
|
|
200
|
-
});
|
|
201
|
-
if (hasResults) {
|
|
202
|
-
result.node = new axe.utils.DqElement(node.actualNode, options);
|
|
203
|
-
ruleResult.nodes.push(result);
|
|
204
|
-
}
|
|
231
|
+
const result = getResult(results);
|
|
232
|
+
if (result) {
|
|
233
|
+
result.node = new axe.utils.DqElement(node.actualNode, options);
|
|
234
|
+
ruleResult.nodes.push(result);
|
|
205
235
|
}
|
|
206
236
|
resolveNode();
|
|
207
237
|
})
|
|
@@ -214,18 +244,165 @@ Rule.prototype.run = function(context, options, resolve, reject) {
|
|
|
214
244
|
q.defer(resolve => setTimeout(resolve, 0));
|
|
215
245
|
|
|
216
246
|
if (options.performanceTimer) {
|
|
217
|
-
|
|
218
|
-
|
|
247
|
+
this._logRulePerformance();
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
q.then(() => resolve(ruleResult)).catch(error => reject(error));
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Runs the Rule's `evaluate` function synchronously
|
|
255
|
+
* @param {Context} context The resolved Context object
|
|
256
|
+
* @param {Mixed} options Options specific to this rule
|
|
257
|
+
*/
|
|
258
|
+
Rule.prototype.runSync = function(context, options = {}) {
|
|
259
|
+
if (options.performanceTimer) {
|
|
260
|
+
this._trackPerformance();
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
const ruleResult = new RuleResult(this);
|
|
264
|
+
let nodes;
|
|
265
|
+
|
|
266
|
+
try {
|
|
267
|
+
nodes = this.gatherAndMatchNodes(context, options);
|
|
268
|
+
} catch (error) {
|
|
269
|
+
// Exit the rule execution if matches fails
|
|
270
|
+
throw new SupportError({ cause: error, ruleId: this.id });
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
if (options.performanceTimer) {
|
|
274
|
+
this._logGatherPerformance(nodes);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
nodes.forEach(node => {
|
|
278
|
+
let results = [];
|
|
279
|
+
['any', 'all', 'none'].forEach(type => {
|
|
280
|
+
results.push(this.runChecksSync(type, node, options, context));
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
const result = getResult(results);
|
|
284
|
+
if (result) {
|
|
285
|
+
result.node = node.actualNode
|
|
286
|
+
? new axe.utils.DqElement(node.actualNode, options)
|
|
287
|
+
: null;
|
|
288
|
+
ruleResult.nodes.push(result);
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
if (options.performanceTimer) {
|
|
293
|
+
this._logRulePerformance();
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
return ruleResult;
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Add performance tracking properties to the rule
|
|
301
|
+
* @private
|
|
302
|
+
*/
|
|
303
|
+
Rule.prototype._trackPerformance = function() {
|
|
304
|
+
this._markStart = 'mark_rule_start_' + this.id;
|
|
305
|
+
this._markEnd = 'mark_rule_end_' + this.id;
|
|
306
|
+
this._markChecksStart = 'mark_runchecks_start_' + this.id;
|
|
307
|
+
this._markChecksEnd = 'mark_runchecks_end_' + this.id;
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Log performance of rule.gather
|
|
312
|
+
* @private
|
|
313
|
+
* @param {Rule} rule The rule to log
|
|
314
|
+
* @param {Array} nodes Result of rule.gather
|
|
315
|
+
*/
|
|
316
|
+
Rule.prototype._logGatherPerformance = function(nodes) {
|
|
317
|
+
axe.log(
|
|
318
|
+
'gather (',
|
|
319
|
+
nodes.length,
|
|
320
|
+
'):',
|
|
321
|
+
axe.utils.performanceTimer.timeElapsed() + 'ms'
|
|
322
|
+
);
|
|
323
|
+
axe.utils.performanceTimer.mark(this._markChecksStart);
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Log performance of the rule
|
|
328
|
+
* @private
|
|
329
|
+
* @param {Rule} rule The rule to log
|
|
330
|
+
*/
|
|
331
|
+
Rule.prototype._logRulePerformance = function() {
|
|
332
|
+
axe.utils.performanceTimer.mark(this._markChecksEnd);
|
|
333
|
+
axe.utils.performanceTimer.mark(this._markEnd);
|
|
334
|
+
axe.utils.performanceTimer.measure(
|
|
335
|
+
'runchecks_' + this.id,
|
|
336
|
+
this._markChecksStart,
|
|
337
|
+
this._markChecksEnd
|
|
338
|
+
);
|
|
339
|
+
|
|
340
|
+
axe.utils.performanceTimer.measure(
|
|
341
|
+
'rule_' + this.id,
|
|
342
|
+
this._markStart,
|
|
343
|
+
this._markEnd
|
|
344
|
+
);
|
|
345
|
+
};
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Process the results of each check and return the result if a check
|
|
349
|
+
* has a result
|
|
350
|
+
* @private
|
|
351
|
+
* @param {Array} results Array of each check result
|
|
352
|
+
* @returns {Object|null}
|
|
353
|
+
*/
|
|
354
|
+
function getResult(results) {
|
|
355
|
+
if (results.length) {
|
|
356
|
+
let hasResults = false,
|
|
357
|
+
result = {};
|
|
358
|
+
results.forEach(function(r) {
|
|
359
|
+
const res = r.results.filter(function(result) {
|
|
360
|
+
return result;
|
|
361
|
+
});
|
|
362
|
+
result[r.type] = res;
|
|
363
|
+
if (res.length) {
|
|
364
|
+
hasResults = true;
|
|
365
|
+
}
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
if (hasResults) {
|
|
369
|
+
return result;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
return null;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* Selects `HTMLElement`s based on configured selector and filters them based on
|
|
378
|
+
* the rules matches function
|
|
379
|
+
* @param {Rule} rule The rule to check for after checks
|
|
380
|
+
* @param {Context} context The resolved Context object
|
|
381
|
+
* @param {Mixed} options Options specific to this rule
|
|
382
|
+
* @return {Array} All matching `HTMLElement`s
|
|
383
|
+
*/
|
|
384
|
+
Rule.prototype.gatherAndMatchNodes = function(context, options) {
|
|
385
|
+
const markMatchesStart = 'mark_matches_start_' + this.id;
|
|
386
|
+
const markMatchesEnd = 'mark_matches_end_' + this.id;
|
|
387
|
+
|
|
388
|
+
let nodes = this.gather(context, options);
|
|
389
|
+
|
|
390
|
+
if (options.performanceTimer) {
|
|
391
|
+
axe.utils.performanceTimer.mark(markMatchesStart);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
nodes = nodes.filter(node => this.matches(node.actualNode, node, context));
|
|
395
|
+
|
|
396
|
+
if (options.performanceTimer) {
|
|
397
|
+
axe.utils.performanceTimer.mark(markMatchesEnd);
|
|
219
398
|
axe.utils.performanceTimer.measure(
|
|
220
|
-
'
|
|
221
|
-
|
|
222
|
-
|
|
399
|
+
'rule_' + this.id + '#matches',
|
|
400
|
+
markMatchesStart,
|
|
401
|
+
markMatchesEnd
|
|
223
402
|
);
|
|
224
|
-
|
|
225
|
-
axe.utils.performanceTimer.measure('rule_' + this.id, markStart, markEnd);
|
|
226
403
|
}
|
|
227
404
|
|
|
228
|
-
|
|
405
|
+
return nodes;
|
|
229
406
|
};
|
|
230
407
|
|
|
231
408
|
/**
|
|
@@ -336,7 +513,7 @@ Rule.prototype.after = function(result, options) {
|
|
|
336
513
|
* @param {Object} spec - the attributes to be reconfigured
|
|
337
514
|
*/
|
|
338
515
|
Rule.prototype.configure = function(spec) {
|
|
339
|
-
/*eslint
|
|
516
|
+
/*eslint no-eval:0 */
|
|
340
517
|
'use strict';
|
|
341
518
|
|
|
342
519
|
if (spec.hasOwnProperty('selector')) {
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
const whitespaceRegex = /[\t\r\n\f]/g;
|
|
2
|
+
|
|
3
|
+
class AbstractVirtualNode {
|
|
4
|
+
constructor() {
|
|
5
|
+
this.children = [];
|
|
6
|
+
this.parent = null;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
get props() {
|
|
10
|
+
throw new Error(
|
|
11
|
+
'VirtualNode class must have a "props" object consisting ' +
|
|
12
|
+
'of "nodeType" and "nodeName" properties'
|
|
13
|
+
);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
attr() {
|
|
17
|
+
throw new Error('VirtualNode class must have a "attr" function');
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
hasAttr() {
|
|
21
|
+
throw new Error('VirtualNode class must have a "hasAttr" function');
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
hasClass(className) {
|
|
25
|
+
// get the value of the class attribute as svgs return a SVGAnimatedString
|
|
26
|
+
// if you access the className property
|
|
27
|
+
let classAttr = this.attr('class');
|
|
28
|
+
if (!classAttr) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
let selector = ' ' + className + ' ';
|
|
33
|
+
return (
|
|
34
|
+
(' ' + classAttr + ' ').replace(whitespaceRegex, ' ').indexOf(selector) >=
|
|
35
|
+
0
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
axe.AbstractVirtualNode = AbstractVirtualNode;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// eslint-disable-next-line no-unused-vars
|
|
2
|
+
class SerialVirtualNode extends axe.AbstractVirtualNode {
|
|
3
|
+
/**
|
|
4
|
+
* Convert a serialised node into a VirtualNode object
|
|
5
|
+
* @param {Object} node Serialised node
|
|
6
|
+
*/
|
|
7
|
+
constructor(serialNode) {
|
|
8
|
+
super();
|
|
9
|
+
this._props = normaliseProps(serialNode);
|
|
10
|
+
this._attrs = normaliseAttrs(serialNode);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Accessof for DOM node properties
|
|
14
|
+
get props() {
|
|
15
|
+
return this._props;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Get the value of the given attribute name.
|
|
20
|
+
* @param {String} attrName The name of the attribute.
|
|
21
|
+
* @return {String|null} The value of the attribute or null if the attribute does not exist
|
|
22
|
+
*/
|
|
23
|
+
attr(attrName) {
|
|
24
|
+
return this._attrs[attrName] || null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Determine if the element has the given attribute.
|
|
29
|
+
* @param {String} attrName The name of the attribute
|
|
30
|
+
* @return {Boolean} True if the element has the attribute, false otherwise.
|
|
31
|
+
*/
|
|
32
|
+
hasAttr(attrName) {
|
|
33
|
+
return this._attrs[attrName] !== undefined;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Convert between serialised props and DOM-like properties
|
|
39
|
+
* @param {Object} serialNode
|
|
40
|
+
* @return {Object} normalProperties
|
|
41
|
+
*/
|
|
42
|
+
function normaliseProps(serialNode) {
|
|
43
|
+
let { nodeName, nodeType = 1 } = serialNode;
|
|
44
|
+
axe.utils.assert(
|
|
45
|
+
nodeType === 1,
|
|
46
|
+
`nodeType has to be undefined or 1, got '${nodeType}'`
|
|
47
|
+
);
|
|
48
|
+
axe.utils.assert(
|
|
49
|
+
typeof nodeName === 'string',
|
|
50
|
+
`nodeName has to be a string, got '${nodeName}'`
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
const props = {
|
|
54
|
+
...serialNode,
|
|
55
|
+
nodeType,
|
|
56
|
+
nodeName: nodeName.toLowerCase()
|
|
57
|
+
};
|
|
58
|
+
delete props.attributes;
|
|
59
|
+
return Object.freeze(props);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Convert between serialised attributes and DOM-like attributes
|
|
64
|
+
* @param {Object} serialNode
|
|
65
|
+
* @return {Object} normalAttributes
|
|
66
|
+
*/
|
|
67
|
+
function normaliseAttrs({ attributes = {} }) {
|
|
68
|
+
const attrMap = {
|
|
69
|
+
htmlFor: 'for',
|
|
70
|
+
className: 'class'
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
return Object.keys(attributes).reduce((attrs, attrName) => {
|
|
74
|
+
const value = attributes[attrName];
|
|
75
|
+
axe.utils.assert(
|
|
76
|
+
typeof value !== 'object' || value === null,
|
|
77
|
+
`expects attributes not to be an object, '${attrName}' was`
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
if (value !== undefined) {
|
|
81
|
+
const mappedName = attrMap[attrName] || attrName;
|
|
82
|
+
attrs[mappedName] = value !== null ? String(value) : null;
|
|
83
|
+
}
|
|
84
|
+
return attrs;
|
|
85
|
+
}, {});
|
|
86
|
+
}
|