OLD | NEW |
(Empty) | |
| 1 /*! aXe v2.3.1 |
| 2 * Copyright (c) 2017 Deque Systems, Inc. |
| 3 * |
| 4 * Your use of this Source Code Form is subject to the terms of the Mozilla Publ
ic |
| 5 * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 7 * |
| 8 * This entire copyright notice must appear in every copy of this file you |
| 9 * distribute or in any file that contains substantial portions of this source |
| 10 * code. |
| 11 */ |
| 12 (function axeFunction(window) { |
| 13 var global = window; |
| 14 var document = window.document; |
| 15 'use strict'; |
| 16 var _typeof = typeof Symbol === 'function' && typeof Symbol.iterator === 'symb
ol' ? function(obj) { |
| 17 return typeof obj; |
| 18 } : function(obj) { |
| 19 return obj && typeof Symbol === 'function' && obj.constructor === Symbol &&
obj !== Symbol.prototype ? 'symbol' : typeof obj; |
| 20 }; |
| 21 var axe = axe || {}; |
| 22 axe.version = '2.3.1'; |
| 23 if (typeof define === 'function' && define.amd) { |
| 24 define([], function() { |
| 25 'use strict'; |
| 26 return axe; |
| 27 }); |
| 28 } |
| 29 if ((typeof module === 'undefined' ? 'undefined' : _typeof(module)) === 'objec
t' && module.exports && typeof axeFunction.toString === 'function') { |
| 30 axe.source = '(' + axeFunction.toString() + ')(typeof window === "object" ?
window : this);'; |
| 31 module.exports = axe; |
| 32 } |
| 33 if (typeof window.getComputedStyle === 'function') { |
| 34 window.axe = axe; |
| 35 } |
| 36 var commons; |
| 37 function SupportError(error) { |
| 38 this.name = 'SupportError'; |
| 39 this.cause = error.cause; |
| 40 this.message = '`' + error.cause + '` - feature unsupported in your environm
ent.'; |
| 41 if (error.ruleId) { |
| 42 this.ruleId = error.ruleId; |
| 43 this.message += ' Skipping ' + this.ruleId + ' rule.'; |
| 44 } |
| 45 this.stack = new Error().stack; |
| 46 } |
| 47 SupportError.prototype = Object.create(Error.prototype); |
| 48 SupportError.prototype.constructor = SupportError; |
| 49 'use strict'; |
| 50 var utils = axe.utils = {}; |
| 51 'use strict'; |
| 52 var helpers = {}; |
| 53 'use strict'; |
| 54 var _typeof = typeof Symbol === 'function' && typeof Symbol.iterator === 'symb
ol' ? function(obj) { |
| 55 return typeof obj; |
| 56 } : function(obj) { |
| 57 return obj && typeof Symbol === 'function' && obj.constructor === Symbol &&
obj !== Symbol.prototype ? 'symbol' : typeof obj; |
| 58 }; |
| 59 function getDefaultConfiguration(audit) { |
| 60 'use strict'; |
| 61 var config; |
| 62 if (audit) { |
| 63 config = axe.utils.clone(audit); |
| 64 config.commons = audit.commons; |
| 65 } else { |
| 66 config = {}; |
| 67 } |
| 68 config.reporter = config.reporter || null; |
| 69 config.rules = config.rules || []; |
| 70 config.checks = config.checks || []; |
| 71 config.data = Object.assign({ |
| 72 checks: {}, |
| 73 rules: {} |
| 74 }, config.data); |
| 75 return config; |
| 76 } |
| 77 function unpackToObject(collection, audit, method) { |
| 78 'use strict'; |
| 79 var i, l; |
| 80 for (i = 0, l = collection.length; i < l; i++) { |
| 81 audit[method](collection[i]); |
| 82 } |
| 83 } |
| 84 function Audit(audit) { |
| 85 this.brand = 'axe'; |
| 86 this.application = 'axeAPI'; |
| 87 this.tagExclude = [ 'experimental' ]; |
| 88 this.defaultConfig = audit; |
| 89 this._init(); |
| 90 } |
| 91 Audit.prototype._init = function() { |
| 92 var audit = getDefaultConfiguration(this.defaultConfig); |
| 93 axe.commons = commons = audit.commons; |
| 94 this.reporter = audit.reporter; |
| 95 this.commands = {}; |
| 96 this.rules = []; |
| 97 this.checks = {}; |
| 98 unpackToObject(audit.rules, this, 'addRule'); |
| 99 unpackToObject(audit.checks, this, 'addCheck'); |
| 100 this.data = {}; |
| 101 this.data.checks = audit.data && audit.data.checks || {}; |
| 102 this.data.rules = audit.data && audit.data.rules || {}; |
| 103 this.data.failureSummaries = audit.data && audit.data.failureSummaries || {}
; |
| 104 this.data.incompleteFallbackMessage = audit.data && audit.data.incompleteFal
lbackMessage || ''; |
| 105 this._constructHelpUrls(); |
| 106 }; |
| 107 Audit.prototype.registerCommand = function(command) { |
| 108 'use strict'; |
| 109 this.commands[command.id] = command.callback; |
| 110 }; |
| 111 Audit.prototype.addRule = function(spec) { |
| 112 'use strict'; |
| 113 if (spec.metadata) { |
| 114 this.data.rules[spec.id] = spec.metadata; |
| 115 } |
| 116 var rule = this.getRule(spec.id); |
| 117 if (rule) { |
| 118 rule.configure(spec); |
| 119 } else { |
| 120 this.rules.push(new Rule(spec, this)); |
| 121 } |
| 122 }; |
| 123 Audit.prototype.addCheck = function(spec) { |
| 124 'use strict'; |
| 125 var metadata = spec.metadata; |
| 126 if ((typeof metadata === 'undefined' ? 'undefined' : _typeof(metadata)) ===
'object') { |
| 127 this.data.checks[spec.id] = metadata; |
| 128 if (_typeof(metadata.messages) === 'object') { |
| 129 Object.keys(metadata.messages).filter(function(prop) { |
| 130 return metadata.messages.hasOwnProperty(prop) && typeof metadata.messa
ges[prop] === 'string'; |
| 131 }).forEach(function(prop) { |
| 132 if (metadata.messages[prop].indexOf('function') === 0) { |
| 133 metadata.messages[prop] = new Function('return ' + metadata.messages
[prop] + ';')(); |
| 134 } |
| 135 }); |
| 136 } |
| 137 } |
| 138 if (this.checks[spec.id]) { |
| 139 this.checks[spec.id].configure(spec); |
| 140 } else { |
| 141 this.checks[spec.id] = new Check(spec); |
| 142 } |
| 143 }; |
| 144 Audit.prototype.run = function(context, options, resolve, reject) { |
| 145 'use strict'; |
| 146 this.validateOptions(options); |
| 147 axe._tree = axe.utils.getFlattenedTree(document.body); |
| 148 var q = axe.utils.queue(); |
| 149 this.rules.forEach(function(rule) { |
| 150 if (axe.utils.ruleShouldRun(rule, context, options)) { |
| 151 if (options.performanceTimer) { |
| 152 var markEnd = 'mark_rule_end_' + rule.id; |
| 153 var markStart = 'mark_rule_start_' + rule.id; |
| 154 axe.utils.performanceTimer.mark(markStart); |
| 155 } |
| 156 q.defer(function(res, rej) { |
| 157 rule.run(context, options, function(out) { |
| 158 if (options.performanceTimer) { |
| 159 axe.utils.performanceTimer.mark(markEnd); |
| 160 axe.utils.performanceTimer.measure('rule_' + rule.id, markStart, m
arkEnd); |
| 161 } |
| 162 res(out); |
| 163 }, function(err) { |
| 164 if (!options.debug) { |
| 165 var errResult = Object.assign(new RuleResult(rule), { |
| 166 result: axe.constants.CANTTELL, |
| 167 description: 'An error occured while running this rule', |
| 168 message: err.message, |
| 169 help: err.stack || err.message, |
| 170 error: err |
| 171 }); |
| 172 res(errResult); |
| 173 } else { |
| 174 rej(err); |
| 175 } |
| 176 }); |
| 177 }); |
| 178 } |
| 179 }); |
| 180 q.then(function(results) { |
| 181 axe._tree = undefined; |
| 182 resolve(results.filter(function(result) { |
| 183 return !!result; |
| 184 })); |
| 185 }).catch(reject); |
| 186 }; |
| 187 Audit.prototype.after = function(results, options) { |
| 188 'use strict'; |
| 189 var rules = this.rules; |
| 190 return results.map(function(ruleResult) { |
| 191 var rule = axe.utils.findBy(rules, 'id', ruleResult.id); |
| 192 return rule.after(ruleResult, options); |
| 193 }); |
| 194 }; |
| 195 Audit.prototype.getRule = function(ruleId) { |
| 196 return this.rules.find(function(rule) { |
| 197 return rule.id === ruleId; |
| 198 }); |
| 199 }; |
| 200 Audit.prototype.validateOptions = function(options) { |
| 201 'use strict'; |
| 202 var audit = this; |
| 203 if (_typeof(options.runOnly) === 'object') { |
| 204 var only = options.runOnly; |
| 205 if (only.type === 'rule' && Array.isArray(only.value)) { |
| 206 only.value.forEach(function(ruleId) { |
| 207 if (!audit.getRule(ruleId)) { |
| 208 throw new Error('unknown rule `' + ruleId + '` in options.runOnly'); |
| 209 } |
| 210 }); |
| 211 } else if (Array.isArray(only.value) && only.value.length > 0) { |
| 212 var tags = [].concat(only.value); |
| 213 audit.rules.forEach(function(rule) { |
| 214 var tagPos, i, l; |
| 215 if (!tags) { |
| 216 return; |
| 217 } |
| 218 for (i = 0, l = rule.tags.length; i < l; i++) { |
| 219 tagPos = tags.indexOf(rule.tags[i]); |
| 220 if (tagPos !== -1) { |
| 221 tags.splice(tagPos, 1); |
| 222 } |
| 223 } |
| 224 }); |
| 225 if (tags.length !== 0) { |
| 226 throw new Error('could not find tags `' + tags.join('`, `') + '`'); |
| 227 } |
| 228 } |
| 229 } |
| 230 if (_typeof(options.rules) === 'object') { |
| 231 Object.keys(options.rules).forEach(function(ruleId) { |
| 232 if (!audit.getRule(ruleId)) { |
| 233 throw new Error('unknown rule `' + ruleId + '` in options.rules'); |
| 234 } |
| 235 }); |
| 236 } |
| 237 return options; |
| 238 }; |
| 239 Audit.prototype.setBranding = function(branding) { |
| 240 'use strict'; |
| 241 var previous = { |
| 242 brand: this.brand, |
| 243 application: this.application |
| 244 }; |
| 245 if (branding && branding.hasOwnProperty('brand') && branding.brand && typeof
branding.brand === 'string') { |
| 246 this.brand = branding.brand; |
| 247 } |
| 248 if (branding && branding.hasOwnProperty('application') && branding.applicati
on && typeof branding.application === 'string') { |
| 249 this.application = branding.application; |
| 250 } |
| 251 this._constructHelpUrls(previous); |
| 252 }; |
| 253 function getHelpUrl(_ref, ruleId, version) { |
| 254 var brand = _ref.brand, application = _ref.application; |
| 255 return axe.constants.helpUrlBase + brand + '/' + (version || axe.version.sub
string(0, axe.version.lastIndexOf('.'))) + '/' + ruleId + '?application=' + appl
ication; |
| 256 } |
| 257 Audit.prototype._constructHelpUrls = function() { |
| 258 var _this = this; |
| 259 var previous = arguments.length > 0 && arguments[0] !== undefined ? argument
s[0] : null; |
| 260 var version = axe.version.substring(0, axe.version.lastIndexOf('.')); |
| 261 this.rules.forEach(function(rule) { |
| 262 if (!_this.data.rules[rule.id]) { |
| 263 _this.data.rules[rule.id] = {}; |
| 264 } |
| 265 var metaData = _this.data.rules[rule.id]; |
| 266 if (typeof metaData.helpUrl !== 'string' || previous && metaData.helpUrl =
== getHelpUrl(previous, rule.id, version)) { |
| 267 metaData.helpUrl = getHelpUrl(_this, rule.id, version); |
| 268 } |
| 269 }); |
| 270 }; |
| 271 Audit.prototype.resetRulesAndChecks = function() { |
| 272 'use strict'; |
| 273 this._init(); |
| 274 }; |
| 275 'use strict'; |
| 276 function CheckResult(check) { |
| 277 'use strict'; |
| 278 this.id = check.id; |
| 279 this.data = null; |
| 280 this.relatedNodes = []; |
| 281 this.result = null; |
| 282 } |
| 283 'use strict'; |
| 284 function createExecutionContext(spec) { |
| 285 'use strict'; |
| 286 if (typeof spec === 'string') { |
| 287 return new Function('return ' + spec + ';')(); |
| 288 } |
| 289 return spec; |
| 290 } |
| 291 function Check(spec) { |
| 292 if (spec) { |
| 293 this.id = spec.id; |
| 294 this.configure(spec); |
| 295 } |
| 296 } |
| 297 Check.prototype.enabled = true; |
| 298 Check.prototype.run = function(node, options, resolve, reject) { |
| 299 'use strict'; |
| 300 options = options || {}; |
| 301 var enabled = options.hasOwnProperty('enabled') ? options.enabled : this.ena
bled, checkOptions = options.options || this.options; |
| 302 if (enabled) { |
| 303 var checkResult = new CheckResult(this); |
| 304 var checkHelper = axe.utils.checkHelper(checkResult, options, resolve, rej
ect); |
| 305 var result; |
| 306 try { |
| 307 result = this.evaluate.call(checkHelper, node.actualNode, checkOptions,
node); |
| 308 } catch (e) { |
| 309 reject(e); |
| 310 return; |
| 311 } |
| 312 if (!checkHelper.isAsync) { |
| 313 checkResult.result = result; |
| 314 setTimeout(function() { |
| 315 resolve(checkResult); |
| 316 }, 0); |
| 317 } |
| 318 } else { |
| 319 resolve(null); |
| 320 } |
| 321 }; |
| 322 Check.prototype.configure = function(spec) { |
| 323 var _this = this; |
| 324 [ 'options', 'enabled' ].filter(function(prop) { |
| 325 return spec.hasOwnProperty(prop); |
| 326 }).forEach(function(prop) { |
| 327 return _this[prop] = spec[prop]; |
| 328 }); |
| 329 [ 'evaluate', 'after' ].filter(function(prop) { |
| 330 return spec.hasOwnProperty(prop); |
| 331 }).forEach(function(prop) { |
| 332 return _this[prop] = createExecutionContext(spec[prop]); |
| 333 }); |
| 334 }; |
| 335 'use strict'; |
| 336 var _typeof = typeof Symbol === 'function' && typeof Symbol.iterator === 'symb
ol' ? function(obj) { |
| 337 return typeof obj; |
| 338 } : function(obj) { |
| 339 return obj && typeof Symbol === 'function' && obj.constructor === Symbol &&
obj !== Symbol.prototype ? 'symbol' : typeof obj; |
| 340 }; |
| 341 function pushUniqueFrame(collection, frame) { |
| 342 'use strict'; |
| 343 if (axe.utils.isHidden(frame)) { |
| 344 return; |
| 345 } |
| 346 var fr = axe.utils.findBy(collection, 'node', frame); |
| 347 if (!fr) { |
| 348 collection.push({ |
| 349 node: frame, |
| 350 include: [], |
| 351 exclude: [] |
| 352 }); |
| 353 } |
| 354 } |
| 355 function pushUniqueFrameSelector(context, type, selectorArray) { |
| 356 'use strict'; |
| 357 context.frames = context.frames || []; |
| 358 var result, frame; |
| 359 var frames = document.querySelectorAll(selectorArray.shift()); |
| 360 frameloop: for (var i = 0, l = frames.length; i < l; i++) { |
| 361 frame = frames[i]; |
| 362 for (var j = 0, l2 = context.frames.length; j < l2; j++) { |
| 363 if (context.frames[j].node === frame) { |
| 364 context.frames[j][type].push(selectorArray); |
| 365 break frameloop; |
| 366 } |
| 367 } |
| 368 result = { |
| 369 node: frame, |
| 370 include: [], |
| 371 exclude: [] |
| 372 }; |
| 373 if (selectorArray) { |
| 374 result[type].push(selectorArray); |
| 375 } |
| 376 context.frames.push(result); |
| 377 } |
| 378 } |
| 379 function normalizeContext(context) { |
| 380 'use strict'; |
| 381 if (context && (typeof context === 'undefined' ? 'undefined' : _typeof(conte
xt)) === 'object' || context instanceof NodeList) { |
| 382 if (context instanceof Node) { |
| 383 return { |
| 384 include: [ context ], |
| 385 exclude: [] |
| 386 }; |
| 387 } |
| 388 if (context.hasOwnProperty('include') || context.hasOwnProperty('exclude')
) { |
| 389 return { |
| 390 include: context.include && +context.include.length ? context.include
: [ document ], |
| 391 exclude: context.exclude || [] |
| 392 }; |
| 393 } |
| 394 if (context.length === +context.length) { |
| 395 return { |
| 396 include: context, |
| 397 exclude: [] |
| 398 }; |
| 399 } |
| 400 } |
| 401 if (typeof context === 'string') { |
| 402 return { |
| 403 include: [ context ], |
| 404 exclude: [] |
| 405 }; |
| 406 } |
| 407 return { |
| 408 include: [ document ], |
| 409 exclude: [] |
| 410 }; |
| 411 } |
| 412 function parseSelectorArray(context, type) { |
| 413 'use strict'; |
| 414 var item, result = [], nodeList; |
| 415 for (var i = 0, l = context[type].length; i < l; i++) { |
| 416 item = context[type][i]; |
| 417 if (typeof item === 'string') { |
| 418 nodeList = Array.from(document.querySelectorAll(item)); |
| 419 result = result.concat(nodeList.map(function(node) { |
| 420 return axe.utils.getFlattenedTree(node)[0]; |
| 421 })); |
| 422 break; |
| 423 } else if (item && item.length && !(item instanceof Node)) { |
| 424 if (item.length > 1) { |
| 425 pushUniqueFrameSelector(context, type, item); |
| 426 } else { |
| 427 nodeList = Array.from(document.querySelectorAll(item[0])); |
| 428 result = result.concat(nodeList.map(function(node) { |
| 429 return axe.utils.getFlattenedTree(node)[0]; |
| 430 })); |
| 431 } |
| 432 } else if (item instanceof Node) { |
| 433 result.push(axe.utils.getFlattenedTree(item)[0]); |
| 434 } |
| 435 } |
| 436 return result.filter(function(r) { |
| 437 return r; |
| 438 }); |
| 439 } |
| 440 function validateContext(context) { |
| 441 'use strict'; |
| 442 if (context.include.length === 0) { |
| 443 if (context.frames.length === 0) { |
| 444 var env = axe.utils.respondable.isInFrame() ? 'frame' : 'page'; |
| 445 return new Error('No elements found for include in ' + env + ' Context')
; |
| 446 } |
| 447 context.frames.forEach(function(frame, i) { |
| 448 if (frame.include.length === 0) { |
| 449 return new Error('No elements found for include in Context of frame '
+ i); |
| 450 } |
| 451 }); |
| 452 } |
| 453 } |
| 454 function Context(spec) { |
| 455 'use strict'; |
| 456 var self = this; |
| 457 this.frames = []; |
| 458 this.initiator = spec && typeof spec.initiator === 'boolean' ? spec.initiato
r : true; |
| 459 this.page = false; |
| 460 spec = normalizeContext(spec); |
| 461 this.exclude = spec.exclude; |
| 462 this.include = spec.include; |
| 463 this.include = parseSelectorArray(this, 'include'); |
| 464 this.exclude = parseSelectorArray(this, 'exclude'); |
| 465 axe.utils.select('frame, iframe', this).forEach(function(frame) { |
| 466 if (isNodeInContext(frame, self)) { |
| 467 pushUniqueFrame(self.frames, frame.actualNode); |
| 468 } |
| 469 }); |
| 470 if (this.include.length === 1 && this.include[0].actualNode === document.doc
umentElement) { |
| 471 this.page = true; |
| 472 } |
| 473 var err = validateContext(this); |
| 474 if (err instanceof Error) { |
| 475 throw err; |
| 476 } |
| 477 } |
| 478 'use strict'; |
| 479 function RuleResult(rule) { |
| 480 'use strict'; |
| 481 this.id = rule.id; |
| 482 this.result = axe.constants.NA; |
| 483 this.pageLevel = rule.pageLevel; |
| 484 this.impact = null; |
| 485 this.nodes = []; |
| 486 } |
| 487 'use strict'; |
| 488 function Rule(spec, parentAudit) { |
| 489 'use strict'; |
| 490 this._audit = parentAudit; |
| 491 this.id = spec.id; |
| 492 this.selector = spec.selector || '*'; |
| 493 this.excludeHidden = typeof spec.excludeHidden === 'boolean' ? spec.excludeH
idden : true; |
| 494 this.enabled = typeof spec.enabled === 'boolean' ? spec.enabled : true; |
| 495 this.pageLevel = typeof spec.pageLevel === 'boolean' ? spec.pageLevel : fals
e; |
| 496 this.any = spec.any || []; |
| 497 this.all = spec.all || []; |
| 498 this.none = spec.none || []; |
| 499 this.tags = spec.tags || []; |
| 500 if (spec.matches) { |
| 501 this.matches = createExecutionContext(spec.matches); |
| 502 } |
| 503 } |
| 504 Rule.prototype.matches = function() { |
| 505 'use strict'; |
| 506 return true; |
| 507 }; |
| 508 Rule.prototype.gather = function(context) { |
| 509 'use strict'; |
| 510 var elements = axe.utils.select(this.selector, context); |
| 511 if (this.excludeHidden) { |
| 512 return elements.filter(function(element) { |
| 513 return !axe.utils.isHidden(element.actualNode); |
| 514 }); |
| 515 } |
| 516 return elements; |
| 517 }; |
| 518 Rule.prototype.runChecks = function(type, node, options, resolve, reject) { |
| 519 'use strict'; |
| 520 var self = this; |
| 521 var checkQueue = axe.utils.queue(); |
| 522 this[type].forEach(function(c) { |
| 523 var check = self._audit.checks[c.id || c]; |
| 524 var option = axe.utils.getCheckOption(check, self.id, options); |
| 525 checkQueue.defer(function(res, rej) { |
| 526 check.run(node, option, res, rej); |
| 527 }); |
| 528 }); |
| 529 checkQueue.then(function(results) { |
| 530 results = results.filter(function(check) { |
| 531 return check; |
| 532 }); |
| 533 resolve({ |
| 534 type: type, |
| 535 results: results |
| 536 }); |
| 537 }).catch(reject); |
| 538 }; |
| 539 Rule.prototype.run = function(context, options, resolve, reject) { |
| 540 var _this = this; |
| 541 var q = axe.utils.queue(); |
| 542 var ruleResult = new RuleResult(this); |
| 543 var nodes = void 0; |
| 544 try { |
| 545 nodes = this.gather(context).filter(function(node) { |
| 546 return _this.matches(node.actualNode); |
| 547 }); |
| 548 } catch (error) { |
| 549 reject(new SupportError({ |
| 550 cause: error, |
| 551 ruleId: this.id |
| 552 })); |
| 553 return; |
| 554 } |
| 555 if (options.performanceTimer) { |
| 556 axe.log('gather (', nodes.length, '):', axe.utils.performanceTimer.timeEla
psed() + 'ms'); |
| 557 } |
| 558 nodes.forEach(function(node) { |
| 559 q.defer(function(resolveNode, rejectNode) { |
| 560 var checkQueue = axe.utils.queue(); |
| 561 checkQueue.defer(function(res, rej) { |
| 562 _this.runChecks('any', node, options, res, rej); |
| 563 }); |
| 564 checkQueue.defer(function(res, rej) { |
| 565 _this.runChecks('all', node, options, res, rej); |
| 566 }); |
| 567 checkQueue.defer(function(res, rej) { |
| 568 _this.runChecks('none', node, options, res, rej); |
| 569 }); |
| 570 checkQueue.then(function(results) { |
| 571 if (results.length) { |
| 572 var hasResults = false, result = {}; |
| 573 results.forEach(function(r) { |
| 574 var res = r.results.filter(function(result) { |
| 575 return result; |
| 576 }); |
| 577 result[r.type] = res; |
| 578 if (res.length) { |
| 579 hasResults = true; |
| 580 } |
| 581 }); |
| 582 if (hasResults) { |
| 583 result.node = new axe.utils.DqElement(node.actualNode, options); |
| 584 ruleResult.nodes.push(result); |
| 585 } |
| 586 } |
| 587 resolveNode(); |
| 588 }).catch(function(err) { |
| 589 return rejectNode(err); |
| 590 }); |
| 591 }); |
| 592 }); |
| 593 q.then(function() { |
| 594 return resolve(ruleResult); |
| 595 }).catch(function(error) { |
| 596 return reject(error); |
| 597 }); |
| 598 }; |
| 599 function findAfterChecks(rule) { |
| 600 'use strict'; |
| 601 return axe.utils.getAllChecks(rule).map(function(c) { |
| 602 var check = rule._audit.checks[c.id || c]; |
| 603 return check && typeof check.after === 'function' ? check : null; |
| 604 }).filter(Boolean); |
| 605 } |
| 606 function findCheckResults(nodes, checkID) { |
| 607 'use strict'; |
| 608 var checkResults = []; |
| 609 nodes.forEach(function(nodeResult) { |
| 610 var checks = axe.utils.getAllChecks(nodeResult); |
| 611 checks.forEach(function(checkResult) { |
| 612 if (checkResult.id === checkID) { |
| 613 checkResults.push(checkResult); |
| 614 } |
| 615 }); |
| 616 }); |
| 617 return checkResults; |
| 618 } |
| 619 function filterChecks(checks) { |
| 620 'use strict'; |
| 621 return checks.filter(function(check) { |
| 622 return check.filtered !== true; |
| 623 }); |
| 624 } |
| 625 function sanitizeNodes(result) { |
| 626 'use strict'; |
| 627 var checkTypes = [ 'any', 'all', 'none' ]; |
| 628 var nodes = result.nodes.filter(function(detail) { |
| 629 var length = 0; |
| 630 checkTypes.forEach(function(type) { |
| 631 detail[type] = filterChecks(detail[type]); |
| 632 length += detail[type].length; |
| 633 }); |
| 634 return length > 0; |
| 635 }); |
| 636 if (result.pageLevel && nodes.length) { |
| 637 nodes = [ nodes.reduce(function(a, b) { |
| 638 if (a) { |
| 639 checkTypes.forEach(function(type) { |
| 640 a[type].push.apply(a[type], b[type]); |
| 641 }); |
| 642 return a; |
| 643 } |
| 644 }) ]; |
| 645 } |
| 646 return nodes; |
| 647 } |
| 648 Rule.prototype.after = function(result, options) { |
| 649 'use strict'; |
| 650 var afterChecks = findAfterChecks(this); |
| 651 var ruleID = this.id; |
| 652 afterChecks.forEach(function(check) { |
| 653 var beforeResults = findCheckResults(result.nodes, check.id); |
| 654 var option = axe.utils.getCheckOption(check, ruleID, options); |
| 655 var afterResults = check.after(beforeResults, option); |
| 656 beforeResults.forEach(function(item) { |
| 657 if (afterResults.indexOf(item) === -1) { |
| 658 item.filtered = true; |
| 659 } |
| 660 }); |
| 661 }); |
| 662 result.nodes = sanitizeNodes(result); |
| 663 return result; |
| 664 }; |
| 665 Rule.prototype.configure = function(spec) { |
| 666 'use strict'; |
| 667 if (spec.hasOwnProperty('selector')) { |
| 668 this.selector = spec.selector; |
| 669 } |
| 670 if (spec.hasOwnProperty('excludeHidden')) { |
| 671 this.excludeHidden = typeof spec.excludeHidden === 'boolean' ? spec.exclud
eHidden : true; |
| 672 } |
| 673 if (spec.hasOwnProperty('enabled')) { |
| 674 this.enabled = typeof spec.enabled === 'boolean' ? spec.enabled : true; |
| 675 } |
| 676 if (spec.hasOwnProperty('pageLevel')) { |
| 677 this.pageLevel = typeof spec.pageLevel === 'boolean' ? spec.pageLevel : fa
lse; |
| 678 } |
| 679 if (spec.hasOwnProperty('any')) { |
| 680 this.any = spec.any; |
| 681 } |
| 682 if (spec.hasOwnProperty('all')) { |
| 683 this.all = spec.all; |
| 684 } |
| 685 if (spec.hasOwnProperty('none')) { |
| 686 this.none = spec.none; |
| 687 } |
| 688 if (spec.hasOwnProperty('tags')) { |
| 689 this.tags = spec.tags; |
| 690 } |
| 691 if (spec.hasOwnProperty('matches')) { |
| 692 if (typeof spec.matches === 'string') { |
| 693 this.matches = new Function('return ' + spec.matches + ';')(); |
| 694 } else { |
| 695 this.matches = spec.matches; |
| 696 } |
| 697 } |
| 698 }; |
| 699 'use strict'; |
| 700 (function(axe) { |
| 701 var definitions = [ { |
| 702 name: 'NA', |
| 703 value: 'inapplicable', |
| 704 priority: 0, |
| 705 group: 'inapplicable' |
| 706 }, { |
| 707 name: 'PASS', |
| 708 value: 'passed', |
| 709 priority: 1, |
| 710 group: 'passes' |
| 711 }, { |
| 712 name: 'CANTTELL', |
| 713 value: 'cantTell', |
| 714 priority: 2, |
| 715 group: 'incomplete' |
| 716 }, { |
| 717 name: 'FAIL', |
| 718 value: 'failed', |
| 719 priority: 3, |
| 720 group: 'violations' |
| 721 } ]; |
| 722 var constants = { |
| 723 helpUrlBase: 'https://dequeuniversity.com/rules/', |
| 724 results: [], |
| 725 resultGroups: [], |
| 726 resultGroupMap: {}, |
| 727 impact: Object.freeze([ 'minor', 'moderate', 'serious', 'critical' ]) |
| 728 }; |
| 729 definitions.forEach(function(definition) { |
| 730 var name = definition.name; |
| 731 var value = definition.value; |
| 732 var priority = definition.priority; |
| 733 var group = definition.group; |
| 734 constants[name] = value; |
| 735 constants[name + '_PRIO'] = priority; |
| 736 constants[name + '_GROUP'] = group; |
| 737 constants.results[priority] = value; |
| 738 constants.resultGroups[priority] = group; |
| 739 constants.resultGroupMap[value] = group; |
| 740 }); |
| 741 Object.freeze(constants.results); |
| 742 Object.freeze(constants.resultGroups); |
| 743 Object.freeze(constants.resultGroupMap); |
| 744 Object.freeze(constants); |
| 745 Object.defineProperty(axe, 'constants', { |
| 746 value: constants, |
| 747 enumerable: true, |
| 748 configurable: false, |
| 749 writable: false |
| 750 }); |
| 751 })(axe); |
| 752 'use strict'; |
| 753 var _typeof = typeof Symbol === 'function' && typeof Symbol.iterator === 'symb
ol' ? function(obj) { |
| 754 return typeof obj; |
| 755 } : function(obj) { |
| 756 return obj && typeof Symbol === 'function' && obj.constructor === Symbol &&
obj !== Symbol.prototype ? 'symbol' : typeof obj; |
| 757 }; |
| 758 axe.log = function() { |
| 759 'use strict'; |
| 760 if ((typeof console === 'undefined' ? 'undefined' : _typeof(console)) === 'o
bject' && console.log) { |
| 761 Function.prototype.apply.call(console.log, console, arguments); |
| 762 } |
| 763 }; |
| 764 'use strict'; |
| 765 var _typeof = typeof Symbol === 'function' && typeof Symbol.iterator === 'symb
ol' ? function(obj) { |
| 766 return typeof obj; |
| 767 } : function(obj) { |
| 768 return obj && typeof Symbol === 'function' && obj.constructor === Symbol &&
obj !== Symbol.prototype ? 'symbol' : typeof obj; |
| 769 }; |
| 770 axe.a11yCheck = function(context, options, callback) { |
| 771 'use strict'; |
| 772 if (typeof options === 'function') { |
| 773 callback = options; |
| 774 options = {}; |
| 775 } |
| 776 if (!options || (typeof options === 'undefined' ? 'undefined' : _typeof(opti
ons)) !== 'object') { |
| 777 options = {}; |
| 778 } |
| 779 var audit = axe._audit; |
| 780 if (!audit) { |
| 781 throw new Error('No audit configured'); |
| 782 } |
| 783 options.reporter = options.reporter || audit.reporter || 'v2'; |
| 784 if (options.performanceTimer) { |
| 785 axe.utils.performanceTimer.start(); |
| 786 } |
| 787 var reporter = axe.getReporter(options.reporter); |
| 788 axe._runRules(context, options, function(results) { |
| 789 var res = reporter(results, options, callback); |
| 790 if (res !== undefined) { |
| 791 if (options.performanceTimer) { |
| 792 axe.utils.performanceTimer.end(); |
| 793 } |
| 794 callback(res); |
| 795 } |
| 796 }, axe.log); |
| 797 }; |
| 798 'use strict'; |
| 799 function cleanupPlugins(resolve, reject) { |
| 800 'use strict'; |
| 801 if (!axe._audit) { |
| 802 throw new Error('No audit configured'); |
| 803 } |
| 804 var q = axe.utils.queue(); |
| 805 var cleanupErrors = []; |
| 806 Object.keys(axe.plugins).forEach(function(key) { |
| 807 q.defer(function(res) { |
| 808 var rej = function rej(err) { |
| 809 cleanupErrors.push(err); |
| 810 res(); |
| 811 }; |
| 812 try { |
| 813 axe.plugins[key].cleanup(res, rej); |
| 814 } catch (err) { |
| 815 rej(err); |
| 816 } |
| 817 }); |
| 818 }); |
| 819 axe.utils.toArray(document.querySelectorAll('frame, iframe')).forEach(functi
on(frame) { |
| 820 q.defer(function(res, rej) { |
| 821 return axe.utils.sendCommandToFrame(frame, { |
| 822 command: 'cleanup-plugin' |
| 823 }, res, rej); |
| 824 }); |
| 825 }); |
| 826 q.then(function(results) { |
| 827 if (cleanupErrors.length === 0) { |
| 828 resolve(results); |
| 829 } else { |
| 830 reject(cleanupErrors); |
| 831 } |
| 832 }).catch(reject); |
| 833 } |
| 834 axe.cleanup = cleanupPlugins; |
| 835 'use strict'; |
| 836 function configureChecksRulesAndBranding(spec) { |
| 837 'use strict'; |
| 838 var audit; |
| 839 audit = axe._audit; |
| 840 if (!audit) { |
| 841 throw new Error('No audit configured'); |
| 842 } |
| 843 if (spec.reporter && (typeof spec.reporter === 'function' || reporters[spec.
reporter])) { |
| 844 audit.reporter = spec.reporter; |
| 845 } |
| 846 if (spec.checks) { |
| 847 spec.checks.forEach(function(check) { |
| 848 audit.addCheck(check); |
| 849 }); |
| 850 } |
| 851 if (spec.rules) { |
| 852 spec.rules.forEach(function(rule) { |
| 853 audit.addRule(rule); |
| 854 }); |
| 855 } |
| 856 if (typeof spec.branding !== 'undefined') { |
| 857 audit.setBranding(spec.branding); |
| 858 } else { |
| 859 audit._constructHelpUrls(); |
| 860 } |
| 861 if (spec.tagExclude) { |
| 862 audit.tagExclude = spec.tagExclude; |
| 863 } |
| 864 } |
| 865 axe.configure = configureChecksRulesAndBranding; |
| 866 'use strict'; |
| 867 axe.getRules = function(tags) { |
| 868 'use strict'; |
| 869 tags = tags || []; |
| 870 var matchingRules = !tags.length ? axe._audit.rules : axe._audit.rules.filte
r(function(item) { |
| 871 return !!tags.filter(function(tag) { |
| 872 return item.tags.indexOf(tag) !== -1; |
| 873 }).length; |
| 874 }); |
| 875 var ruleData = axe._audit.data.rules || {}; |
| 876 return matchingRules.map(function(matchingRule) { |
| 877 var rd = ruleData[matchingRule.id] || {}; |
| 878 return { |
| 879 ruleId: matchingRule.id, |
| 880 description: rd.description, |
| 881 help: rd.help, |
| 882 helpUrl: rd.helpUrl, |
| 883 tags: matchingRule.tags |
| 884 }; |
| 885 }); |
| 886 }; |
| 887 'use strict'; |
| 888 function runCommand(data, keepalive, callback) { |
| 889 'use strict'; |
| 890 var resolve = callback; |
| 891 var reject = function reject(err) { |
| 892 if (err instanceof Error === false) { |
| 893 err = new Error(err); |
| 894 } |
| 895 callback(err); |
| 896 }; |
| 897 var context = data && data.context || {}; |
| 898 if (context.include && !context.include.length) { |
| 899 context.include = [ document ]; |
| 900 } |
| 901 var options = data && data.options || {}; |
| 902 switch (data.command) { |
| 903 case 'rules': |
| 904 return runRules(context, options, resolve, reject); |
| 905 |
| 906 case 'cleanup-plugin': |
| 907 return cleanupPlugins(resolve, reject); |
| 908 |
| 909 default: |
| 910 if (axe._audit && axe._audit.commands && axe._audit.commands[data.command]
) { |
| 911 return axe._audit.commands[data.command](data, callback); |
| 912 } |
| 913 } |
| 914 } |
| 915 axe._load = function(audit) { |
| 916 'use strict'; |
| 917 axe.utils.respondable.subscribe('axe.ping', function(data, keepalive, respon
d) { |
| 918 respond({ |
| 919 axe: true |
| 920 }); |
| 921 }); |
| 922 axe.utils.respondable.subscribe('axe.start', runCommand); |
| 923 axe._audit = new Audit(audit); |
| 924 }; |
| 925 'use strict'; |
| 926 var axe = axe || {}; |
| 927 axe.plugins = {}; |
| 928 function Plugin(spec) { |
| 929 'use strict'; |
| 930 this._run = spec.run; |
| 931 this._collect = spec.collect; |
| 932 this._registry = {}; |
| 933 spec.commands.forEach(function(command) { |
| 934 axe._audit.registerCommand(command); |
| 935 }); |
| 936 } |
| 937 Plugin.prototype.run = function() { |
| 938 'use strict'; |
| 939 return this._run.apply(this, arguments); |
| 940 }; |
| 941 Plugin.prototype.collect = function() { |
| 942 'use strict'; |
| 943 return this._collect.apply(this, arguments); |
| 944 }; |
| 945 Plugin.prototype.cleanup = function(done) { |
| 946 'use strict'; |
| 947 var q = axe.utils.queue(); |
| 948 var that = this; |
| 949 Object.keys(this._registry).forEach(function(key) { |
| 950 q.defer(function(done) { |
| 951 that._registry[key].cleanup(done); |
| 952 }); |
| 953 }); |
| 954 q.then(function() { |
| 955 done(); |
| 956 }); |
| 957 }; |
| 958 Plugin.prototype.add = function(impl) { |
| 959 'use strict'; |
| 960 this._registry[impl.id] = impl; |
| 961 }; |
| 962 axe.registerPlugin = function(plugin) { |
| 963 'use strict'; |
| 964 axe.plugins[plugin.id] = new Plugin(plugin); |
| 965 }; |
| 966 'use strict'; |
| 967 var reporters = {}; |
| 968 var defaultReporter; |
| 969 axe.getReporter = function(reporter) { |
| 970 'use strict'; |
| 971 if (typeof reporter === 'string' && reporters[reporter]) { |
| 972 return reporters[reporter]; |
| 973 } |
| 974 if (typeof reporter === 'function') { |
| 975 return reporter; |
| 976 } |
| 977 return defaultReporter; |
| 978 }; |
| 979 axe.addReporter = function registerReporter(name, cb, isDefault) { |
| 980 'use strict'; |
| 981 reporters[name] = cb; |
| 982 if (isDefault) { |
| 983 defaultReporter = cb; |
| 984 } |
| 985 }; |
| 986 'use strict'; |
| 987 function resetConfiguration() { |
| 988 'use strict'; |
| 989 var audit = axe._audit; |
| 990 if (!audit) { |
| 991 throw new Error('No audit configured'); |
| 992 } |
| 993 audit.resetRulesAndChecks(); |
| 994 } |
| 995 axe.reset = resetConfiguration; |
| 996 'use strict'; |
| 997 function runRules(context, options, resolve, reject) { |
| 998 'use strict'; |
| 999 try { |
| 1000 context = new Context(context); |
| 1001 } catch (e) { |
| 1002 return reject(e); |
| 1003 } |
| 1004 var q = axe.utils.queue(); |
| 1005 var audit = axe._audit; |
| 1006 if (options.performanceTimer) { |
| 1007 axe.utils.performanceTimer.auditStart(); |
| 1008 } |
| 1009 if (context.frames.length && options.iframes !== false) { |
| 1010 q.defer(function(res, rej) { |
| 1011 axe.utils.collectResultsFromFrames(context, options, 'rules', null, res,
rej); |
| 1012 }); |
| 1013 } |
| 1014 q.defer(function(res, rej) { |
| 1015 audit.run(context, options, res, rej); |
| 1016 }); |
| 1017 q.then(function(data) { |
| 1018 try { |
| 1019 if (options.performanceTimer) { |
| 1020 axe.utils.performanceTimer.auditEnd(); |
| 1021 } |
| 1022 var results = axe.utils.mergeResults(data.map(function(d) { |
| 1023 return { |
| 1024 results: d |
| 1025 }; |
| 1026 })); |
| 1027 if (context.initiator) { |
| 1028 results = audit.after(results, options); |
| 1029 results.forEach(axe.utils.publishMetaData); |
| 1030 results = results.map(axe.utils.finalizeRuleResult); |
| 1031 } |
| 1032 try { |
| 1033 resolve(results); |
| 1034 } catch (e) { |
| 1035 axe.log(e); |
| 1036 } |
| 1037 } catch (e) { |
| 1038 reject(e); |
| 1039 } |
| 1040 }).catch(reject); |
| 1041 } |
| 1042 axe._runRules = runRules; |
| 1043 'use strict'; |
| 1044 var _typeof = typeof Symbol === 'function' && typeof Symbol.iterator === 'symb
ol' ? function(obj) { |
| 1045 return typeof obj; |
| 1046 } : function(obj) { |
| 1047 return obj && typeof Symbol === 'function' && obj.constructor === Symbol &&
obj !== Symbol.prototype ? 'symbol' : typeof obj; |
| 1048 }; |
| 1049 function isContext(potential) { |
| 1050 'use strict'; |
| 1051 switch (true) { |
| 1052 case typeof potential === 'string': |
| 1053 case Array.isArray(potential): |
| 1054 case Node && potential instanceof Node: |
| 1055 case NodeList && potential instanceof NodeList: |
| 1056 return true; |
| 1057 |
| 1058 case (typeof potential === 'undefined' ? 'undefined' : _typeof(potential))
!== 'object': |
| 1059 return false; |
| 1060 |
| 1061 case potential.include !== undefined: |
| 1062 case potential.exclude !== undefined: |
| 1063 case typeof potential.length === 'number': |
| 1064 return true; |
| 1065 |
| 1066 default: |
| 1067 return false; |
| 1068 } |
| 1069 } |
| 1070 var noop = function noop() {}; |
| 1071 function normalizeRunParams(context, options, callback) { |
| 1072 'use strict'; |
| 1073 var typeErr = new TypeError('axe.run arguments are invalid'); |
| 1074 if (!isContext(context)) { |
| 1075 if (callback !== undefined) { |
| 1076 throw typeErr; |
| 1077 } |
| 1078 callback = options; |
| 1079 options = context; |
| 1080 context = document; |
| 1081 } |
| 1082 if ((typeof options === 'undefined' ? 'undefined' : _typeof(options)) !== 'o
bject') { |
| 1083 if (callback !== undefined) { |
| 1084 throw typeErr; |
| 1085 } |
| 1086 callback = options; |
| 1087 options = {}; |
| 1088 } |
| 1089 if (typeof callback !== 'function' && callback !== undefined) { |
| 1090 throw typeErr; |
| 1091 } |
| 1092 return { |
| 1093 context: context, |
| 1094 options: options, |
| 1095 callback: callback || noop |
| 1096 }; |
| 1097 } |
| 1098 axe.run = function(context, options, callback) { |
| 1099 'use strict'; |
| 1100 if (!axe._audit) { |
| 1101 throw new Error('No audit configured'); |
| 1102 } |
| 1103 var args = normalizeRunParams(context, options, callback); |
| 1104 context = args.context; |
| 1105 options = args.options; |
| 1106 callback = args.callback; |
| 1107 options.reporter = options.reporter || axe._audit.reporter || 'v1'; |
| 1108 if (options.performanceTimer) { |
| 1109 axe.utils.performanceTimer.start(); |
| 1110 } |
| 1111 var p = void 0; |
| 1112 var reject = noop; |
| 1113 var resolve = noop; |
| 1114 if (window.Promise && callback === noop) { |
| 1115 p = new Promise(function(_resolve, _reject) { |
| 1116 reject = _reject; |
| 1117 resolve = _resolve; |
| 1118 }); |
| 1119 } |
| 1120 axe._runRules(context, options, function(rawResults) { |
| 1121 var respond = function respond(results) { |
| 1122 try { |
| 1123 callback(null, results); |
| 1124 } catch (e) { |
| 1125 axe.log(e); |
| 1126 } |
| 1127 resolve(results); |
| 1128 }; |
| 1129 if (options.performanceTimer) { |
| 1130 axe.utils.performanceTimer.end(); |
| 1131 } |
| 1132 try { |
| 1133 var reporter = axe.getReporter(options.reporter); |
| 1134 var results = reporter(rawResults, options, respond); |
| 1135 if (results !== undefined) { |
| 1136 respond(results); |
| 1137 } |
| 1138 } catch (err) { |
| 1139 callback(err); |
| 1140 reject(err); |
| 1141 } |
| 1142 }, function(err) { |
| 1143 callback(err); |
| 1144 reject(err); |
| 1145 }); |
| 1146 return p; |
| 1147 }; |
| 1148 'use strict'; |
| 1149 helpers.failureSummary = function failureSummary(nodeData) { |
| 1150 'use strict'; |
| 1151 var failingChecks = {}; |
| 1152 failingChecks.none = nodeData.none.concat(nodeData.all); |
| 1153 failingChecks.any = nodeData.any; |
| 1154 return Object.keys(failingChecks).map(function(key) { |
| 1155 if (!failingChecks[key].length) { |
| 1156 return; |
| 1157 } |
| 1158 var sum = axe._audit.data.failureSummaries[key]; |
| 1159 if (sum && typeof sum.failureMessage === 'function') { |
| 1160 return sum.failureMessage(failingChecks[key].map(function(check) { |
| 1161 return check.message || ''; |
| 1162 })); |
| 1163 } |
| 1164 }).filter(function(i) { |
| 1165 return i !== undefined; |
| 1166 }).join('\n\n'); |
| 1167 }; |
| 1168 'use strict'; |
| 1169 helpers.incompleteFallbackMessage = function incompleteFallbackMessage() { |
| 1170 'use strict'; |
| 1171 return axe._audit.data.incompleteFallbackMessage(); |
| 1172 }; |
| 1173 'use strict'; |
| 1174 var _typeof = typeof Symbol === 'function' && typeof Symbol.iterator === 'symb
ol' ? function(obj) { |
| 1175 return typeof obj; |
| 1176 } : function(obj) { |
| 1177 return obj && typeof Symbol === 'function' && obj.constructor === Symbol &&
obj !== Symbol.prototype ? 'symbol' : typeof obj; |
| 1178 }; |
| 1179 function normalizeRelatedNodes(node, options) { |
| 1180 'use strict'; |
| 1181 [ 'any', 'all', 'none' ].forEach(function(type) { |
| 1182 if (!Array.isArray(node[type])) { |
| 1183 return; |
| 1184 } |
| 1185 node[type].filter(function(checkRes) { |
| 1186 return Array.isArray(checkRes.relatedNodes); |
| 1187 }).forEach(function(checkRes) { |
| 1188 checkRes.relatedNodes = checkRes.relatedNodes.map(function(relatedNode)
{ |
| 1189 var res = { |
| 1190 html: relatedNode.source |
| 1191 }; |
| 1192 if (options.elementRef && !relatedNode.fromFrame) { |
| 1193 res.element = relatedNode.element; |
| 1194 } |
| 1195 if (options.selectors !== false || relatedNode.fromFrame) { |
| 1196 res.target = relatedNode.selector; |
| 1197 } |
| 1198 if (options.xpath) { |
| 1199 res.xpath = relatedNode.xpath; |
| 1200 } |
| 1201 return res; |
| 1202 }); |
| 1203 }); |
| 1204 }); |
| 1205 } |
| 1206 var resultKeys = axe.constants.resultGroups; |
| 1207 helpers.processAggregate = function(results, options) { |
| 1208 var resultObject = axe.utils.aggregateResult(results); |
| 1209 resultObject.timestamp = new Date().toISOString(); |
| 1210 resultObject.url = window.location.href; |
| 1211 resultKeys.forEach(function(key) { |
| 1212 resultObject[key] = (resultObject[key] || []).map(function(ruleResult) { |
| 1213 ruleResult = Object.assign({}, ruleResult); |
| 1214 if (Array.isArray(ruleResult.nodes) && ruleResult.nodes.length > 0) { |
| 1215 ruleResult.nodes = ruleResult.nodes.map(function(subResult) { |
| 1216 if (_typeof(subResult.node) === 'object') { |
| 1217 subResult.html = subResult.node.source; |
| 1218 if (options.elementRef && !subResult.node.fromFrame) { |
| 1219 subResult.element = subResult.node.element; |
| 1220 } |
| 1221 if (options.selectors !== false || subResult.node.fromFrame) { |
| 1222 subResult.target = subResult.node.selector; |
| 1223 } |
| 1224 if (options.xpath) { |
| 1225 subResult.xpath = subResult.node.xpath; |
| 1226 } |
| 1227 } |
| 1228 delete subResult.result; |
| 1229 delete subResult.node; |
| 1230 normalizeRelatedNodes(subResult, options); |
| 1231 return subResult; |
| 1232 }); |
| 1233 } |
| 1234 resultKeys.forEach(function(key) { |
| 1235 return delete ruleResult[key]; |
| 1236 }); |
| 1237 delete ruleResult.pageLevel; |
| 1238 delete ruleResult.result; |
| 1239 return ruleResult; |
| 1240 }); |
| 1241 }); |
| 1242 return resultObject; |
| 1243 }; |
| 1244 'use strict'; |
| 1245 axe.addReporter('na', function(results, options, callback) { |
| 1246 'use strict'; |
| 1247 if (typeof options === 'function') { |
| 1248 callback = options; |
| 1249 options = {}; |
| 1250 } |
| 1251 var out = helpers.processAggregate(results, options); |
| 1252 callback({ |
| 1253 violations: out.violations, |
| 1254 passes: out.passes, |
| 1255 incomplete: out.incomplete, |
| 1256 inapplicable: out.inapplicable, |
| 1257 timestamp: out.timestamp, |
| 1258 url: out.url |
| 1259 }); |
| 1260 }); |
| 1261 'use strict'; |
| 1262 axe.addReporter('no-passes', function(results, options, callback) { |
| 1263 'use strict'; |
| 1264 if (typeof options === 'function') { |
| 1265 callback = options; |
| 1266 options = {}; |
| 1267 } |
| 1268 var out = helpers.processAggregate(results, options); |
| 1269 callback({ |
| 1270 violations: out.violations, |
| 1271 timestamp: out.timestamp, |
| 1272 url: out.url |
| 1273 }); |
| 1274 }); |
| 1275 'use strict'; |
| 1276 axe.addReporter('raw', function(results, options, callback) { |
| 1277 'use strict'; |
| 1278 if (typeof options === 'function') { |
| 1279 callback = options; |
| 1280 options = {}; |
| 1281 } |
| 1282 callback(results); |
| 1283 }); |
| 1284 'use strict'; |
| 1285 axe.addReporter('v1', function(results, options, callback) { |
| 1286 'use strict'; |
| 1287 if (typeof options === 'function') { |
| 1288 callback = options; |
| 1289 options = {}; |
| 1290 } |
| 1291 var out = helpers.processAggregate(results, options); |
| 1292 out.violations.forEach(function(result) { |
| 1293 return result.nodes.forEach(function(nodeResult) { |
| 1294 nodeResult.failureSummary = helpers.failureSummary(nodeResult); |
| 1295 }); |
| 1296 }); |
| 1297 callback({ |
| 1298 violations: out.violations, |
| 1299 passes: out.passes, |
| 1300 incomplete: out.incomplete, |
| 1301 inapplicable: out.inapplicable, |
| 1302 timestamp: out.timestamp, |
| 1303 url: out.url |
| 1304 }); |
| 1305 }); |
| 1306 'use strict'; |
| 1307 axe.addReporter('v2', function(results, options, callback) { |
| 1308 'use strict'; |
| 1309 if (typeof options === 'function') { |
| 1310 callback = options; |
| 1311 options = {}; |
| 1312 } |
| 1313 var out = helpers.processAggregate(results, options); |
| 1314 callback({ |
| 1315 violations: out.violations, |
| 1316 passes: out.passes, |
| 1317 incomplete: out.incomplete, |
| 1318 inapplicable: out.inapplicable, |
| 1319 timestamp: out.timestamp, |
| 1320 url: out.url |
| 1321 }); |
| 1322 }, true); |
| 1323 'use strict'; |
| 1324 axe.utils.aggregate = function(map, values, initial) { |
| 1325 values = values.slice(); |
| 1326 if (initial) { |
| 1327 values.push(initial); |
| 1328 } |
| 1329 var sorting = values.map(function(val) { |
| 1330 return map.indexOf(val); |
| 1331 }).sort(); |
| 1332 return map[sorting.pop()]; |
| 1333 }; |
| 1334 'use strict'; |
| 1335 var checkMap = []; |
| 1336 checkMap[axe.constants.PASS_PRIO] = true; |
| 1337 checkMap[axe.constants.CANTTELL_PRIO] = null; |
| 1338 checkMap[axe.constants.FAIL_PRIO] = false; |
| 1339 var checkTypes = [ 'any', 'all', 'none' ]; |
| 1340 function anyAllNone(obj, functor) { |
| 1341 return checkTypes.reduce(function(out, type) { |
| 1342 out[type] = (obj[type] || []).map(function(val) { |
| 1343 return functor(val, type); |
| 1344 }); |
| 1345 return out; |
| 1346 }, {}); |
| 1347 } |
| 1348 axe.utils.aggregateChecks = function(nodeResOriginal) { |
| 1349 var nodeResult = Object.assign({}, nodeResOriginal); |
| 1350 anyAllNone(nodeResult, function(check, type) { |
| 1351 var i = checkMap.indexOf(check.result); |
| 1352 check.priority = i !== -1 ? i : axe.constants.CANTTELL_PRIO; |
| 1353 if (type === 'none') { |
| 1354 check.priority = 4 - check.priority; |
| 1355 } |
| 1356 }); |
| 1357 var priorities = anyAllNone(nodeResult, function(c) { |
| 1358 return c.priority; |
| 1359 }); |
| 1360 nodeResult.priority = Math.max(priorities.all.reduce(function(a, b) { |
| 1361 return Math.max(a, b); |
| 1362 }, 0), priorities.none.reduce(function(a, b) { |
| 1363 return Math.max(a, b); |
| 1364 }, 0), priorities.any.reduce(function(a, b) { |
| 1365 return Math.min(a, b); |
| 1366 }, 4) % 4); |
| 1367 var impacts = []; |
| 1368 checkTypes.forEach(function(type) { |
| 1369 nodeResult[type] = nodeResult[type].filter(function(check) { |
| 1370 return check.priority === nodeResult.priority; |
| 1371 }); |
| 1372 nodeResult[type].forEach(function(check) { |
| 1373 return impacts.push(check.impact); |
| 1374 }); |
| 1375 }); |
| 1376 if (nodeResult.priority === axe.constants.FAIL_PRIO) { |
| 1377 nodeResult.impact = axe.utils.aggregate(axe.constants.impact, impacts); |
| 1378 } else { |
| 1379 nodeResult.impact = null; |
| 1380 } |
| 1381 anyAllNone(nodeResult, function(c) { |
| 1382 delete c.result; |
| 1383 delete c.priority; |
| 1384 }); |
| 1385 nodeResult.result = axe.constants.results[nodeResult.priority]; |
| 1386 delete nodeResult.priority; |
| 1387 return nodeResult; |
| 1388 }; |
| 1389 'use strict'; |
| 1390 function copyToGroup(resultObject, subResult, group) { |
| 1391 var resultCopy = Object.assign({}, subResult); |
| 1392 resultCopy.nodes = (resultCopy[group] || []).concat(); |
| 1393 axe.constants.resultGroups.forEach(function(group) { |
| 1394 delete resultCopy[group]; |
| 1395 }); |
| 1396 resultObject[group].push(resultCopy); |
| 1397 } |
| 1398 axe.utils.aggregateResult = function(results) { |
| 1399 var resultObject = {}; |
| 1400 axe.constants.resultGroups.forEach(function(groupName) { |
| 1401 return resultObject[groupName] = []; |
| 1402 }); |
| 1403 results.forEach(function(subResult) { |
| 1404 if (subResult.error) { |
| 1405 copyToGroup(resultObject, subResult, axe.constants.CANTTELL_GROUP); |
| 1406 } else if (subResult.result === axe.constants.NA) { |
| 1407 copyToGroup(resultObject, subResult, axe.constants.NA_GROUP); |
| 1408 } else { |
| 1409 axe.constants.resultGroups.forEach(function(group) { |
| 1410 if (Array.isArray(subResult[group]) && subResult[group].length > 0) { |
| 1411 copyToGroup(resultObject, subResult, group); |
| 1412 } |
| 1413 }); |
| 1414 } |
| 1415 }); |
| 1416 return resultObject; |
| 1417 }; |
| 1418 'use strict'; |
| 1419 (function() { |
| 1420 axe.utils.aggregateRule = function(subResults) { |
| 1421 var ruleResult = {}; |
| 1422 subResults = subResults.map(function(subResult) { |
| 1423 if (subResult.any && subResult.all && subResult.none) { |
| 1424 return axe.utils.aggregateChecks(subResult); |
| 1425 } else if (Array.isArray(subResult.node)) { |
| 1426 return axe.utils.finalizeRuleResult(subResult); |
| 1427 } else { |
| 1428 throw new TypeError('Invalid Result type'); |
| 1429 } |
| 1430 }); |
| 1431 var resultList = subResults.map(function(node) { |
| 1432 return node.result; |
| 1433 }); |
| 1434 ruleResult.result = axe.utils.aggregate(axe.constants.results, resultList,
ruleResult.result); |
| 1435 axe.constants.resultGroups.forEach(function(group) { |
| 1436 return ruleResult[group] = []; |
| 1437 }); |
| 1438 subResults.forEach(function(subResult) { |
| 1439 var groupName = axe.constants.resultGroupMap[subResult.result]; |
| 1440 ruleResult[groupName].push(subResult); |
| 1441 }); |
| 1442 var failGroup = axe.constants.FAIL_GROUP; |
| 1443 if (ruleResult[failGroup].length > 0) { |
| 1444 var impactList = ruleResult[failGroup].map(function(failure) { |
| 1445 return failure.impact; |
| 1446 }); |
| 1447 ruleResult.impact = axe.utils.aggregate(axe.constants.impact, impactList
) || null; |
| 1448 } else { |
| 1449 ruleResult.impact = null; |
| 1450 } |
| 1451 return ruleResult; |
| 1452 }; |
| 1453 })(); |
| 1454 'use strict'; |
| 1455 function areStylesSet(el, styles, stopAt) { |
| 1456 'use strict'; |
| 1457 var styl = window.getComputedStyle(el, null); |
| 1458 var set = false; |
| 1459 if (!styl) { |
| 1460 return false; |
| 1461 } |
| 1462 styles.forEach(function(att) { |
| 1463 if (styl.getPropertyValue(att.property) === att.value) { |
| 1464 set = true; |
| 1465 } |
| 1466 }); |
| 1467 if (set) { |
| 1468 return true; |
| 1469 } |
| 1470 if (el.nodeName.toUpperCase() === stopAt.toUpperCase() || !el.parentNode) { |
| 1471 return false; |
| 1472 } |
| 1473 return areStylesSet(el.parentNode, styles, stopAt); |
| 1474 } |
| 1475 axe.utils.areStylesSet = areStylesSet; |
| 1476 'use strict'; |
| 1477 axe.utils.checkHelper = function checkHelper(checkResult, options, resolve, re
ject) { |
| 1478 'use strict'; |
| 1479 return { |
| 1480 isAsync: false, |
| 1481 async: function async() { |
| 1482 this.isAsync = true; |
| 1483 return function(result) { |
| 1484 if (result instanceof Error === false) { |
| 1485 checkResult.value = result; |
| 1486 resolve(checkResult); |
| 1487 } else { |
| 1488 reject(result); |
| 1489 } |
| 1490 }; |
| 1491 }, |
| 1492 data: function data(_data) { |
| 1493 checkResult.data = _data; |
| 1494 }, |
| 1495 relatedNodes: function relatedNodes(nodes) { |
| 1496 nodes = nodes instanceof Node ? [ nodes ] : axe.utils.toArray(nodes); |
| 1497 checkResult.relatedNodes = nodes.map(function(element) { |
| 1498 return new axe.utils.DqElement(element, options); |
| 1499 }); |
| 1500 } |
| 1501 }; |
| 1502 }; |
| 1503 'use strict'; |
| 1504 var _typeof = typeof Symbol === 'function' && typeof Symbol.iterator === 'symb
ol' ? function(obj) { |
| 1505 return typeof obj; |
| 1506 } : function(obj) { |
| 1507 return obj && typeof Symbol === 'function' && obj.constructor === Symbol &&
obj !== Symbol.prototype ? 'symbol' : typeof obj; |
| 1508 }; |
| 1509 axe.utils.clone = function(obj) { |
| 1510 'use strict'; |
| 1511 var index, length, out = obj; |
| 1512 if (obj !== null && (typeof obj === 'undefined' ? 'undefined' : _typeof(obj)
) === 'object') { |
| 1513 if (Array.isArray(obj)) { |
| 1514 out = []; |
| 1515 for (index = 0, length = obj.length; index < length; index++) { |
| 1516 out[index] = axe.utils.clone(obj[index]); |
| 1517 } |
| 1518 } else { |
| 1519 out = {}; |
| 1520 for (index in obj) { |
| 1521 out[index] = axe.utils.clone(obj[index]); |
| 1522 } |
| 1523 } |
| 1524 } |
| 1525 return out; |
| 1526 }; |
| 1527 'use strict'; |
| 1528 function err(message, node) { |
| 1529 'use strict'; |
| 1530 return new Error(message + ': ' + axe.utils.getSelector(node)); |
| 1531 } |
| 1532 axe.utils.sendCommandToFrame = function(node, parameters, resolve, reject) { |
| 1533 'use strict'; |
| 1534 var win = node.contentWindow; |
| 1535 if (!win) { |
| 1536 axe.log('Frame does not have a content window', node); |
| 1537 resolve(null); |
| 1538 return; |
| 1539 } |
| 1540 var timeout = setTimeout(function() { |
| 1541 timeout = setTimeout(function() { |
| 1542 var errMsg = err('No response from frame', node); |
| 1543 if (!parameters.debug) { |
| 1544 axe.log(errMsg); |
| 1545 resolve(null); |
| 1546 } else { |
| 1547 reject(errMsg); |
| 1548 } |
| 1549 }, 0); |
| 1550 }, 500); |
| 1551 axe.utils.respondable(win, 'axe.ping', null, undefined, function() { |
| 1552 clearTimeout(timeout); |
| 1553 timeout = setTimeout(function() { |
| 1554 reject(err('Axe in frame timed out', node)); |
| 1555 }, 3e4); |
| 1556 axe.utils.respondable(win, 'axe.start', parameters, undefined, function(da
ta) { |
| 1557 clearTimeout(timeout); |
| 1558 if (data instanceof Error === false) { |
| 1559 resolve(data); |
| 1560 } else { |
| 1561 reject(data); |
| 1562 } |
| 1563 }); |
| 1564 }); |
| 1565 }; |
| 1566 function collectResultsFromFrames(context, options, command, parameter, resolv
e, reject) { |
| 1567 'use strict'; |
| 1568 var q = axe.utils.queue(); |
| 1569 var frames = context.frames; |
| 1570 frames.forEach(function(frame) { |
| 1571 var params = { |
| 1572 options: options, |
| 1573 command: command, |
| 1574 parameter: parameter, |
| 1575 context: { |
| 1576 initiator: false, |
| 1577 page: context.page, |
| 1578 include: frame.include || [], |
| 1579 exclude: frame.exclude || [] |
| 1580 } |
| 1581 }; |
| 1582 q.defer(function(res, rej) { |
| 1583 var node = frame.node; |
| 1584 axe.utils.sendCommandToFrame(node, params, function(data) { |
| 1585 if (data) { |
| 1586 return res({ |
| 1587 results: data, |
| 1588 frameElement: node, |
| 1589 frame: axe.utils.getSelector(node) |
| 1590 }); |
| 1591 } |
| 1592 res(null); |
| 1593 }, rej); |
| 1594 }); |
| 1595 }); |
| 1596 q.then(function(data) { |
| 1597 resolve(axe.utils.mergeResults(data, options)); |
| 1598 }).catch(reject); |
| 1599 } |
| 1600 axe.utils.collectResultsFromFrames = collectResultsFromFrames; |
| 1601 'use strict'; |
| 1602 axe.utils.contains = function(node, otherNode) { |
| 1603 'use strict'; |
| 1604 function containsShadowChild(node, otherNode) { |
| 1605 if (node.shadowId === otherNode.shadowId) { |
| 1606 return true; |
| 1607 } |
| 1608 return !!node.children.find(function(child) { |
| 1609 return containsShadowChild(child, otherNode); |
| 1610 }); |
| 1611 } |
| 1612 if (node.shadowId || otherNode.shadowId) { |
| 1613 return containsShadowChild(node, otherNode); |
| 1614 } |
| 1615 if (typeof node.actualNode.contains === 'function') { |
| 1616 return node.actualNode.contains(otherNode.actualNode); |
| 1617 } |
| 1618 return !!(node.actualNode.compareDocumentPosition(otherNode.actualNode) & 16
); |
| 1619 }; |
| 1620 'use strict'; |
| 1621 (function(axe) { |
| 1622 /*! |
| 1623 * The copyright below covers the code within this function block only |
| 1624 * |
| 1625 * Copyright (c) 2013 Dulin Marat |
| 1626 * |
| 1627 * Permission is hereby granted, free of charge, to any person obtaining a copy |
| 1628 * of this software and associated documentation files (the "Software"), to dea
l |
| 1629 * in the Software without restriction, including without limitation the rights |
| 1630 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 1631 * copies of the Software, and to permit persons to whom the Software is |
| 1632 * furnished to do so, subject to the following conditions: |
| 1633 * |
| 1634 * The above copyright notice and this permission notice shall be included in |
| 1635 * all copies or substantial portions of the Software. |
| 1636 * |
| 1637 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 1638 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 1639 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 1640 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 1641 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM
, |
| 1642 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| 1643 * THE SOFTWARE. |
| 1644 */ |
| 1645 function CssSelectorParser() { |
| 1646 this.pseudos = {}; |
| 1647 this.attrEqualityMods = {}; |
| 1648 this.ruleNestingOperators = {}; |
| 1649 this.substitutesEnabled = false; |
| 1650 } |
| 1651 CssSelectorParser.prototype.registerSelectorPseudos = function(name) { |
| 1652 for (var j = 0, len = arguments.length; j < len; j++) { |
| 1653 name = arguments[j]; |
| 1654 this.pseudos[name] = 'selector'; |
| 1655 } |
| 1656 return this; |
| 1657 }; |
| 1658 CssSelectorParser.prototype.unregisterSelectorPseudos = function(name) { |
| 1659 for (var j = 0, len = arguments.length; j < len; j++) { |
| 1660 name = arguments[j]; |
| 1661 delete this.pseudos[name]; |
| 1662 } |
| 1663 return this; |
| 1664 }; |
| 1665 CssSelectorParser.prototype.registerNumericPseudos = function(name) { |
| 1666 for (var j = 0, len = arguments.length; j < len; j++) { |
| 1667 name = arguments[j]; |
| 1668 this.pseudos[name] = 'numeric'; |
| 1669 } |
| 1670 return this; |
| 1671 }; |
| 1672 CssSelectorParser.prototype.unregisterNumericPseudos = function(name) { |
| 1673 for (var j = 0, len = arguments.length; j < len; j++) { |
| 1674 name = arguments[j]; |
| 1675 delete this.pseudos[name]; |
| 1676 } |
| 1677 return this; |
| 1678 }; |
| 1679 CssSelectorParser.prototype.registerNestingOperators = function(operator) { |
| 1680 for (var j = 0, len = arguments.length; j < len; j++) { |
| 1681 operator = arguments[j]; |
| 1682 this.ruleNestingOperators[operator] = true; |
| 1683 } |
| 1684 return this; |
| 1685 }; |
| 1686 CssSelectorParser.prototype.unregisterNestingOperators = function(operator)
{ |
| 1687 for (var j = 0, len = arguments.length; j < len; j++) { |
| 1688 operator = arguments[j]; |
| 1689 delete this.ruleNestingOperators[operator]; |
| 1690 } |
| 1691 return this; |
| 1692 }; |
| 1693 CssSelectorParser.prototype.registerAttrEqualityMods = function(mod) { |
| 1694 for (var j = 0, len = arguments.length; j < len; j++) { |
| 1695 mod = arguments[j]; |
| 1696 this.attrEqualityMods[mod] = true; |
| 1697 } |
| 1698 return this; |
| 1699 }; |
| 1700 CssSelectorParser.prototype.unregisterAttrEqualityMods = function(mod) { |
| 1701 for (var j = 0, len = arguments.length; j < len; j++) { |
| 1702 mod = arguments[j]; |
| 1703 delete this.attrEqualityMods[mod]; |
| 1704 } |
| 1705 return this; |
| 1706 }; |
| 1707 CssSelectorParser.prototype.enableSubstitutes = function() { |
| 1708 this.substitutesEnabled = true; |
| 1709 return this; |
| 1710 }; |
| 1711 CssSelectorParser.prototype.disableSubstitutes = function() { |
| 1712 this.substitutesEnabled = false; |
| 1713 return this; |
| 1714 }; |
| 1715 function isIdentStart(c) { |
| 1716 return c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c === '-' || c ===
'_'; |
| 1717 } |
| 1718 function isIdent(c) { |
| 1719 return c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9
' || c === '-' || c === '_'; |
| 1720 } |
| 1721 function isHex(c) { |
| 1722 return c >= 'a' && c <= 'f' || c >= 'A' && c <= 'F' || c >= '0' && c <= '9
'; |
| 1723 } |
| 1724 function isDecimal(c) { |
| 1725 return c >= '0' && c <= '9'; |
| 1726 } |
| 1727 function isAttrMatchOperator(chr) { |
| 1728 return chr === '=' || chr === '^' || chr === '$' || chr === '*' || chr ===
'~'; |
| 1729 } |
| 1730 var identSpecialChars = { |
| 1731 '!': true, |
| 1732 '"': true, |
| 1733 '#': true, |
| 1734 $: true, |
| 1735 '%': true, |
| 1736 '&': true, |
| 1737 '\'': true, |
| 1738 '(': true, |
| 1739 ')': true, |
| 1740 '*': true, |
| 1741 '+': true, |
| 1742 ',': true, |
| 1743 '.': true, |
| 1744 '/': true, |
| 1745 ';': true, |
| 1746 '<': true, |
| 1747 '=': true, |
| 1748 '>': true, |
| 1749 '?': true, |
| 1750 '@': true, |
| 1751 '[': true, |
| 1752 '\\': true, |
| 1753 ']': true, |
| 1754 '^': true, |
| 1755 '`': true, |
| 1756 '{': true, |
| 1757 '|': true, |
| 1758 '}': true, |
| 1759 '~': true |
| 1760 }; |
| 1761 var strReplacementsRev = { |
| 1762 '\n': '\\n', |
| 1763 '\r': '\\r', |
| 1764 '\t': '\\t', |
| 1765 '\f': '\\f', |
| 1766 '\v': '\\v' |
| 1767 }; |
| 1768 var singleQuoteEscapeChars = { |
| 1769 n: '\n', |
| 1770 r: '\r', |
| 1771 t: '\t', |
| 1772 f: '\f', |
| 1773 '\\': '\\', |
| 1774 '\'': '\'' |
| 1775 }; |
| 1776 var doubleQuotesEscapeChars = { |
| 1777 n: '\n', |
| 1778 r: '\r', |
| 1779 t: '\t', |
| 1780 f: '\f', |
| 1781 '\\': '\\', |
| 1782 '"': '"' |
| 1783 }; |
| 1784 function ParseContext(str, pos, pseudos, attrEqualityMods, ruleNestingOperat
ors, substitutesEnabled) { |
| 1785 var chr, getIdent, getStr, l, skipWhitespace; |
| 1786 l = str.length; |
| 1787 chr = null; |
| 1788 getStr = function getStr(quote, escapeTable) { |
| 1789 var esc, hex, result; |
| 1790 result = ''; |
| 1791 pos++; |
| 1792 chr = str.charAt(pos); |
| 1793 while (pos < l) { |
| 1794 if (chr === quote) { |
| 1795 pos++; |
| 1796 return result; |
| 1797 } else if (chr === '\\') { |
| 1798 pos++; |
| 1799 chr = str.charAt(pos); |
| 1800 if (chr === quote) { |
| 1801 result += quote; |
| 1802 } else if (esc = escapeTable[chr]) { |
| 1803 result += esc; |
| 1804 } else if (isHex(chr)) { |
| 1805 hex = chr; |
| 1806 pos++; |
| 1807 chr = str.charAt(pos); |
| 1808 while (isHex(chr)) { |
| 1809 hex += chr; |
| 1810 pos++; |
| 1811 chr = str.charAt(pos); |
| 1812 } |
| 1813 if (chr === ' ') { |
| 1814 pos++; |
| 1815 chr = str.charAt(pos); |
| 1816 } |
| 1817 result += String.fromCharCode(parseInt(hex, 16)); |
| 1818 continue; |
| 1819 } else { |
| 1820 result += chr; |
| 1821 } |
| 1822 } else { |
| 1823 result += chr; |
| 1824 } |
| 1825 pos++; |
| 1826 chr = str.charAt(pos); |
| 1827 } |
| 1828 return result; |
| 1829 }; |
| 1830 getIdent = function getIdent() { |
| 1831 var result = ''; |
| 1832 chr = str.charAt(pos); |
| 1833 while (pos < l) { |
| 1834 if (isIdent(chr)) { |
| 1835 result += chr; |
| 1836 } else if (chr === '\\') { |
| 1837 pos++; |
| 1838 if (pos >= l) { |
| 1839 throw Error('Expected symbol but end of file reached.'); |
| 1840 } |
| 1841 chr = str.charAt(pos); |
| 1842 if (identSpecialChars[chr]) { |
| 1843 result += chr; |
| 1844 } else if (isHex(chr)) { |
| 1845 var hex = chr; |
| 1846 pos++; |
| 1847 chr = str.charAt(pos); |
| 1848 while (isHex(chr)) { |
| 1849 hex += chr; |
| 1850 pos++; |
| 1851 chr = str.charAt(pos); |
| 1852 } |
| 1853 if (chr === ' ') { |
| 1854 pos++; |
| 1855 chr = str.charAt(pos); |
| 1856 } |
| 1857 result += String.fromCharCode(parseInt(hex, 16)); |
| 1858 continue; |
| 1859 } else { |
| 1860 result += chr; |
| 1861 } |
| 1862 } else { |
| 1863 return result; |
| 1864 } |
| 1865 pos++; |
| 1866 chr = str.charAt(pos); |
| 1867 } |
| 1868 return result; |
| 1869 }; |
| 1870 skipWhitespace = function skipWhitespace() { |
| 1871 chr = str.charAt(pos); |
| 1872 var result = false; |
| 1873 while (chr === ' ' || chr === '\t' || chr === '\n' || chr === '\r' || ch
r === '\f') { |
| 1874 result = true; |
| 1875 pos++; |
| 1876 chr = str.charAt(pos); |
| 1877 } |
| 1878 return result; |
| 1879 }; |
| 1880 this.parse = function() { |
| 1881 var res = this.parseSelector(); |
| 1882 if (pos < l) { |
| 1883 throw Error('Rule expected but "' + str.charAt(pos) + '" found.'); |
| 1884 } |
| 1885 return res; |
| 1886 }; |
| 1887 this.parseSelector = function() { |
| 1888 var res; |
| 1889 var selector = res = this.parseSingleSelector(); |
| 1890 chr = str.charAt(pos); |
| 1891 while (chr === ',') { |
| 1892 pos++; |
| 1893 skipWhitespace(); |
| 1894 if (res.type !== 'selectors') { |
| 1895 res = { |
| 1896 type: 'selectors', |
| 1897 selectors: [ selector ] |
| 1898 }; |
| 1899 } |
| 1900 selector = this.parseSingleSelector(); |
| 1901 if (!selector) { |
| 1902 throw Error('Rule expected after ",".'); |
| 1903 } |
| 1904 res.selectors.push(selector); |
| 1905 } |
| 1906 return res; |
| 1907 }; |
| 1908 this.parseSingleSelector = function() { |
| 1909 skipWhitespace(); |
| 1910 var selector = { |
| 1911 type: 'ruleSet' |
| 1912 }; |
| 1913 var rule = this.parseRule(); |
| 1914 if (!rule) { |
| 1915 return null; |
| 1916 } |
| 1917 var currentRule = selector; |
| 1918 while (rule) { |
| 1919 rule.type = 'rule'; |
| 1920 currentRule.rule = rule; |
| 1921 currentRule = rule; |
| 1922 skipWhitespace(); |
| 1923 chr = str.charAt(pos); |
| 1924 if (pos >= l || chr === ',' || chr === ')') { |
| 1925 break; |
| 1926 } |
| 1927 if (ruleNestingOperators[chr]) { |
| 1928 var op = chr; |
| 1929 pos++; |
| 1930 skipWhitespace(); |
| 1931 rule = this.parseRule(); |
| 1932 if (!rule) { |
| 1933 throw Error('Rule expected after "' + op + '".'); |
| 1934 } |
| 1935 rule.nestingOperator = op; |
| 1936 } else { |
| 1937 rule = this.parseRule(); |
| 1938 if (rule) { |
| 1939 rule.nestingOperator = null; |
| 1940 } |
| 1941 } |
| 1942 } |
| 1943 return selector; |
| 1944 }; |
| 1945 this.parseRule = function() { |
| 1946 var rule = null; |
| 1947 while (pos < l) { |
| 1948 chr = str.charAt(pos); |
| 1949 if (chr === '*') { |
| 1950 pos++; |
| 1951 (rule = rule || {}).tagName = '*'; |
| 1952 } else if (isIdentStart(chr) || chr === '\\') { |
| 1953 (rule = rule || {}).tagName = getIdent(); |
| 1954 } else if (chr === '.') { |
| 1955 pos++; |
| 1956 rule = rule || {}; |
| 1957 (rule.classNames = rule.classNames || []).push(getIdent()); |
| 1958 } else if (chr === '#') { |
| 1959 pos++; |
| 1960 (rule = rule || {}).id = getIdent(); |
| 1961 } else if (chr === '[') { |
| 1962 pos++; |
| 1963 skipWhitespace(); |
| 1964 var attr = { |
| 1965 name: getIdent() |
| 1966 }; |
| 1967 skipWhitespace(); |
| 1968 if (chr === ']') { |
| 1969 pos++; |
| 1970 } else { |
| 1971 var operator = ''; |
| 1972 if (attrEqualityMods[chr]) { |
| 1973 operator = chr; |
| 1974 pos++; |
| 1975 chr = str.charAt(pos); |
| 1976 } |
| 1977 if (pos >= l) { |
| 1978 throw Error('Expected "=" but end of file reached.'); |
| 1979 } |
| 1980 if (chr !== '=') { |
| 1981 throw Error('Expected "=" but "' + chr + '" found.'); |
| 1982 } |
| 1983 attr.operator = operator + '='; |
| 1984 pos++; |
| 1985 skipWhitespace(); |
| 1986 var attrValue = ''; |
| 1987 attr.valueType = 'string'; |
| 1988 if (chr === '"') { |
| 1989 attrValue = getStr('"', doubleQuotesEscapeChars); |
| 1990 } else if (chr === '\'') { |
| 1991 attrValue = getStr('\'', singleQuoteEscapeChars); |
| 1992 } else if (substitutesEnabled && chr === '$') { |
| 1993 pos++; |
| 1994 attrValue = getIdent(); |
| 1995 attr.valueType = 'substitute'; |
| 1996 } else { |
| 1997 while (pos < l) { |
| 1998 if (chr === ']') { |
| 1999 break; |
| 2000 } |
| 2001 attrValue += chr; |
| 2002 pos++; |
| 2003 chr = str.charAt(pos); |
| 2004 } |
| 2005 attrValue = attrValue.trim(); |
| 2006 } |
| 2007 skipWhitespace(); |
| 2008 if (pos >= l) { |
| 2009 throw Error('Expected "]" but end of file reached.'); |
| 2010 } |
| 2011 if (chr !== ']') { |
| 2012 throw Error('Expected "]" but "' + chr + '" found.'); |
| 2013 } |
| 2014 pos++; |
| 2015 attr.value = attrValue; |
| 2016 } |
| 2017 rule = rule || {}; |
| 2018 (rule.attrs = rule.attrs || []).push(attr); |
| 2019 } else if (chr === ':') { |
| 2020 pos++; |
| 2021 var pseudoName = getIdent(); |
| 2022 var pseudo = { |
| 2023 name: pseudoName |
| 2024 }; |
| 2025 if (chr === '(') { |
| 2026 pos++; |
| 2027 var value = ''; |
| 2028 skipWhitespace(); |
| 2029 if (pseudos[pseudoName] === 'selector') { |
| 2030 pseudo.valueType = 'selector'; |
| 2031 value = this.parseSelector(); |
| 2032 } else { |
| 2033 pseudo.valueType = pseudos[pseudoName] || 'string'; |
| 2034 if (chr === '"') { |
| 2035 value = getStr('"', doubleQuotesEscapeChars); |
| 2036 } else if (chr === '\'') { |
| 2037 value = getStr('\'', singleQuoteEscapeChars); |
| 2038 } else if (substitutesEnabled && chr === '$') { |
| 2039 pos++; |
| 2040 value = getIdent(); |
| 2041 pseudo.valueType = 'substitute'; |
| 2042 } else { |
| 2043 while (pos < l) { |
| 2044 if (chr === ')') { |
| 2045 break; |
| 2046 } |
| 2047 value += chr; |
| 2048 pos++; |
| 2049 chr = str.charAt(pos); |
| 2050 } |
| 2051 value = value.trim(); |
| 2052 } |
| 2053 skipWhitespace(); |
| 2054 } |
| 2055 if (pos >= l) { |
| 2056 throw Error('Expected ")" but end of file reached.'); |
| 2057 } |
| 2058 if (chr !== ')') { |
| 2059 throw Error('Expected ")" but "' + chr + '" found.'); |
| 2060 } |
| 2061 pos++; |
| 2062 pseudo.value = value; |
| 2063 } |
| 2064 rule = rule || {}; |
| 2065 (rule.pseudos = rule.pseudos || []).push(pseudo); |
| 2066 } else { |
| 2067 break; |
| 2068 } |
| 2069 } |
| 2070 return rule; |
| 2071 }; |
| 2072 return this; |
| 2073 } |
| 2074 CssSelectorParser.prototype.parse = function(str) { |
| 2075 var context = new ParseContext(str, 0, this.pseudos, this.attrEqualityMods
, this.ruleNestingOperators, this.substitutesEnabled); |
| 2076 return context.parse(); |
| 2077 }; |
| 2078 CssSelectorParser.prototype.escapeIdentifier = function(s) { |
| 2079 var result = ''; |
| 2080 var i = 0; |
| 2081 var len = s.length; |
| 2082 while (i < len) { |
| 2083 var chr = s.charAt(i); |
| 2084 if (identSpecialChars[chr]) { |
| 2085 result += '\\' + chr; |
| 2086 } else { |
| 2087 if (!(chr === '_' || chr === '-' || chr >= 'A' && chr <= 'Z' || chr >=
'a' && chr <= 'z' || i !== 0 && chr >= '0' && chr <= '9')) { |
| 2088 var charCode = chr.charCodeAt(0); |
| 2089 if ((charCode & 63488) === 55296) { |
| 2090 var extraCharCode = s.charCodeAt(i++); |
| 2091 if ((charCode & 64512) !== 55296 || (extraCharCode & 64512) !== 56
320) { |
| 2092 throw Error('UCS-2(decode): illegal sequence'); |
| 2093 } |
| 2094 charCode = ((charCode & 1023) << 10) + (extraCharCode & 1023) + 65
536; |
| 2095 } |
| 2096 result += '\\' + charCode.toString(16) + ' '; |
| 2097 } else { |
| 2098 result += chr; |
| 2099 } |
| 2100 } |
| 2101 i++; |
| 2102 } |
| 2103 return result; |
| 2104 }; |
| 2105 CssSelectorParser.prototype.escapeStr = function(s) { |
| 2106 var result = ''; |
| 2107 var i = 0; |
| 2108 var len = s.length; |
| 2109 var chr, replacement; |
| 2110 while (i < len) { |
| 2111 chr = s.charAt(i); |
| 2112 if (chr === '"') { |
| 2113 chr = '\\"'; |
| 2114 } else if (chr === '\\') { |
| 2115 chr = '\\\\'; |
| 2116 } else if (replacement = strReplacementsRev[chr]) { |
| 2117 chr = replacement; |
| 2118 } |
| 2119 result += chr; |
| 2120 i++; |
| 2121 } |
| 2122 return '"' + result + '"'; |
| 2123 }; |
| 2124 CssSelectorParser.prototype.render = function(path) { |
| 2125 return this._renderEntity(path).trim(); |
| 2126 }; |
| 2127 CssSelectorParser.prototype._renderEntity = function(entity) { |
| 2128 var currentEntity, parts, res; |
| 2129 res = ''; |
| 2130 switch (entity.type) { |
| 2131 case 'ruleSet': |
| 2132 currentEntity = entity.rule; |
| 2133 parts = []; |
| 2134 while (currentEntity) { |
| 2135 if (currentEntity.nestingOperator) { |
| 2136 parts.push(currentEntity.nestingOperator); |
| 2137 } |
| 2138 parts.push(this._renderEntity(currentEntity)); |
| 2139 currentEntity = currentEntity.rule; |
| 2140 } |
| 2141 res = parts.join(' '); |
| 2142 break; |
| 2143 |
| 2144 case 'selectors': |
| 2145 res = entity.selectors.map(this._renderEntity, this).join(', '); |
| 2146 break; |
| 2147 |
| 2148 case 'rule': |
| 2149 if (entity.tagName) { |
| 2150 if (entity.tagName === '*') { |
| 2151 res = '*'; |
| 2152 } else { |
| 2153 res = this.escapeIdentifier(entity.tagName); |
| 2154 } |
| 2155 } |
| 2156 if (entity.id) { |
| 2157 res += '#' + this.escapeIdentifier(entity.id); |
| 2158 } |
| 2159 if (entity.classNames) { |
| 2160 res += entity.classNames.map(function(cn) { |
| 2161 return '.' + this.escapeIdentifier(cn); |
| 2162 }, this).join(''); |
| 2163 } |
| 2164 if (entity.attrs) { |
| 2165 res += entity.attrs.map(function(attr) { |
| 2166 if (attr.operator) { |
| 2167 if (attr.valueType === 'substitute') { |
| 2168 return '[' + this.escapeIdentifier(attr.name) + attr.operator +
'$' + attr.value + ']'; |
| 2169 } else { |
| 2170 return '[' + this.escapeIdentifier(attr.name) + attr.operator +
this.escapeStr(attr.value) + ']'; |
| 2171 } |
| 2172 } else { |
| 2173 return '[' + this.escapeIdentifier(attr.name) + ']'; |
| 2174 } |
| 2175 }, this).join(''); |
| 2176 } |
| 2177 if (entity.pseudos) { |
| 2178 res += entity.pseudos.map(function(pseudo) { |
| 2179 if (pseudo.valueType) { |
| 2180 if (pseudo.valueType === 'selector') { |
| 2181 return ':' + this.escapeIdentifier(pseudo.name) + '(' + this._re
nderEntity(pseudo.value) + ')'; |
| 2182 } else if (pseudo.valueType === 'substitute') { |
| 2183 return ':' + this.escapeIdentifier(pseudo.name) + '($' + pseudo.
value + ')'; |
| 2184 } else if (pseudo.valueType === 'numeric') { |
| 2185 return ':' + this.escapeIdentifier(pseudo.name) + '(' + pseudo.v
alue + ')'; |
| 2186 } else { |
| 2187 return ':' + this.escapeIdentifier(pseudo.name) + '(' + this.esc
apeIdentifier(pseudo.value) + ')'; |
| 2188 } |
| 2189 } else { |
| 2190 return ':' + this.escapeIdentifier(pseudo.name); |
| 2191 } |
| 2192 }, this).join(''); |
| 2193 } |
| 2194 break; |
| 2195 |
| 2196 default: |
| 2197 throw Error('Unknown entity type: "' + entity.type(+'".')); |
| 2198 } |
| 2199 return res; |
| 2200 }; |
| 2201 var parser = new CssSelectorParser(); |
| 2202 parser.registerNestingOperators('>'); |
| 2203 axe.utils.cssParser = parser; |
| 2204 })(axe); |
| 2205 'use strict'; |
| 2206 function truncate(str, maxLength) { |
| 2207 maxLength = maxLength || 300; |
| 2208 if (str.length > maxLength) { |
| 2209 var index = str.indexOf('>'); |
| 2210 str = str.substring(0, index + 1); |
| 2211 } |
| 2212 return str; |
| 2213 } |
| 2214 function getSource(element) { |
| 2215 var source = element.outerHTML; |
| 2216 if (!source && typeof XMLSerializer === 'function') { |
| 2217 source = new XMLSerializer().serializeToString(element); |
| 2218 } |
| 2219 return truncate(source || ''); |
| 2220 } |
| 2221 function DqElement(element, options, spec) { |
| 2222 this._fromFrame = !!spec; |
| 2223 this.spec = spec || {}; |
| 2224 if (options && options.absolutePaths) { |
| 2225 this._options = { |
| 2226 toRoot: true |
| 2227 }; |
| 2228 } |
| 2229 this.source = this.spec.source !== undefined ? this.spec.source : getSource(
element); |
| 2230 this._element = element; |
| 2231 } |
| 2232 DqElement.prototype = { |
| 2233 get selector() { |
| 2234 return this.spec.selector || [ axe.utils.getSelector(this.element, this._o
ptions) ]; |
| 2235 }, |
| 2236 get xpath() { |
| 2237 return this.spec.xpath || [ axe.utils.getXpath(this.element) ]; |
| 2238 }, |
| 2239 get element() { |
| 2240 return this._element; |
| 2241 }, |
| 2242 get fromFrame() { |
| 2243 return this._fromFrame; |
| 2244 }, |
| 2245 toJSON: function toJSON() { |
| 2246 'use strict'; |
| 2247 return { |
| 2248 selector: this.selector, |
| 2249 source: this.source, |
| 2250 xpath: this.xpath |
| 2251 }; |
| 2252 } |
| 2253 }; |
| 2254 DqElement.fromFrame = function(node, options, frame) { |
| 2255 node.selector.unshift(frame.selector); |
| 2256 node.xpath.unshift(frame.xpath); |
| 2257 return new axe.utils.DqElement(frame.element, options, node); |
| 2258 }; |
| 2259 axe.utils.DqElement = DqElement; |
| 2260 'use strict'; |
| 2261 axe.utils.matchesSelector = function() { |
| 2262 'use strict'; |
| 2263 var method; |
| 2264 function getMethod(win) { |
| 2265 var index, candidate, elProto = win.Element.prototype, candidates = [ 'mat
ches', 'matchesSelector', 'mozMatchesSelector', 'webkitMatchesSelector', 'msMatc
hesSelector' ], length = candidates.length; |
| 2266 for (index = 0; index < length; index++) { |
| 2267 candidate = candidates[index]; |
| 2268 if (elProto[candidate]) { |
| 2269 return candidate; |
| 2270 } |
| 2271 } |
| 2272 } |
| 2273 return function(node, selector) { |
| 2274 if (!method || !node[method]) { |
| 2275 method = getMethod(node.ownerDocument.defaultView); |
| 2276 } |
| 2277 return node[method](selector); |
| 2278 }; |
| 2279 }(); |
| 2280 'use strict'; |
| 2281 axe.utils.escapeSelector = function(value) { |
| 2282 'use strict'; |
| 2283 var string = String(value); |
| 2284 var length = string.length; |
| 2285 var index = -1; |
| 2286 var codeUnit; |
| 2287 var result = ''; |
| 2288 var firstCodeUnit = string.charCodeAt(0); |
| 2289 while (++index < length) { |
| 2290 codeUnit = string.charCodeAt(index); |
| 2291 if (codeUnit == 0) { |
| 2292 throw new Error('INVALID_CHARACTER_ERR'); |
| 2293 } |
| 2294 if (codeUnit >= 1 && codeUnit <= 31 || codeUnit >= 127 && codeUnit <= 159
|| index == 0 && codeUnit >= 48 && codeUnit <= 57 || index == 1 && codeUnit >= 4
8 && codeUnit <= 57 && firstCodeUnit == 45) { |
| 2295 result += '\\' + codeUnit.toString(16) + ' '; |
| 2296 continue; |
| 2297 } |
| 2298 if (index == 1 && codeUnit == 45 && firstCodeUnit == 45) { |
| 2299 result += '\\' + string.charAt(index); |
| 2300 continue; |
| 2301 } |
| 2302 if (codeUnit >= 128 || codeUnit == 45 || codeUnit == 95 || codeUnit >= 48
&& codeUnit <= 57 || codeUnit >= 65 && codeUnit <= 90 || codeUnit >= 97 && codeU
nit <= 122) { |
| 2303 result += string.charAt(index); |
| 2304 continue; |
| 2305 } |
| 2306 result += '\\' + string.charAt(index); |
| 2307 } |
| 2308 return result; |
| 2309 }; |
| 2310 'use strict'; |
| 2311 axe.utils.extendMetaData = function(to, from) { |
| 2312 Object.assign(to, from); |
| 2313 Object.keys(from).filter(function(prop) { |
| 2314 return typeof from[prop] === 'function'; |
| 2315 }).forEach(function(prop) { |
| 2316 to[prop] = null; |
| 2317 try { |
| 2318 to[prop] = from[prop](to); |
| 2319 } catch (e) {} |
| 2320 }); |
| 2321 }; |
| 2322 'use strict'; |
| 2323 axe.utils.finalizeRuleResult = function(ruleResult) { |
| 2324 Object.assign(ruleResult, axe.utils.aggregateRule(ruleResult.nodes)); |
| 2325 delete ruleResult.nodes; |
| 2326 return ruleResult; |
| 2327 }; |
| 2328 'use strict'; |
| 2329 var _typeof = typeof Symbol === 'function' && typeof Symbol.iterator === 'symb
ol' ? function(obj) { |
| 2330 return typeof obj; |
| 2331 } : function(obj) { |
| 2332 return obj && typeof Symbol === 'function' && obj.constructor === Symbol &&
obj !== Symbol.prototype ? 'symbol' : typeof obj; |
| 2333 }; |
| 2334 axe.utils.findBy = function(array, key, value) { |
| 2335 if (Array.isArray(array)) { |
| 2336 return array.find(function(obj) { |
| 2337 return (typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) === 'ob
ject' && obj[key] === value; |
| 2338 }); |
| 2339 } |
| 2340 }; |
| 2341 'use strict'; |
| 2342 var axe = axe || { |
| 2343 utils: {} |
| 2344 }; |
| 2345 function virtualDOMfromNode(node, shadowId) { |
| 2346 return { |
| 2347 shadowId: shadowId, |
| 2348 children: [], |
| 2349 actualNode: node |
| 2350 }; |
| 2351 } |
| 2352 function getSlotChildren(node) { |
| 2353 var retVal = []; |
| 2354 node = node.firstChild; |
| 2355 while (node) { |
| 2356 retVal.push(node); |
| 2357 node = node.nextSibling; |
| 2358 } |
| 2359 return retVal; |
| 2360 } |
| 2361 axe.utils.getFlattenedTree = function(node, shadowId) { |
| 2362 var retVal, realArray, nodeName; |
| 2363 function reduceShadowDOM(res, child) { |
| 2364 var replacements = axe.utils.getFlattenedTree(child, shadowId); |
| 2365 if (replacements) { |
| 2366 res = res.concat(replacements); |
| 2367 } |
| 2368 return res; |
| 2369 } |
| 2370 if (node.documentElement) { |
| 2371 node = node.documentElement; |
| 2372 } |
| 2373 nodeName = node.nodeName.toLowerCase(); |
| 2374 if (node.shadowRoot && nodeName !== 'marquee') { |
| 2375 shadowId = 'a' + Math.random().toString().substring(2); |
| 2376 realArray = Array.from(node.shadowRoot.childNodes); |
| 2377 return realArray.reduce(reduceShadowDOM, []); |
| 2378 } else { |
| 2379 if (nodeName === 'content') { |
| 2380 realArray = Array.from(node.getDistributedNodes()); |
| 2381 return realArray.reduce(reduceShadowDOM, []); |
| 2382 } else if (nodeName === 'slot') { |
| 2383 realArray = Array.from(node.assignedNodes()); |
| 2384 if (!realArray.length) { |
| 2385 realArray = getSlotChildren(node); |
| 2386 } |
| 2387 var styl = window.getComputedStyle(node); |
| 2388 if (false && styl.display !== 'contents') { |
| 2389 retVal = virtualDOMfromNode(node, shadowId); |
| 2390 retVal.children = realArray.reduce(reduceShadowDOM, []); |
| 2391 return [ retVal ]; |
| 2392 } else { |
| 2393 return realArray.reduce(reduceShadowDOM, []); |
| 2394 } |
| 2395 } else { |
| 2396 if (node.nodeType === 1) { |
| 2397 retVal = virtualDOMfromNode(node, shadowId); |
| 2398 realArray = Array.from(node.childNodes); |
| 2399 retVal.children = realArray.reduce(reduceShadowDOM, []); |
| 2400 return [ retVal ]; |
| 2401 } else if (node.nodeType === 3) { |
| 2402 return [ virtualDOMfromNode(node) ]; |
| 2403 } |
| 2404 return undefined; |
| 2405 } |
| 2406 } |
| 2407 }; |
| 2408 axe.utils.getNodeFromTree = function(vNode, node) { |
| 2409 var found; |
| 2410 vNode.children.forEach(function(candidate) { |
| 2411 var retVal; |
| 2412 if (candidate.actualNode === node) { |
| 2413 found = candidate; |
| 2414 } else { |
| 2415 retVal = axe.utils.getNodeFromTree(candidate, node); |
| 2416 if (retVal) { |
| 2417 found = retVal; |
| 2418 } |
| 2419 } |
| 2420 }); |
| 2421 return found; |
| 2422 }; |
| 2423 'use strict'; |
| 2424 axe.utils.getAllChecks = function getAllChecks(object) { |
| 2425 'use strict'; |
| 2426 var result = []; |
| 2427 return result.concat(object.any || []).concat(object.all || []).concat(objec
t.none || []); |
| 2428 }; |
| 2429 'use strict'; |
| 2430 axe.utils.getCheckOption = function(check, ruleID, options) { |
| 2431 var ruleCheckOption = ((options.rules && options.rules[ruleID] || {}).checks
|| {})[check.id]; |
| 2432 var checkOption = (options.checks || {})[check.id]; |
| 2433 var enabled = check.enabled; |
| 2434 var opts = check.options; |
| 2435 if (checkOption) { |
| 2436 if (checkOption.hasOwnProperty('enabled')) { |
| 2437 enabled = checkOption.enabled; |
| 2438 } |
| 2439 if (checkOption.hasOwnProperty('options')) { |
| 2440 opts = checkOption.options; |
| 2441 } |
| 2442 } |
| 2443 if (ruleCheckOption) { |
| 2444 if (ruleCheckOption.hasOwnProperty('enabled')) { |
| 2445 enabled = ruleCheckOption.enabled; |
| 2446 } |
| 2447 if (ruleCheckOption.hasOwnProperty('options')) { |
| 2448 opts = ruleCheckOption.options; |
| 2449 } |
| 2450 } |
| 2451 return { |
| 2452 enabled: enabled, |
| 2453 options: opts, |
| 2454 absolutePaths: options.absolutePaths |
| 2455 }; |
| 2456 }; |
| 2457 'use strict'; |
| 2458 var _slicedToArray = function() { |
| 2459 function sliceIterator(arr, i) { |
| 2460 var _arr = []; |
| 2461 var _n = true; |
| 2462 var _d = false; |
| 2463 var _e = undefined; |
| 2464 try { |
| 2465 for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done);
_n = true) { |
| 2466 _arr.push(_s.value); |
| 2467 if (i && _arr.length === i) { |
| 2468 break; |
| 2469 } |
| 2470 } |
| 2471 } catch (err) { |
| 2472 _d = true; |
| 2473 _e = err; |
| 2474 } finally { |
| 2475 try { |
| 2476 if (!_n && _i['return']) { |
| 2477 _i['return'](); |
| 2478 } |
| 2479 } finally { |
| 2480 if (_d) { |
| 2481 throw _e; |
| 2482 } |
| 2483 } |
| 2484 } |
| 2485 return _arr; |
| 2486 } |
| 2487 return function(arr, i) { |
| 2488 if (Array.isArray(arr)) { |
| 2489 return arr; |
| 2490 } else if (Symbol.iterator in Object(arr)) { |
| 2491 return sliceIterator(arr, i); |
| 2492 } else { |
| 2493 throw new TypeError('Invalid attempt to destructure non-iterable instanc
e'); |
| 2494 } |
| 2495 }; |
| 2496 }(); |
| 2497 function isMostlyNumbers() { |
| 2498 var str = arguments.length > 0 && arguments[0] !== undefined ? arguments[0]
: ''; |
| 2499 return str.length !== 0 && (str.match(/[0-9]/g) || '').length >= str.length
/ 2; |
| 2500 } |
| 2501 function splitString(str, splitIndex) { |
| 2502 return [ str.substring(0, splitIndex), str.substring(splitIndex) ]; |
| 2503 } |
| 2504 function uriParser(url) { |
| 2505 var original = url; |
| 2506 var protocol = '', domain = '', port = '', path = '', query = '', hash = ''; |
| 2507 if (url.includes('#')) { |
| 2508 var _splitString = splitString(url, url.indexOf('#')); |
| 2509 var _splitString2 = _slicedToArray(_splitString, 2); |
| 2510 url = _splitString2[0]; |
| 2511 hash = _splitString2[1]; |
| 2512 } |
| 2513 if (url.includes('?')) { |
| 2514 var _splitString3 = splitString(url, url.indexOf('?')); |
| 2515 var _splitString4 = _slicedToArray(_splitString3, 2); |
| 2516 url = _splitString4[0]; |
| 2517 query = _splitString4[1]; |
| 2518 } |
| 2519 if (url.includes('://')) { |
| 2520 var _url$split = url.split('://'); |
| 2521 var _url$split2 = _slicedToArray(_url$split, 2); |
| 2522 protocol = _url$split2[0]; |
| 2523 url = _url$split2[1]; |
| 2524 var _splitString5 = splitString(url, url.indexOf('/')); |
| 2525 var _splitString6 = _slicedToArray(_splitString5, 2); |
| 2526 domain = _splitString6[0]; |
| 2527 url = _splitString6[1]; |
| 2528 } else if (url.substr(0, 2) === '//') { |
| 2529 url = url.substr(2); |
| 2530 var _splitString7 = splitString(url, url.indexOf('/')); |
| 2531 var _splitString8 = _slicedToArray(_splitString7, 2); |
| 2532 domain = _splitString8[0]; |
| 2533 url = _splitString8[1]; |
| 2534 } |
| 2535 if (domain.substr(0, 4) === 'www.') { |
| 2536 domain = domain.substr(4); |
| 2537 } |
| 2538 if (domain && domain.includes(':')) { |
| 2539 var _splitString9 = splitString(domain, domain.indexOf(':')); |
| 2540 var _splitString10 = _slicedToArray(_splitString9, 2); |
| 2541 domain = _splitString10[0]; |
| 2542 port = _splitString10[1]; |
| 2543 } |
| 2544 path = url; |
| 2545 return { |
| 2546 original: original, |
| 2547 protocol: protocol, |
| 2548 domain: domain, |
| 2549 port: port, |
| 2550 path: path, |
| 2551 query: query, |
| 2552 hash: hash |
| 2553 }; |
| 2554 } |
| 2555 axe.utils.getFriendlyUriEnd = function getFriendlyUriEnd() { |
| 2556 var uri = arguments.length > 0 && arguments[0] !== undefined ? arguments[0]
: ''; |
| 2557 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments
[1] : {}; |
| 2558 if (uri.length <= 1 || uri.substr(0, 5) === 'data:' || uri.substr(0, 11) ===
'javascript:' || uri.includes('?')) { |
| 2559 return; |
| 2560 } |
| 2561 var currentDomain = options.currentDomain, _options$maxLength = options.maxL
ength, maxLength = _options$maxLength === undefined ? 25 : _options$maxLength; |
| 2562 var _uriParser = uriParser(uri), path = _uriParser.path, domain = _uriParser
.domain, hash = _uriParser.hash; |
| 2563 var pathEnd = path.substr(path.substr(0, path.length - 2).lastIndexOf('/') +
1); |
| 2564 if (hash) { |
| 2565 if (pathEnd && (pathEnd + hash).length <= maxLength) { |
| 2566 return pathEnd + hash; |
| 2567 } else if (pathEnd.length < 2 && hash.length > 2 && hash.length <= maxLeng
th) { |
| 2568 return hash; |
| 2569 } else { |
| 2570 return; |
| 2571 } |
| 2572 } else if (domain && domain.length < maxLength && path.length <= 1) { |
| 2573 return domain + path; |
| 2574 } |
| 2575 if (path === '/' + pathEnd && domain && currentDomain && domain !== currentD
omain && (domain + path).length <= maxLength) { |
| 2576 return domain + path; |
| 2577 } |
| 2578 var lastDotIndex = pathEnd.lastIndexOf('.'); |
| 2579 if ((lastDotIndex === -1 || lastDotIndex > 1) && (lastDotIndex !== -1 || pat
hEnd.length > 2) && pathEnd.length <= maxLength && !pathEnd.match(/index(\.[a-zA
-Z]{2-4})?/) && !isMostlyNumbers(pathEnd)) { |
| 2580 return pathEnd; |
| 2581 } |
| 2582 }; |
| 2583 'use strict'; |
| 2584 function _toConsumableArray(arr) { |
| 2585 if (Array.isArray(arr)) { |
| 2586 for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { |
| 2587 arr2[i] = arr[i]; |
| 2588 } |
| 2589 return arr2; |
| 2590 } else { |
| 2591 return Array.from(arr); |
| 2592 } |
| 2593 } |
| 2594 var escapeSelector = axe.utils.escapeSelector; |
| 2595 function isUncommonClassName(className) { |
| 2596 return ![ 'focus', 'hover', 'hidden', 'visible', 'dirty', 'touched', 'valid'
, 'disable', 'enable', 'active', 'col-' ].find(function(str) { |
| 2597 return className.includes(str); |
| 2598 }); |
| 2599 } |
| 2600 function getDistinctClassList(elm) { |
| 2601 if (!elm.classList || elm.classList.length === 0) { |
| 2602 return []; |
| 2603 } |
| 2604 var siblings = elm.parentNode && Array.from(elm.parentNode.children || '') |
| []; |
| 2605 return siblings.reduce(function(classList, childElm) { |
| 2606 if (elm === childElm) { |
| 2607 return classList; |
| 2608 } else { |
| 2609 return classList.filter(function(classItem) { |
| 2610 return !childElm.classList.contains(classItem); |
| 2611 }); |
| 2612 } |
| 2613 }, Array.from(elm.classList).filter(isUncommonClassName)); |
| 2614 } |
| 2615 var commonNodes = [ 'div', 'span', 'p', 'b', 'i', 'u', 'strong', 'em', 'h2', '
h3' ]; |
| 2616 function getNthChildString(elm, selector) { |
| 2617 var siblings = elm.parentNode && Array.from(elm.parentNode.children || '') |
| []; |
| 2618 var hasMatchingSiblings = siblings.find(function(sibling) { |
| 2619 return sibling !== elm && axe.utils.matchesSelector(sibling, selector); |
| 2620 }); |
| 2621 if (hasMatchingSiblings) { |
| 2622 var nthChild = 1 + siblings.indexOf(elm); |
| 2623 return ':nth-child(' + nthChild + ')'; |
| 2624 } else { |
| 2625 return ''; |
| 2626 } |
| 2627 } |
| 2628 var createSelector = { |
| 2629 getElmId: function getElmId(elm) { |
| 2630 if (!elm.id) { |
| 2631 return; |
| 2632 } |
| 2633 var doc = elm.getRootNode && elm.getRootNode() || document; |
| 2634 var id = '#' + escapeSelector(elm.id || ''); |
| 2635 if (!id.match(/player_uid_/) && doc.querySelectorAll(id).length === 1) { |
| 2636 return id; |
| 2637 } |
| 2638 }, |
| 2639 getCustomElm: function getCustomElm(elm, _ref) { |
| 2640 var isCustomElm = _ref.isCustomElm, nodeName = _ref.nodeName; |
| 2641 if (isCustomElm) { |
| 2642 return nodeName; |
| 2643 } |
| 2644 }, |
| 2645 getElmRoleProp: function getElmRoleProp(elm) { |
| 2646 if (elm.hasAttribute('role')) { |
| 2647 return '[role="' + escapeSelector(elm.getAttribute('role')) + '"]'; |
| 2648 } |
| 2649 }, |
| 2650 getUncommonElm: function getUncommonElm(elm, _ref2) { |
| 2651 var isCommonElm = _ref2.isCommonElm, isCustomElm = _ref2.isCustomElm, node
Name = _ref2.nodeName; |
| 2652 if (!isCommonElm && !isCustomElm) { |
| 2653 nodeName = escapeSelector(nodeName); |
| 2654 if (nodeName === 'input' && elm.hasAttribute('type')) { |
| 2655 nodeName += '[type="' + elm.type + '"]'; |
| 2656 } |
| 2657 return nodeName; |
| 2658 } |
| 2659 }, |
| 2660 getElmNameProp: function getElmNameProp(elm) { |
| 2661 if (!elm.id && elm.name) { |
| 2662 return '[name="' + escapeSelector(elm.name) + '"]'; |
| 2663 } |
| 2664 }, |
| 2665 getDistinctClass: function getDistinctClass(elm, _ref3) { |
| 2666 var distinctClassList = _ref3.distinctClassList; |
| 2667 if (distinctClassList.length > 0 && distinctClassList.length < 3) { |
| 2668 return '.' + distinctClassList.map(escapeSelector).join('.'); |
| 2669 } |
| 2670 }, |
| 2671 getFileRefProp: function getFileRefProp(elm) { |
| 2672 var attr = void 0; |
| 2673 if (elm.hasAttribute('href')) { |
| 2674 attr = 'href'; |
| 2675 } else if (elm.hasAttribute('src')) { |
| 2676 attr = 'src'; |
| 2677 } else { |
| 2678 return; |
| 2679 } |
| 2680 var friendlyUriEnd = axe.utils.getFriendlyUriEnd(elm.getAttribute(attr)); |
| 2681 if (friendlyUriEnd) { |
| 2682 return '[' + attr + '$="' + encodeURI(friendlyUriEnd) + '"]'; |
| 2683 } |
| 2684 }, |
| 2685 getCommonName: function getCommonName(elm, _ref4) { |
| 2686 var nodeName = _ref4.nodeName, isCommonElm = _ref4.isCommonElm; |
| 2687 if (isCommonElm) { |
| 2688 return nodeName; |
| 2689 } |
| 2690 } |
| 2691 }; |
| 2692 function getElmFeatures(elm, featureCount) { |
| 2693 var nodeName = elm.nodeName.toLowerCase(); |
| 2694 var classList = Array.from(elm.classList) || []; |
| 2695 var props = { |
| 2696 nodeName: nodeName, |
| 2697 classList: classList, |
| 2698 isCustomElm: nodeName.includes('-'), |
| 2699 isCommonElm: commonNodes.includes(nodeName), |
| 2700 distinctClassList: getDistinctClassList(elm) |
| 2701 }; |
| 2702 return [ createSelector.getCustomElm, createSelector.getElmRoleProp, createS
elector.getUncommonElm, createSelector.getElmNameProp, createSelector.getDistinc
tClass, createSelector.getFileRefProp, createSelector.getCommonName ].reduce(fun
ction(features, func) { |
| 2703 if (features.length === featureCount) { |
| 2704 return features; |
| 2705 } |
| 2706 var feature = func(elm, props); |
| 2707 if (feature) { |
| 2708 if (!feature[0].match(/[a-z]/)) { |
| 2709 features.push(feature); |
| 2710 } else { |
| 2711 features.unshift(feature); |
| 2712 } |
| 2713 } |
| 2714 return features; |
| 2715 }, []); |
| 2716 } |
| 2717 function generateSelector(elm, options, doc) { |
| 2718 var selector = void 0, addParent = void 0; |
| 2719 var _options$isUnique = options.isUnique, isUnique = _options$isUnique === u
ndefined ? false : _options$isUnique; |
| 2720 var idSelector = createSelector.getElmId(elm); |
| 2721 var _options$featureCount = options.featureCount, featureCount = _options$fe
atureCount === undefined ? 2 : _options$featureCount, _options$minDepth = option
s.minDepth, minDepth = _options$minDepth === undefined ? 1 : _options$minDepth,
_options$toRoot = options.toRoot, toRoot = _options$toRoot === undefined ? false
: _options$toRoot, _options$childSelecto = options.childSelectors, childSelecto
rs = _options$childSelecto === undefined ? [] : _options$childSelecto; |
| 2722 if (idSelector) { |
| 2723 selector = idSelector; |
| 2724 isUnique = true; |
| 2725 } else { |
| 2726 selector = getElmFeatures(elm, featureCount).join(''); |
| 2727 selector += getNthChildString(elm, selector); |
| 2728 isUnique = options.isUnique || doc.querySelectorAll(selector).length === 1
; |
| 2729 if (!isUnique && elm === document.documentElement) { |
| 2730 selector += ':root'; |
| 2731 } |
| 2732 addParent = minDepth !== 0 || !isUnique; |
| 2733 } |
| 2734 var selectorParts = [ selector ].concat(_toConsumableArray(childSelectors)); |
| 2735 if (elm.parentElement && elm.parentElement.nodeType !== 11 && (toRoot || add
Parent)) { |
| 2736 return generateSelector(elm.parentNode, { |
| 2737 toRoot: toRoot, |
| 2738 isUnique: isUnique, |
| 2739 childSelectors: selectorParts, |
| 2740 featureCount: 1, |
| 2741 minDepth: minDepth - 1 |
| 2742 }, doc); |
| 2743 } else { |
| 2744 return selectorParts.join(' > '); |
| 2745 } |
| 2746 } |
| 2747 axe.utils.getSelector = function createUniqueSelector(elm) { |
| 2748 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments
[1] : {}; |
| 2749 if (!elm) { |
| 2750 return ''; |
| 2751 } |
| 2752 var doc = elm.getRootNode && elm.getRootNode() || document; |
| 2753 if (doc.nodeType === 11) { |
| 2754 var stack = []; |
| 2755 while (doc.nodeType === 11) { |
| 2756 stack.push({ |
| 2757 elm: elm, |
| 2758 doc: doc |
| 2759 }); |
| 2760 elm = doc.host; |
| 2761 doc = elm.getRootNode(); |
| 2762 } |
| 2763 stack.push({ |
| 2764 elm: elm, |
| 2765 doc: doc |
| 2766 }); |
| 2767 return stack.reverse().map(function(comp) { |
| 2768 return generateSelector(comp.elm, options, comp.doc); |
| 2769 }); |
| 2770 } else { |
| 2771 return generateSelector(elm, options, doc); |
| 2772 } |
| 2773 }; |
| 2774 'use strict'; |
| 2775 function getXPathArray(node, path) { |
| 2776 var sibling, count; |
| 2777 if (!node) { |
| 2778 return []; |
| 2779 } |
| 2780 if (!path && node.nodeType === 9) { |
| 2781 path = [ { |
| 2782 str: 'html' |
| 2783 } ]; |
| 2784 return path; |
| 2785 } |
| 2786 path = path || []; |
| 2787 if (node.parentNode && node.parentNode !== node) { |
| 2788 path = getXPathArray(node.parentNode, path); |
| 2789 } |
| 2790 if (node.previousSibling) { |
| 2791 count = 1; |
| 2792 sibling = node.previousSibling; |
| 2793 do { |
| 2794 if (sibling.nodeType === 1 && sibling.nodeName === node.nodeName) { |
| 2795 count++; |
| 2796 } |
| 2797 sibling = sibling.previousSibling; |
| 2798 } while (sibling); |
| 2799 if (count === 1) { |
| 2800 count = null; |
| 2801 } |
| 2802 } else if (node.nextSibling) { |
| 2803 sibling = node.nextSibling; |
| 2804 do { |
| 2805 if (sibling.nodeType === 1 && sibling.nodeName === node.nodeName) { |
| 2806 count = 1; |
| 2807 sibling = null; |
| 2808 } else { |
| 2809 count = null; |
| 2810 sibling = sibling.previousSibling; |
| 2811 } |
| 2812 } while (sibling); |
| 2813 } |
| 2814 if (node.nodeType === 1) { |
| 2815 var element = {}; |
| 2816 element.str = node.nodeName.toLowerCase(); |
| 2817 if (node.getAttribute && node.getAttribute('id') && node.ownerDocument.que
rySelectorAll('#' + axe.utils.escapeSelector(node.id)).length === 1) { |
| 2818 element.id = node.getAttribute('id'); |
| 2819 } |
| 2820 if (count > 1) { |
| 2821 element.count = count; |
| 2822 } |
| 2823 path.push(element); |
| 2824 } |
| 2825 return path; |
| 2826 } |
| 2827 function xpathToString(xpathArray) { |
| 2828 return xpathArray.reduce(function(str, elm) { |
| 2829 if (elm.id) { |
| 2830 return '/' + elm.str + '[@id=\'' + elm.id + '\']'; |
| 2831 } else { |
| 2832 return str + ('/' + elm.str) + (elm.count > 0 ? '[' + elm.count + ']' :
''); |
| 2833 } |
| 2834 }, ''); |
| 2835 } |
| 2836 axe.utils.getXpath = function getXpath(node) { |
| 2837 var xpathArray = getXPathArray(node); |
| 2838 return xpathToString(xpathArray); |
| 2839 }; |
| 2840 'use strict'; |
| 2841 var styleSheet; |
| 2842 function injectStyle(style) { |
| 2843 'use strict'; |
| 2844 if (styleSheet && styleSheet.parentNode) { |
| 2845 if (styleSheet.styleSheet === undefined) { |
| 2846 styleSheet.appendChild(document.createTextNode(style)); |
| 2847 } else { |
| 2848 styleSheet.styleSheet.cssText += style; |
| 2849 } |
| 2850 return styleSheet; |
| 2851 } |
| 2852 if (!style) { |
| 2853 return; |
| 2854 } |
| 2855 var head = document.head || document.getElementsByTagName('head')[0]; |
| 2856 styleSheet = document.createElement('style'); |
| 2857 styleSheet.type = 'text/css'; |
| 2858 if (styleSheet.styleSheet === undefined) { |
| 2859 styleSheet.appendChild(document.createTextNode(style)); |
| 2860 } else { |
| 2861 styleSheet.styleSheet.cssText = style; |
| 2862 } |
| 2863 head.appendChild(styleSheet); |
| 2864 return styleSheet; |
| 2865 } |
| 2866 axe.utils.injectStyle = injectStyle; |
| 2867 'use strict'; |
| 2868 axe.utils.isHidden = function isHidden(el, recursed) { |
| 2869 'use strict'; |
| 2870 var parent; |
| 2871 if (el.nodeType === 9) { |
| 2872 return false; |
| 2873 } |
| 2874 if (el.nodeType === 11) { |
| 2875 el = el.host; |
| 2876 } |
| 2877 var style = window.getComputedStyle(el, null); |
| 2878 if (!style || !el.parentNode || style.getPropertyValue('display') === 'none'
|| !recursed && style.getPropertyValue('visibility') === 'hidden' || el.getAttr
ibute('aria-hidden') === 'true') { |
| 2879 return true; |
| 2880 } |
| 2881 parent = el.assignedSlot ? el.assignedSlot : el.parentNode; |
| 2882 return axe.utils.isHidden(parent, true); |
| 2883 }; |
| 2884 'use strict'; |
| 2885 function pushFrame(resultSet, options, frameElement, frameSelector) { |
| 2886 'use strict'; |
| 2887 var frameXpath = axe.utils.getXpath(frameElement); |
| 2888 var frameSpec = { |
| 2889 element: frameElement, |
| 2890 selector: frameSelector, |
| 2891 xpath: frameXpath |
| 2892 }; |
| 2893 resultSet.forEach(function(res) { |
| 2894 res.node = axe.utils.DqElement.fromFrame(res.node, options, frameSpec); |
| 2895 var checks = axe.utils.getAllChecks(res); |
| 2896 if (checks.length) { |
| 2897 checks.forEach(function(check) { |
| 2898 check.relatedNodes = check.relatedNodes.map(function(node) { |
| 2899 return axe.utils.DqElement.fromFrame(node, options, frameSpec); |
| 2900 }); |
| 2901 }); |
| 2902 } |
| 2903 }); |
| 2904 } |
| 2905 function spliceNodes(target, to) { |
| 2906 'use strict'; |
| 2907 var firstFromFrame = to[0].node, sorterResult, t; |
| 2908 for (var i = 0, l = target.length; i < l; i++) { |
| 2909 t = target[i].node; |
| 2910 sorterResult = axe.utils.nodeSorter({ |
| 2911 actualNode: t.element |
| 2912 }, { |
| 2913 actualNode: firstFromFrame.element |
| 2914 }); |
| 2915 if (sorterResult > 0 || sorterResult === 0 && firstFromFrame.selector.leng
th < t.selector.length) { |
| 2916 target.splice.apply(target, [ i, 0 ].concat(to)); |
| 2917 return; |
| 2918 } |
| 2919 } |
| 2920 target.push.apply(target, to); |
| 2921 } |
| 2922 function normalizeResult(result) { |
| 2923 'use strict'; |
| 2924 if (!result || !result.results) { |
| 2925 return null; |
| 2926 } |
| 2927 if (!Array.isArray(result.results)) { |
| 2928 return [ result.results ]; |
| 2929 } |
| 2930 if (!result.results.length) { |
| 2931 return null; |
| 2932 } |
| 2933 return result.results; |
| 2934 } |
| 2935 axe.utils.mergeResults = function mergeResults(frameResults, options) { |
| 2936 'use strict'; |
| 2937 var result = []; |
| 2938 frameResults.forEach(function(frameResult) { |
| 2939 var results = normalizeResult(frameResult); |
| 2940 if (!results || !results.length) { |
| 2941 return; |
| 2942 } |
| 2943 results.forEach(function(ruleResult) { |
| 2944 if (ruleResult.nodes && frameResult.frame) { |
| 2945 pushFrame(ruleResult.nodes, options, frameResult.frameElement, frameRe
sult.frame); |
| 2946 } |
| 2947 var res = axe.utils.findBy(result, 'id', ruleResult.id); |
| 2948 if (!res) { |
| 2949 result.push(ruleResult); |
| 2950 } else { |
| 2951 if (ruleResult.nodes.length) { |
| 2952 spliceNodes(res.nodes, ruleResult.nodes); |
| 2953 } |
| 2954 } |
| 2955 }); |
| 2956 }); |
| 2957 return result; |
| 2958 }; |
| 2959 'use strict'; |
| 2960 axe.utils.nodeSorter = function nodeSorter(a, b) { |
| 2961 'use strict'; |
| 2962 if (a.actualNode === b.actualNode) { |
| 2963 return 0; |
| 2964 } |
| 2965 if (a.actualNode.compareDocumentPosition(b.actualNode) & 4) { |
| 2966 return -1; |
| 2967 } |
| 2968 return 1; |
| 2969 }; |
| 2970 'use strict'; |
| 2971 utils.performanceTimer = function() { |
| 2972 'use strict'; |
| 2973 function now() { |
| 2974 if (window.performance && window.performance) { |
| 2975 return window.performance.now(); |
| 2976 } |
| 2977 } |
| 2978 var originalTime = null; |
| 2979 var lastRecordedTime = now(); |
| 2980 return { |
| 2981 start: function start() { |
| 2982 this.mark('mark_axe_start'); |
| 2983 }, |
| 2984 end: function end() { |
| 2985 this.mark('mark_axe_end'); |
| 2986 this.measure('axe', 'mark_axe_start', 'mark_axe_end'); |
| 2987 this.logMeasures('axe'); |
| 2988 }, |
| 2989 auditStart: function auditStart() { |
| 2990 this.mark('mark_audit_start'); |
| 2991 }, |
| 2992 auditEnd: function auditEnd() { |
| 2993 this.mark('mark_audit_end'); |
| 2994 this.measure('audit_start_to_end', 'mark_audit_start', 'mark_audit_end')
; |
| 2995 this.logMeasures(); |
| 2996 }, |
| 2997 mark: function mark(markName) { |
| 2998 if (window.performance && window.performance.mark !== undefined) { |
| 2999 window.performance.mark(markName); |
| 3000 } |
| 3001 }, |
| 3002 measure: function measure(measureName, startMark, endMark) { |
| 3003 if (window.performance && window.performance.measure !== undefined) { |
| 3004 window.performance.measure(measureName, startMark, endMark); |
| 3005 } |
| 3006 }, |
| 3007 logMeasures: function logMeasures(measureName) { |
| 3008 function log(req) { |
| 3009 axe.log('Measure ' + req.name + ' took ' + req.duration + 'ms'); |
| 3010 } |
| 3011 if (window.performance && window.performance.getEntriesByType !== undefi
ned) { |
| 3012 var measures = window.performance.getEntriesByType('measure'); |
| 3013 for (var i = 0; i < measures.length; ++i) { |
| 3014 var req = measures[i]; |
| 3015 if (req.name === measureName) { |
| 3016 log(req); |
| 3017 return; |
| 3018 } |
| 3019 log(req); |
| 3020 } |
| 3021 } |
| 3022 }, |
| 3023 timeElapsed: function timeElapsed() { |
| 3024 return now() - lastRecordedTime; |
| 3025 }, |
| 3026 reset: function reset() { |
| 3027 if (!originalTime) { |
| 3028 originalTime = now(); |
| 3029 } |
| 3030 lastRecordedTime = now(); |
| 3031 } |
| 3032 }; |
| 3033 }(); |
| 3034 'use strict'; |
| 3035 if (typeof Object.assign !== 'function') { |
| 3036 (function() { |
| 3037 Object.assign = function(target) { |
| 3038 'use strict'; |
| 3039 if (target === undefined || target === null) { |
| 3040 throw new TypeError('Cannot convert undefined or null to object'); |
| 3041 } |
| 3042 var output = Object(target); |
| 3043 for (var index = 1; index < arguments.length; index++) { |
| 3044 var source = arguments[index]; |
| 3045 if (source !== undefined && source !== null) { |
| 3046 for (var nextKey in source) { |
| 3047 if (source.hasOwnProperty(nextKey)) { |
| 3048 output[nextKey] = source[nextKey]; |
| 3049 } |
| 3050 } |
| 3051 } |
| 3052 } |
| 3053 return output; |
| 3054 }; |
| 3055 })(); |
| 3056 } |
| 3057 if (!Array.prototype.find) { |
| 3058 Array.prototype.find = function(predicate) { |
| 3059 if (this === null) { |
| 3060 throw new TypeError('Array.prototype.find called on null or undefined'); |
| 3061 } |
| 3062 if (typeof predicate !== 'function') { |
| 3063 throw new TypeError('predicate must be a function'); |
| 3064 } |
| 3065 var list = Object(this); |
| 3066 var length = list.length >>> 0; |
| 3067 var thisArg = arguments[1]; |
| 3068 var value; |
| 3069 for (var i = 0; i < length; i++) { |
| 3070 value = list[i]; |
| 3071 if (predicate.call(thisArg, value, i, list)) { |
| 3072 return value; |
| 3073 } |
| 3074 } |
| 3075 return undefined; |
| 3076 }; |
| 3077 } |
| 3078 axe.utils.pollyfillElementsFromPoint = function() { |
| 3079 if (document.elementsFromPoint) { |
| 3080 return document.elementsFromPoint; |
| 3081 } |
| 3082 if (document.msElementsFromPoint) { |
| 3083 return document.msElementsFromPoint; |
| 3084 } |
| 3085 var usePointer = function() { |
| 3086 var element = document.createElement('x'); |
| 3087 element.style.cssText = 'pointer-events:auto'; |
| 3088 return element.style.pointerEvents === 'auto'; |
| 3089 }(); |
| 3090 var cssProp = usePointer ? 'pointer-events' : 'visibility'; |
| 3091 var cssDisableVal = usePointer ? 'none' : 'hidden'; |
| 3092 var style = document.createElement('style'); |
| 3093 style.innerHTML = usePointer ? '* { pointer-events: all }' : '* { visibility
: visible }'; |
| 3094 return function(x, y) { |
| 3095 var current, i, d; |
| 3096 var elements = []; |
| 3097 var previousPointerEvents = []; |
| 3098 document.head.appendChild(style); |
| 3099 while ((current = document.elementFromPoint(x, y)) && elements.indexOf(cur
rent) === -1) { |
| 3100 elements.push(current); |
| 3101 previousPointerEvents.push({ |
| 3102 value: current.style.getPropertyValue(cssProp), |
| 3103 priority: current.style.getPropertyPriority(cssProp) |
| 3104 }); |
| 3105 current.style.setProperty(cssProp, cssDisableVal, 'important'); |
| 3106 } |
| 3107 for (i = previousPointerEvents.length; !!(d = previousPointerEvents[--i]);
) { |
| 3108 elements[i].style.setProperty(cssProp, d.value ? d.value : '', d.priorit
y); |
| 3109 } |
| 3110 document.head.removeChild(style); |
| 3111 return elements; |
| 3112 }; |
| 3113 }; |
| 3114 if (typeof window.addEventListener === 'function') { |
| 3115 document.elementsFromPoint = axe.utils.pollyfillElementsFromPoint(); |
| 3116 } |
| 3117 if (!Array.prototype.includes) { |
| 3118 Array.prototype.includes = function(searchElement) { |
| 3119 'use strict'; |
| 3120 var O = Object(this); |
| 3121 var len = parseInt(O.length, 10) || 0; |
| 3122 if (len === 0) { |
| 3123 return false; |
| 3124 } |
| 3125 var n = parseInt(arguments[1], 10) || 0; |
| 3126 var k; |
| 3127 if (n >= 0) { |
| 3128 k = n; |
| 3129 } else { |
| 3130 k = len + n; |
| 3131 if (k < 0) { |
| 3132 k = 0; |
| 3133 } |
| 3134 } |
| 3135 var currentElement; |
| 3136 while (k < len) { |
| 3137 currentElement = O[k]; |
| 3138 if (searchElement === currentElement || searchElement !== searchElement
&& currentElement !== currentElement) { |
| 3139 return true; |
| 3140 } |
| 3141 k++; |
| 3142 } |
| 3143 return false; |
| 3144 }; |
| 3145 } |
| 3146 if (!Array.prototype.some) { |
| 3147 Array.prototype.some = function(fun) { |
| 3148 'use strict'; |
| 3149 if (this == null) { |
| 3150 throw new TypeError('Array.prototype.some called on null or undefined'); |
| 3151 } |
| 3152 if (typeof fun !== 'function') { |
| 3153 throw new TypeError(); |
| 3154 } |
| 3155 var t = Object(this); |
| 3156 var len = t.length >>> 0; |
| 3157 var thisArg = arguments.length >= 2 ? arguments[1] : void 0; |
| 3158 for (var i = 0; i < len; i++) { |
| 3159 if (i in t && fun.call(thisArg, t[i], i, t)) { |
| 3160 return true; |
| 3161 } |
| 3162 } |
| 3163 return false; |
| 3164 }; |
| 3165 } |
| 3166 if (!Array.from) { |
| 3167 Array.from = function() { |
| 3168 var toStr = Object.prototype.toString; |
| 3169 var isCallable = function isCallable(fn) { |
| 3170 return typeof fn === 'function' || toStr.call(fn) === '[object Function]
'; |
| 3171 }; |
| 3172 var toInteger = function toInteger(value) { |
| 3173 var number = Number(value); |
| 3174 if (isNaN(number)) { |
| 3175 return 0; |
| 3176 } |
| 3177 if (number === 0 || !isFinite(number)) { |
| 3178 return number; |
| 3179 } |
| 3180 return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number)); |
| 3181 }; |
| 3182 var maxSafeInteger = Math.pow(2, 53) - 1; |
| 3183 var toLength = function toLength(value) { |
| 3184 var len = toInteger(value); |
| 3185 return Math.min(Math.max(len, 0), maxSafeInteger); |
| 3186 }; |
| 3187 return function from(arrayLike) { |
| 3188 var C = this; |
| 3189 var items = Object(arrayLike); |
| 3190 if (arrayLike == null) { |
| 3191 throw new TypeError('Array.from requires an array-like object - not nu
ll or undefined'); |
| 3192 } |
| 3193 var mapFn = arguments.length > 1 ? arguments[1] : void undefined; |
| 3194 var T; |
| 3195 if (typeof mapFn !== 'undefined') { |
| 3196 if (!isCallable(mapFn)) { |
| 3197 throw new TypeError('Array.from: when provided, the second argument
must be a function'); |
| 3198 } |
| 3199 if (arguments.length > 2) { |
| 3200 T = arguments[2]; |
| 3201 } |
| 3202 } |
| 3203 var len = toLength(items.length); |
| 3204 var A = isCallable(C) ? Object(new C(len)) : new Array(len); |
| 3205 var k = 0; |
| 3206 var kValue; |
| 3207 while (k < len) { |
| 3208 kValue = items[k]; |
| 3209 if (mapFn) { |
| 3210 A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, k
Value, k); |
| 3211 } else { |
| 3212 A[k] = kValue; |
| 3213 } |
| 3214 k += 1; |
| 3215 } |
| 3216 A.length = len; |
| 3217 return A; |
| 3218 }; |
| 3219 }(); |
| 3220 } |
| 3221 if (!String.prototype.includes) { |
| 3222 String.prototype.includes = function(search, start) { |
| 3223 if (typeof start !== 'number') { |
| 3224 start = 0; |
| 3225 } |
| 3226 if (start + search.length > this.length) { |
| 3227 return false; |
| 3228 } else { |
| 3229 return this.indexOf(search, start) !== -1; |
| 3230 } |
| 3231 }; |
| 3232 } |
| 3233 'use strict'; |
| 3234 var _typeof = typeof Symbol === 'function' && typeof Symbol.iterator === 'symb
ol' ? function(obj) { |
| 3235 return typeof obj; |
| 3236 } : function(obj) { |
| 3237 return obj && typeof Symbol === 'function' && obj.constructor === Symbol &&
obj !== Symbol.prototype ? 'symbol' : typeof obj; |
| 3238 }; |
| 3239 function getIncompleteReason(checkData, messages) { |
| 3240 function getDefaultMsg(messages) { |
| 3241 if (messages.incomplete && messages.incomplete.default) { |
| 3242 return messages.incomplete.default; |
| 3243 } else { |
| 3244 return helpers.incompleteFallbackMessage(); |
| 3245 } |
| 3246 } |
| 3247 if (checkData && checkData.missingData) { |
| 3248 try { |
| 3249 var msg = messages.incomplete[checkData.missingData[0].reason]; |
| 3250 if (!msg) { |
| 3251 throw new Error(); |
| 3252 } |
| 3253 return msg; |
| 3254 } catch (e) { |
| 3255 if (typeof checkData.missingData === 'string') { |
| 3256 return messages.incomplete[checkData.missingData]; |
| 3257 } else { |
| 3258 return getDefaultMsg(messages); |
| 3259 } |
| 3260 } |
| 3261 } else { |
| 3262 return getDefaultMsg(messages); |
| 3263 } |
| 3264 } |
| 3265 function extender(checksData, shouldBeTrue) { |
| 3266 'use strict'; |
| 3267 return function(check) { |
| 3268 var sourceData = checksData[check.id] || {}; |
| 3269 var messages = sourceData.messages || {}; |
| 3270 var data = Object.assign({}, sourceData); |
| 3271 delete data.messages; |
| 3272 if (check.result === undefined) { |
| 3273 if (_typeof(messages.incomplete) === 'object') { |
| 3274 data.message = function() { |
| 3275 return getIncompleteReason(check.data, messages); |
| 3276 }; |
| 3277 } else { |
| 3278 data.message = messages.incomplete; |
| 3279 } |
| 3280 } else { |
| 3281 data.message = check.result === shouldBeTrue ? messages.pass : messages.
fail; |
| 3282 } |
| 3283 axe.utils.extendMetaData(check, data); |
| 3284 }; |
| 3285 } |
| 3286 axe.utils.publishMetaData = function(ruleResult) { |
| 3287 'use strict'; |
| 3288 var checksData = axe._audit.data.checks || {}; |
| 3289 var rulesData = axe._audit.data.rules || {}; |
| 3290 var rule = axe.utils.findBy(axe._audit.rules, 'id', ruleResult.id) || {}; |
| 3291 ruleResult.tags = axe.utils.clone(rule.tags || []); |
| 3292 var shouldBeTrue = extender(checksData, true); |
| 3293 var shouldBeFalse = extender(checksData, false); |
| 3294 ruleResult.nodes.forEach(function(detail) { |
| 3295 detail.any.forEach(shouldBeTrue); |
| 3296 detail.all.forEach(shouldBeTrue); |
| 3297 detail.none.forEach(shouldBeFalse); |
| 3298 }); |
| 3299 axe.utils.extendMetaData(ruleResult, axe.utils.clone(rulesData[ruleResult.id
] || {})); |
| 3300 }; |
| 3301 'use strict'; |
| 3302 var convertExpressions = function convertExpressions() {}; |
| 3303 var matchExpressions = function matchExpressions() {}; |
| 3304 function matchesTag(node, exp) { |
| 3305 return node.nodeType === 1 && (exp.tag === '*' || node.nodeName.toLowerCase(
) === exp.tag); |
| 3306 } |
| 3307 function matchesClasses(node, exp) { |
| 3308 return !exp.classes || exp.classes.reduce(function(result, cl) { |
| 3309 return result && node.className && node.className.match(cl.regexp); |
| 3310 }, true); |
| 3311 } |
| 3312 function matchesAttributes(node, exp) { |
| 3313 return !exp.attributes || exp.attributes.reduce(function(result, att) { |
| 3314 var nodeAtt = node.getAttribute(att.key); |
| 3315 return result && nodeAtt !== null && (!att.value || att.test(nodeAtt)); |
| 3316 }, true); |
| 3317 } |
| 3318 function matchesId(node, exp) { |
| 3319 return !exp.id || node.id === exp.id; |
| 3320 } |
| 3321 function matchesPseudos(target, exp) { |
| 3322 if (!exp.pseudos || exp.pseudos.reduce(function(result, pseudo) { |
| 3323 if (pseudo.name === 'not') { |
| 3324 return result && !matchExpressions([ target ], pseudo.expressions, false
).length; |
| 3325 } |
| 3326 throw new Error('the pseudo selector ' + pseudo.name + ' has not yet been
implemented'); |
| 3327 }, true)) { |
| 3328 return true; |
| 3329 } |
| 3330 return false; |
| 3331 } |
| 3332 function matchSelector(targets, exp, recurse) { |
| 3333 var result = []; |
| 3334 targets = Array.isArray(targets) ? targets : [ targets ]; |
| 3335 targets.forEach(function(target) { |
| 3336 if (matchesTag(target.actualNode, exp) && matchesClasses(target.actualNode
, exp) && matchesAttributes(target.actualNode, exp) && matchesId(target.actualNo
de, exp) && matchesPseudos(target, exp)) { |
| 3337 result.push(target); |
| 3338 } |
| 3339 if (recurse) { |
| 3340 result = result.concat(matchSelector(target.children.filter(function(chi
ld) { |
| 3341 return !exp.id || child.shadowId === target.shadowId; |
| 3342 }), exp, recurse)); |
| 3343 } |
| 3344 }); |
| 3345 return result; |
| 3346 } |
| 3347 var escapeRegExp = function() { |
| 3348 /*! Credit: XRegExp 0.6.1 (c) 2007-2008 Steven Levithan <http://stevenlevith
an.com/regex/xregexp/> MIT License */ |
| 3349 var from = /(?=[\-\[\]{}()*+?.\\\^$|,#\s])/g; |
| 3350 var to = '\\'; |
| 3351 return function(string) { |
| 3352 return string.replace(from, to); |
| 3353 }; |
| 3354 }(); |
| 3355 var reUnescape = /\\/g; |
| 3356 function convertAttributes(atts) { |
| 3357 /*! Credit Mootools Copyright Mootools, MIT License */ |
| 3358 if (!atts) { |
| 3359 return; |
| 3360 } |
| 3361 return atts.map(function(att) { |
| 3362 var attributeKey = att.name.replace(reUnescape, ''); |
| 3363 var attributeValue = (att.value || '').replace(reUnescape, ''); |
| 3364 var test, regexp; |
| 3365 switch (att.operator) { |
| 3366 case '^=': |
| 3367 regexp = new RegExp('^' + escapeRegExp(attributeValue)); |
| 3368 break; |
| 3369 |
| 3370 case '$=': |
| 3371 regexp = new RegExp(escapeRegExp(attributeValue) + '$'); |
| 3372 break; |
| 3373 |
| 3374 case '~=': |
| 3375 regexp = new RegExp('(^|\\s)' + escapeRegExp(attributeValue) + '(\\s|$)'
); |
| 3376 break; |
| 3377 |
| 3378 case '|=': |
| 3379 regexp = new RegExp('^' + escapeRegExp(attributeValue) + '(-|$)'); |
| 3380 break; |
| 3381 |
| 3382 case '=': |
| 3383 test = function test(value) { |
| 3384 return attributeValue === value; |
| 3385 }; |
| 3386 break; |
| 3387 |
| 3388 case '*=': |
| 3389 test = function test(value) { |
| 3390 return value && value.indexOf(attributeValue) > -1; |
| 3391 }; |
| 3392 break; |
| 3393 |
| 3394 case '!=': |
| 3395 test = function test(value) { |
| 3396 return attributeValue !== value; |
| 3397 }; |
| 3398 break; |
| 3399 |
| 3400 default: |
| 3401 test = function test(value) { |
| 3402 return !!value; |
| 3403 }; |
| 3404 } |
| 3405 if (attributeValue === '' && /^[*$^]=$/.test(att.operator)) { |
| 3406 test = function test() { |
| 3407 return false; |
| 3408 }; |
| 3409 } |
| 3410 if (!test) { |
| 3411 test = function test(value) { |
| 3412 return value && regexp.test(value); |
| 3413 }; |
| 3414 } |
| 3415 return { |
| 3416 key: attributeKey, |
| 3417 value: attributeValue, |
| 3418 test: test |
| 3419 }; |
| 3420 }); |
| 3421 } |
| 3422 function convertClasses(classes) { |
| 3423 if (!classes) { |
| 3424 return; |
| 3425 } |
| 3426 return classes.map(function(className) { |
| 3427 className = className.replace(reUnescape, ''); |
| 3428 return { |
| 3429 value: className, |
| 3430 regexp: new RegExp('(^|\\s)' + escapeRegExp(className) + '(\\s|$)') |
| 3431 }; |
| 3432 }); |
| 3433 } |
| 3434 function convertPseudos(pseudos) { |
| 3435 if (!pseudos) { |
| 3436 return; |
| 3437 } |
| 3438 return pseudos.map(function(p) { |
| 3439 var expressions; |
| 3440 if (p.name === 'not') { |
| 3441 expressions = axe.utils.cssParser.parse(p.value); |
| 3442 expressions = expressions.selectors ? expressions.selectors : [ expressi
ons ]; |
| 3443 expressions = convertExpressions(expressions); |
| 3444 } |
| 3445 return { |
| 3446 name: p.name, |
| 3447 expressions: expressions, |
| 3448 value: p.value |
| 3449 }; |
| 3450 }); |
| 3451 } |
| 3452 convertExpressions = function convertExpressions(expressions) { |
| 3453 return expressions.map(function(exp) { |
| 3454 var newExp = []; |
| 3455 var rule = exp.rule; |
| 3456 while (rule) { |
| 3457 newExp.push({ |
| 3458 tag: rule.tagName ? rule.tagName.toLowerCase() : '*', |
| 3459 combinator: rule.nestingOperator ? rule.nestingOperator : ' ', |
| 3460 id: rule.id, |
| 3461 attributes: convertAttributes(rule.attrs), |
| 3462 classes: convertClasses(rule.classNames), |
| 3463 pseudos: convertPseudos(rule.pseudos) |
| 3464 }); |
| 3465 rule = rule.rule; |
| 3466 } |
| 3467 return newExp; |
| 3468 }); |
| 3469 }; |
| 3470 matchExpressions = function matchExpressions(domTree, expressions, recurse) { |
| 3471 return expressions.reduce(function(collected, exprArr) { |
| 3472 var candidates = domTree; |
| 3473 exprArr.forEach(function(exp, index) { |
| 3474 recurse = exp.combinator === '>' ? false : recurse; |
| 3475 if ([ ' ', '>' ].indexOf(exp.combinator) === -1) { |
| 3476 throw new Error('axe.utils.querySelectorAll does not support the combi
nator: ' + exp.combinator); |
| 3477 } |
| 3478 candidates = candidates.reduce(function(result, node) { |
| 3479 return result.concat(matchSelector(index ? node.children : node, exp,
recurse)); |
| 3480 }, []); |
| 3481 }); |
| 3482 return collected.concat(candidates); |
| 3483 }, []); |
| 3484 }; |
| 3485 axe.utils.querySelectorAll = function(domTree, selector) { |
| 3486 domTree = Array.isArray(domTree) ? domTree : [ domTree ]; |
| 3487 var expressions = axe.utils.cssParser.parse(selector); |
| 3488 expressions = expressions.selectors ? expressions.selectors : [ expressions
]; |
| 3489 expressions = convertExpressions(expressions); |
| 3490 return matchExpressions(domTree, expressions, true); |
| 3491 }; |
| 3492 'use strict'; |
| 3493 var _typeof = typeof Symbol === 'function' && typeof Symbol.iterator === 'symb
ol' ? function(obj) { |
| 3494 return typeof obj; |
| 3495 } : function(obj) { |
| 3496 return obj && typeof Symbol === 'function' && obj.constructor === Symbol &&
obj !== Symbol.prototype ? 'symbol' : typeof obj; |
| 3497 }; |
| 3498 (function() { |
| 3499 'use strict'; |
| 3500 function noop() {} |
| 3501 function funcGuard(f) { |
| 3502 if (typeof f !== 'function') { |
| 3503 throw new TypeError('Queue methods require functions as arguments'); |
| 3504 } |
| 3505 } |
| 3506 function queue() { |
| 3507 var tasks = []; |
| 3508 var started = 0; |
| 3509 var remaining = 0; |
| 3510 var completeQueue = noop; |
| 3511 var complete = false; |
| 3512 var err; |
| 3513 var defaultFail = function defaultFail(e) { |
| 3514 err = e; |
| 3515 setTimeout(function() { |
| 3516 if (err !== undefined && err !== null) { |
| 3517 axe.log('Uncaught error (of queue)', err); |
| 3518 } |
| 3519 }, 1); |
| 3520 }; |
| 3521 var failed = defaultFail; |
| 3522 function createResolve(i) { |
| 3523 return function(r) { |
| 3524 tasks[i] = r; |
| 3525 remaining -= 1; |
| 3526 if (!remaining && completeQueue !== noop) { |
| 3527 complete = true; |
| 3528 completeQueue(tasks); |
| 3529 } |
| 3530 }; |
| 3531 } |
| 3532 function abort(msg) { |
| 3533 completeQueue = noop; |
| 3534 failed(msg); |
| 3535 return tasks; |
| 3536 } |
| 3537 function pop() { |
| 3538 var length = tasks.length; |
| 3539 for (;started < length; started++) { |
| 3540 var task = tasks[started]; |
| 3541 try { |
| 3542 task.call(null, createResolve(started), abort); |
| 3543 } catch (e) { |
| 3544 abort(e); |
| 3545 } |
| 3546 } |
| 3547 } |
| 3548 var q = { |
| 3549 defer: function defer(fn) { |
| 3550 if ((typeof fn === 'undefined' ? 'undefined' : _typeof(fn)) === 'objec
t' && fn.then && fn.catch) { |
| 3551 var defer = fn; |
| 3552 fn = function fn(resolve, reject) { |
| 3553 defer.then(resolve).catch(reject); |
| 3554 }; |
| 3555 } |
| 3556 funcGuard(fn); |
| 3557 if (err !== undefined) { |
| 3558 return; |
| 3559 } else if (complete) { |
| 3560 throw new Error('Queue already completed'); |
| 3561 } |
| 3562 tasks.push(fn); |
| 3563 ++remaining; |
| 3564 pop(); |
| 3565 return q; |
| 3566 }, |
| 3567 then: function then(fn) { |
| 3568 funcGuard(fn); |
| 3569 if (completeQueue !== noop) { |
| 3570 throw new Error('queue `then` already set'); |
| 3571 } |
| 3572 if (!err) { |
| 3573 completeQueue = fn; |
| 3574 if (!remaining) { |
| 3575 complete = true; |
| 3576 completeQueue(tasks); |
| 3577 } |
| 3578 } |
| 3579 return q; |
| 3580 }, |
| 3581 catch: function _catch(fn) { |
| 3582 funcGuard(fn); |
| 3583 if (failed !== defaultFail) { |
| 3584 throw new Error('queue `catch` already set'); |
| 3585 } |
| 3586 if (!err) { |
| 3587 failed = fn; |
| 3588 } else { |
| 3589 fn(err); |
| 3590 err = null; |
| 3591 } |
| 3592 return q; |
| 3593 }, |
| 3594 abort: abort |
| 3595 }; |
| 3596 return q; |
| 3597 } |
| 3598 axe.utils.queue = queue; |
| 3599 })(); |
| 3600 'use strict'; |
| 3601 var _typeof = typeof Symbol === 'function' && typeof Symbol.iterator === 'symb
ol' ? function(obj) { |
| 3602 return typeof obj; |
| 3603 } : function(obj) { |
| 3604 return obj && typeof Symbol === 'function' && obj.constructor === Symbol &&
obj !== Symbol.prototype ? 'symbol' : typeof obj; |
| 3605 }; |
| 3606 (function(exports) { |
| 3607 'use strict'; |
| 3608 var messages = {}, subscribers = {}; |
| 3609 function _getSource() { |
| 3610 var application = 'axe', version = '', src; |
| 3611 if (typeof axe !== 'undefined' && axe._audit && !axe._audit.application) { |
| 3612 application = axe._audit.application; |
| 3613 } |
| 3614 if (typeof axe !== 'undefined') { |
| 3615 version = axe.version; |
| 3616 } |
| 3617 src = application + '.' + version; |
| 3618 return src; |
| 3619 } |
| 3620 function verify(postedMessage) { |
| 3621 if ((typeof postedMessage === 'undefined' ? 'undefined' : _typeof(postedMe
ssage)) === 'object' && typeof postedMessage.uuid === 'string' && postedMessage.
_respondable === true) { |
| 3622 var messageSource = _getSource(); |
| 3623 return postedMessage._source === messageSource || postedMessage._source
=== 'axe.x.y.z' || messageSource === 'axe.x.y.z'; |
| 3624 } |
| 3625 return false; |
| 3626 } |
| 3627 function post(win, topic, message, uuid, keepalive, callback) { |
| 3628 var error; |
| 3629 if (message instanceof Error) { |
| 3630 error = { |
| 3631 name: message.name, |
| 3632 message: message.message, |
| 3633 stack: message.stack |
| 3634 }; |
| 3635 message = undefined; |
| 3636 } |
| 3637 var data = { |
| 3638 uuid: uuid, |
| 3639 topic: topic, |
| 3640 message: message, |
| 3641 error: error, |
| 3642 _respondable: true, |
| 3643 _source: _getSource(), |
| 3644 _keepalive: keepalive |
| 3645 }; |
| 3646 if (typeof callback === 'function') { |
| 3647 messages[uuid] = callback; |
| 3648 } |
| 3649 win.postMessage(JSON.stringify(data), '*'); |
| 3650 } |
| 3651 function respondable(win, topic, message, keepalive, callback) { |
| 3652 var id = uuid.v1(); |
| 3653 post(win, topic, message, id, keepalive, callback); |
| 3654 } |
| 3655 respondable.subscribe = function(topic, callback) { |
| 3656 subscribers[topic] = callback; |
| 3657 }; |
| 3658 respondable.isInFrame = function(win) { |
| 3659 win = win || window; |
| 3660 return !!win.frameElement; |
| 3661 }; |
| 3662 function createResponder(source, topic, uuid) { |
| 3663 return function(message, keepalive, callback) { |
| 3664 post(source, topic, message, uuid, keepalive, callback); |
| 3665 }; |
| 3666 } |
| 3667 function publish(target, data, keepalive) { |
| 3668 var topic = data.topic; |
| 3669 var subscriber = subscribers[topic]; |
| 3670 if (subscriber) { |
| 3671 var responder = createResponder(target, null, data.uuid); |
| 3672 subscriber(data.message, keepalive, responder); |
| 3673 } |
| 3674 } |
| 3675 function buildErrorObject(error) { |
| 3676 var msg = error.message || 'Unknown error occurred'; |
| 3677 var ErrConstructor = window[error.name] || Error; |
| 3678 if (error.stack) { |
| 3679 msg += '\n' + error.stack.replace(error.message, ''); |
| 3680 } |
| 3681 return new ErrConstructor(msg); |
| 3682 } |
| 3683 function parseMessage(dataString) { |
| 3684 var data; |
| 3685 if (typeof dataString !== 'string') { |
| 3686 return; |
| 3687 } |
| 3688 try { |
| 3689 data = JSON.parse(dataString); |
| 3690 } catch (ex) {} |
| 3691 if (!verify(data)) { |
| 3692 return; |
| 3693 } |
| 3694 if (_typeof(data.error) === 'object') { |
| 3695 data.error = buildErrorObject(data.error); |
| 3696 } else { |
| 3697 data.error = undefined; |
| 3698 } |
| 3699 return data; |
| 3700 } |
| 3701 if (typeof window.addEventListener === 'function') { |
| 3702 window.addEventListener('message', function(e) { |
| 3703 var data = parseMessage(e.data); |
| 3704 if (!data) { |
| 3705 return; |
| 3706 } |
| 3707 var uuid = data.uuid; |
| 3708 var keepalive = data._keepalive; |
| 3709 var callback = messages[uuid]; |
| 3710 if (callback) { |
| 3711 var result = data.error || data.message; |
| 3712 var responder = createResponder(e.source, data.topic, uuid); |
| 3713 callback(result, keepalive, responder); |
| 3714 if (!keepalive) { |
| 3715 delete messages[uuid]; |
| 3716 } |
| 3717 } |
| 3718 if (!data.error) { |
| 3719 try { |
| 3720 publish(e.source, data, keepalive); |
| 3721 } catch (err) { |
| 3722 post(e.source, data.topic, err, uuid, false); |
| 3723 } |
| 3724 } |
| 3725 }, false); |
| 3726 } |
| 3727 exports.respondable = respondable; |
| 3728 })(utils); |
| 3729 'use strict'; |
| 3730 function matchTags(rule, runOnly) { |
| 3731 'use strict'; |
| 3732 var include, exclude, matching; |
| 3733 var defaultExclude = axe._audit && axe._audit.tagExclude ? axe._audit.tagExc
lude : []; |
| 3734 if (runOnly.include || runOnly.exclude) { |
| 3735 include = runOnly.include || []; |
| 3736 include = Array.isArray(include) ? include : [ include ]; |
| 3737 exclude = runOnly.exclude || []; |
| 3738 exclude = Array.isArray(exclude) ? exclude : [ exclude ]; |
| 3739 exclude = exclude.concat(defaultExclude.filter(function(tag) { |
| 3740 return include.indexOf(tag) === -1; |
| 3741 })); |
| 3742 } else { |
| 3743 include = Array.isArray(runOnly) ? runOnly : [ runOnly ]; |
| 3744 exclude = defaultExclude.filter(function(tag) { |
| 3745 return include.indexOf(tag) === -1; |
| 3746 }); |
| 3747 } |
| 3748 matching = include.some(function(tag) { |
| 3749 return rule.tags.indexOf(tag) !== -1; |
| 3750 }); |
| 3751 if (matching || include.length === 0 && rule.enabled !== false) { |
| 3752 return exclude.every(function(tag) { |
| 3753 return rule.tags.indexOf(tag) === -1; |
| 3754 }); |
| 3755 } else { |
| 3756 return false; |
| 3757 } |
| 3758 } |
| 3759 axe.utils.ruleShouldRun = function(rule, context, options) { |
| 3760 'use strict'; |
| 3761 var runOnly = options.runOnly || {}; |
| 3762 var ruleOptions = (options.rules || {})[rule.id]; |
| 3763 if (rule.pageLevel && !context.page) { |
| 3764 return false; |
| 3765 } else if (runOnly.type === 'rule') { |
| 3766 return runOnly.values.indexOf(rule.id) !== -1; |
| 3767 } else if (ruleOptions && typeof ruleOptions.enabled === 'boolean') { |
| 3768 return ruleOptions.enabled; |
| 3769 } else if (runOnly.type === 'tag' && runOnly.values) { |
| 3770 return matchTags(rule, runOnly.values); |
| 3771 } else { |
| 3772 return matchTags(rule, []); |
| 3773 } |
| 3774 }; |
| 3775 'use strict'; |
| 3776 function getDeepest(collection) { |
| 3777 'use strict'; |
| 3778 return collection.sort(function(a, b) { |
| 3779 if (axe.utils.contains(a, b)) { |
| 3780 return 1; |
| 3781 } |
| 3782 return -1; |
| 3783 })[0]; |
| 3784 } |
| 3785 function isNodeInContext(node, context) { |
| 3786 'use strict'; |
| 3787 var include = context.include && getDeepest(context.include.filter(function(
candidate) { |
| 3788 return axe.utils.contains(candidate, node); |
| 3789 })); |
| 3790 var exclude = context.exclude && getDeepest(context.exclude.filter(function(
candidate) { |
| 3791 return axe.utils.contains(candidate, node); |
| 3792 })); |
| 3793 if (!exclude && include || exclude && axe.utils.contains(exclude, include))
{ |
| 3794 return true; |
| 3795 } |
| 3796 return false; |
| 3797 } |
| 3798 function pushNode(result, nodes, context) { |
| 3799 'use strict'; |
| 3800 for (var i = 0, l = nodes.length; i < l; i++) { |
| 3801 if (!result.find(function(item) { |
| 3802 return item.actualNode === nodes[i].actualNode; |
| 3803 }) && isNodeInContext(nodes[i], context)) { |
| 3804 result.push(nodes[i]); |
| 3805 } |
| 3806 } |
| 3807 } |
| 3808 axe.utils.select = function select(selector, context) { |
| 3809 'use strict'; |
| 3810 var result = [], candidate; |
| 3811 for (var i = 0, l = context.include.length; i < l; i++) { |
| 3812 candidate = context.include[i]; |
| 3813 if (candidate.actualNode.nodeType === candidate.actualNode.ELEMENT_NODE &&
axe.utils.matchesSelector(candidate.actualNode, selector)) { |
| 3814 pushNode(result, [ candidate ], context); |
| 3815 } |
| 3816 pushNode(result, axe.utils.querySelectorAll(candidate, selector), context)
; |
| 3817 } |
| 3818 return result.sort(axe.utils.nodeSorter); |
| 3819 }; |
| 3820 'use strict'; |
| 3821 axe.utils.toArray = function(thing) { |
| 3822 'use strict'; |
| 3823 return Array.prototype.slice.call(thing); |
| 3824 }; |
| 3825 'use strict'; |
| 3826 var uuid; |
| 3827 (function(_global) { |
| 3828 var _rng; |
| 3829 var _crypto = _global.crypto || _global.msCrypto; |
| 3830 if (!_rng && _crypto && _crypto.getRandomValues) { |
| 3831 var _rnds8 = new Uint8Array(16); |
| 3832 _rng = function whatwgRNG() { |
| 3833 _crypto.getRandomValues(_rnds8); |
| 3834 return _rnds8; |
| 3835 }; |
| 3836 } |
| 3837 if (!_rng) { |
| 3838 var _rnds = new Array(16); |
| 3839 _rng = function _rng() { |
| 3840 for (var i = 0, r; i < 16; i++) { |
| 3841 if ((i & 3) === 0) { |
| 3842 r = Math.random() * 4294967296; |
| 3843 } |
| 3844 _rnds[i] = r >>> ((i & 3) << 3) & 255; |
| 3845 } |
| 3846 return _rnds; |
| 3847 }; |
| 3848 } |
| 3849 var BufferClass = typeof _global.Buffer == 'function' ? _global.Buffer : Arr
ay; |
| 3850 var _byteToHex = []; |
| 3851 var _hexToByte = {}; |
| 3852 for (var i = 0; i < 256; i++) { |
| 3853 _byteToHex[i] = (i + 256).toString(16).substr(1); |
| 3854 _hexToByte[_byteToHex[i]] = i; |
| 3855 } |
| 3856 function parse(s, buf, offset) { |
| 3857 var i = buf && offset || 0, ii = 0; |
| 3858 buf = buf || []; |
| 3859 s.toLowerCase().replace(/[0-9a-f]{2}/g, function(oct) { |
| 3860 if (ii < 16) { |
| 3861 buf[i + ii++] = _hexToByte[oct]; |
| 3862 } |
| 3863 }); |
| 3864 while (ii < 16) { |
| 3865 buf[i + ii++] = 0; |
| 3866 } |
| 3867 return buf; |
| 3868 } |
| 3869 function unparse(buf, offset) { |
| 3870 var i = offset || 0, bth = _byteToHex; |
| 3871 return bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + '-'
+ bth[buf[i++]] + bth[buf[i++]] + '-' + bth[buf[i++]] + bth[buf[i++]] + '-' + b
th[buf[i++]] + bth[buf[i++]] + '-' + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++
]] + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]]; |
| 3872 } |
| 3873 var _seedBytes = _rng(); |
| 3874 var _nodeId = [ _seedBytes[0] | 1, _seedBytes[1], _seedBytes[2], _seedBytes[
3], _seedBytes[4], _seedBytes[5] ]; |
| 3875 var _clockseq = (_seedBytes[6] << 8 | _seedBytes[7]) & 16383; |
| 3876 var _lastMSecs = 0, _lastNSecs = 0; |
| 3877 function v1(options, buf, offset) { |
| 3878 var i = buf && offset || 0; |
| 3879 var b = buf || []; |
| 3880 options = options || {}; |
| 3881 var clockseq = options.clockseq != null ? options.clockseq : _clockseq; |
| 3882 var msecs = options.msecs != null ? options.msecs : new Date().getTime(); |
| 3883 var nsecs = options.nsecs != null ? options.nsecs : _lastNSecs + 1; |
| 3884 var dt = msecs - _lastMSecs + (nsecs - _lastNSecs) / 1e4; |
| 3885 if (dt < 0 && options.clockseq == null) { |
| 3886 clockseq = clockseq + 1 & 16383; |
| 3887 } |
| 3888 if ((dt < 0 || msecs > _lastMSecs) && options.nsecs == null) { |
| 3889 nsecs = 0; |
| 3890 } |
| 3891 if (nsecs >= 1e4) { |
| 3892 throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec'); |
| 3893 } |
| 3894 _lastMSecs = msecs; |
| 3895 _lastNSecs = nsecs; |
| 3896 _clockseq = clockseq; |
| 3897 msecs += 122192928e5; |
| 3898 var tl = ((msecs & 268435455) * 1e4 + nsecs) % 4294967296; |
| 3899 b[i++] = tl >>> 24 & 255; |
| 3900 b[i++] = tl >>> 16 & 255; |
| 3901 b[i++] = tl >>> 8 & 255; |
| 3902 b[i++] = tl & 255; |
| 3903 var tmh = msecs / 4294967296 * 1e4 & 268435455; |
| 3904 b[i++] = tmh >>> 8 & 255; |
| 3905 b[i++] = tmh & 255; |
| 3906 b[i++] = tmh >>> 24 & 15 | 16; |
| 3907 b[i++] = tmh >>> 16 & 255; |
| 3908 b[i++] = clockseq >>> 8 | 128; |
| 3909 b[i++] = clockseq & 255; |
| 3910 var node = options.node || _nodeId; |
| 3911 for (var n = 0; n < 6; n++) { |
| 3912 b[i + n] = node[n]; |
| 3913 } |
| 3914 return buf ? buf : unparse(b); |
| 3915 } |
| 3916 function v4(options, buf, offset) { |
| 3917 var i = buf && offset || 0; |
| 3918 if (typeof options == 'string') { |
| 3919 buf = options == 'binary' ? new BufferClass(16) : null; |
| 3920 options = null; |
| 3921 } |
| 3922 options = options || {}; |
| 3923 var rnds = options.random || (options.rng || _rng)(); |
| 3924 rnds[6] = rnds[6] & 15 | 64; |
| 3925 rnds[8] = rnds[8] & 63 | 128; |
| 3926 if (buf) { |
| 3927 for (var ii = 0; ii < 16; ii++) { |
| 3928 buf[i + ii] = rnds[ii]; |
| 3929 } |
| 3930 } |
| 3931 return buf || unparse(rnds); |
| 3932 } |
| 3933 uuid = v4; |
| 3934 uuid.v1 = v1; |
| 3935 uuid.v4 = v4; |
| 3936 uuid.parse = parse; |
| 3937 uuid.unparse = unparse; |
| 3938 uuid.BufferClass = BufferClass; |
| 3939 })(window); |
| 3940 'use strict'; |
| 3941 axe._load({ |
| 3942 data: { |
| 3943 rules: { |
| 3944 accesskeys: { |
| 3945 description: 'Ensures every accesskey attribute value is unique', |
| 3946 help: 'accesskey attribute value must be unique' |
| 3947 }, |
| 3948 'area-alt': { |
| 3949 description: 'Ensures <area> elements of image maps have alternate tex
t', |
| 3950 help: 'Active <area> elements must have alternate text' |
| 3951 }, |
| 3952 'aria-allowed-attr': { |
| 3953 description: 'Ensures ARIA attributes are allowed for an element\'s ro
le', |
| 3954 help: 'Elements must only use allowed ARIA attributes' |
| 3955 }, |
| 3956 'aria-hidden-body': { |
| 3957 description: 'Ensures aria-hidden=\'true\' is not present on the docum
ent body.', |
| 3958 help: 'aria-hidden=\'true\' must not be present on the document body' |
| 3959 }, |
| 3960 'aria-required-attr': { |
| 3961 description: 'Ensures elements with ARIA roles have all required ARIA
attributes', |
| 3962 help: 'Required ARIA attributes must be provided' |
| 3963 }, |
| 3964 'aria-required-children': { |
| 3965 description: 'Ensures elements with an ARIA role that require child ro
les contain them', |
| 3966 help: 'Certain ARIA roles must contain particular children' |
| 3967 }, |
| 3968 'aria-required-parent': { |
| 3969 description: 'Ensures elements with an ARIA role that require parent r
oles are contained by them', |
| 3970 help: 'Certain ARIA roles must be contained by particular parents' |
| 3971 }, |
| 3972 'aria-roles': { |
| 3973 description: 'Ensures all elements with a role attribute use a valid v
alue', |
| 3974 help: 'ARIA roles used must conform to valid values' |
| 3975 }, |
| 3976 'aria-valid-attr-value': { |
| 3977 description: 'Ensures all ARIA attributes have valid values', |
| 3978 help: 'ARIA attributes must conform to valid values' |
| 3979 }, |
| 3980 'aria-valid-attr': { |
| 3981 description: 'Ensures attributes that begin with aria- are valid ARIA
attributes', |
| 3982 help: 'ARIA attributes must conform to valid names' |
| 3983 }, |
| 3984 'audio-caption': { |
| 3985 description: 'Ensures <audio> elements have captions', |
| 3986 help: '<audio> elements must have a captions track' |
| 3987 }, |
| 3988 blink: { |
| 3989 description: 'Ensures <blink> elements are not used', |
| 3990 help: '<blink> elements are deprecated and must not be used' |
| 3991 }, |
| 3992 'button-name': { |
| 3993 description: 'Ensures buttons have discernible text', |
| 3994 help: 'Buttons must have discernible text' |
| 3995 }, |
| 3996 bypass: { |
| 3997 description: 'Ensures each page has at least one mechanism for a user
to bypass navigation and jump straight to the content', |
| 3998 help: 'Page must have means to bypass repeated blocks' |
| 3999 }, |
| 4000 checkboxgroup: { |
| 4001 description: 'Ensures related <input type="checkbox"> elements have a
group and that that group designation is consistent', |
| 4002 help: 'Checkbox inputs with the same name attribute value must be part
of a group' |
| 4003 }, |
| 4004 'color-contrast': { |
| 4005 description: 'Ensures the contrast between foreground and background c
olors meets WCAG 2 AA contrast ratio thresholds', |
| 4006 help: 'Elements must have sufficient color contrast' |
| 4007 }, |
| 4008 'definition-list': { |
| 4009 description: 'Ensures <dl> elements are structured correctly', |
| 4010 help: '<dl> elements must only directly contain properly-ordered <dt>
and <dd> groups, <script> or <template> elements' |
| 4011 }, |
| 4012 dlitem: { |
| 4013 description: 'Ensures <dt> and <dd> elements are contained by a <dl>', |
| 4014 help: '<dt> and <dd> elements must be contained by a <dl>' |
| 4015 }, |
| 4016 'document-title': { |
| 4017 description: 'Ensures each HTML document contains a non-empty <title>
element', |
| 4018 help: 'Documents must have <title> element to aid in navigation' |
| 4019 }, |
| 4020 'duplicate-id': { |
| 4021 description: 'Ensures every id attribute value is unique', |
| 4022 help: 'id attribute value must be unique' |
| 4023 }, |
| 4024 'empty-heading': { |
| 4025 description: 'Ensures headings have discernible text', |
| 4026 help: 'Headings must not be empty' |
| 4027 }, |
| 4028 'frame-title-unique': { |
| 4029 description: 'Ensures <iframe> and <frame> elements contain a unique t
itle attribute', |
| 4030 help: 'Frames must have a unique title attribute' |
| 4031 }, |
| 4032 'frame-title': { |
| 4033 description: 'Ensures <iframe> and <frame> elements contain a non-empt
y title attribute', |
| 4034 help: 'Frames must have title attribute' |
| 4035 }, |
| 4036 'heading-order': { |
| 4037 description: 'Ensures the order of headings is semantically correct', |
| 4038 help: 'Heading levels should only increase by one' |
| 4039 }, |
| 4040 'hidden-content': { |
| 4041 description: 'Informs users about hidden content.', |
| 4042 help: 'Hidden content on the page cannot be analyzed' |
| 4043 }, |
| 4044 'href-no-hash': { |
| 4045 description: 'Ensures that href values are valid link references to pr
omote only using anchors as links', |
| 4046 help: 'Anchors must only be used as links with valid URLs or URL fragm
ents' |
| 4047 }, |
| 4048 'html-has-lang': { |
| 4049 description: 'Ensures every HTML document has a lang attribute', |
| 4050 help: '<html> element must have a lang attribute' |
| 4051 }, |
| 4052 'html-lang-valid': { |
| 4053 description: 'Ensures the lang attribute of the <html> element has a v
alid value', |
| 4054 help: '<html> element must have a valid value for the lang attribute' |
| 4055 }, |
| 4056 'image-alt': { |
| 4057 description: 'Ensures <img> elements have alternate text or a role of
none or presentation', |
| 4058 help: 'Images must have alternate text' |
| 4059 }, |
| 4060 'image-redundant-alt': { |
| 4061 description: 'Ensure button and link text is not repeated as image alt
ernative', |
| 4062 help: 'Text of buttons and links should not be repeated in the image a
lternative' |
| 4063 }, |
| 4064 'input-image-alt': { |
| 4065 description: 'Ensures <input type="image"> elements have alternate tex
t', |
| 4066 help: 'Image buttons must have alternate text' |
| 4067 }, |
| 4068 'label-title-only': { |
| 4069 description: 'Ensures that every form element is not solely labeled us
ing the title or aria-describedby attributes', |
| 4070 help: 'Form elements should have a visible label' |
| 4071 }, |
| 4072 label: { |
| 4073 description: 'Ensures every form element has a label', |
| 4074 help: 'Form elements must have labels' |
| 4075 }, |
| 4076 'layout-table': { |
| 4077 description: 'Ensures presentational <table> elements do not use <th>,
<caption> elements or the summary attribute', |
| 4078 help: 'Layout tables must not use data table elements' |
| 4079 }, |
| 4080 'link-in-text-block': { |
| 4081 description: 'Links can be distinguished without relying on color', |
| 4082 help: 'Links must be distinguished from surrounding text in a way that
does not rely on color' |
| 4083 }, |
| 4084 'link-name': { |
| 4085 description: 'Ensures links have discernible text', |
| 4086 help: 'Links must have discernible text' |
| 4087 }, |
| 4088 list: { |
| 4089 description: 'Ensures that lists are structured correctly', |
| 4090 help: '<ul> and <ol> must only directly contain <li>, <script> or <tem
plate> elements' |
| 4091 }, |
| 4092 listitem: { |
| 4093 description: 'Ensures <li> elements are used semantically', |
| 4094 help: '<li> elements must be contained in a <ul> or <ol>' |
| 4095 }, |
| 4096 marquee: { |
| 4097 description: 'Ensures <marquee> elements are not used', |
| 4098 help: '<marquee> elements are deprecated and must not be used' |
| 4099 }, |
| 4100 'meta-refresh': { |
| 4101 description: 'Ensures <meta http-equiv="refresh"> is not used', |
| 4102 help: 'Timed refresh must not exist' |
| 4103 }, |
| 4104 'meta-viewport-large': { |
| 4105 description: 'Ensures <meta name="viewport"> can scale a significant a
mount', |
| 4106 help: 'Users should be able to zoom and scale the text up to 500%' |
| 4107 }, |
| 4108 'meta-viewport': { |
| 4109 description: 'Ensures <meta name="viewport"> does not disable text sca
ling and zooming', |
| 4110 help: 'Zooming and scaling must not be disabled' |
| 4111 }, |
| 4112 'object-alt': { |
| 4113 description: 'Ensures <object> elements have alternate text', |
| 4114 help: '<object> elements must have alternate text' |
| 4115 }, |
| 4116 'p-as-heading': { |
| 4117 description: 'Ensure p elements are not used to style headings', |
| 4118 help: 'Bold, italic text and font-size are not used to style p element
s as a heading' |
| 4119 }, |
| 4120 radiogroup: { |
| 4121 description: 'Ensures related <input type="radio"> elements have a gro
up and that the group designation is consistent', |
| 4122 help: 'Radio inputs with the same name attribute value must be part of
a group' |
| 4123 }, |
| 4124 region: { |
| 4125 description: 'Ensures all content is contained within a landmark regio
n', |
| 4126 help: 'Content should be contained in a landmark region' |
| 4127 }, |
| 4128 'scope-attr-valid': { |
| 4129 description: 'Ensures the scope attribute is used correctly on tables'
, |
| 4130 help: 'scope attribute should be used correctly' |
| 4131 }, |
| 4132 'server-side-image-map': { |
| 4133 description: 'Ensures that server-side image maps are not used', |
| 4134 help: 'Server-side image maps must not be used' |
| 4135 }, |
| 4136 'skip-link': { |
| 4137 description: 'Ensures the first link on the page is a skip link', |
| 4138 help: 'The page should have a skip link as its first link' |
| 4139 }, |
| 4140 tabindex: { |
| 4141 description: 'Ensures tabindex attribute values are not greater than 0
', |
| 4142 help: 'Elements should not have tabindex greater than zero' |
| 4143 }, |
| 4144 'table-duplicate-name': { |
| 4145 description: 'Ensure that tables do not have the same summary and capt
ion', |
| 4146 help: 'The <caption> element should not contain the same text as the s
ummary attribute' |
| 4147 }, |
| 4148 'table-fake-caption': { |
| 4149 description: 'Ensure that tables with a caption use the <caption> elem
ent.', |
| 4150 help: 'Data or header cells should not be used to give caption to a da
ta table.' |
| 4151 }, |
| 4152 'td-has-header': { |
| 4153 description: 'Ensure that each non-empty data cell in a large table ha
s one or more table headers', |
| 4154 help: 'All non-empty td element in table larger than 3 by 3 must have
an associated table header' |
| 4155 }, |
| 4156 'td-headers-attr': { |
| 4157 description: 'Ensure that each cell in a table using the headers refer
s to another cell in that table', |
| 4158 help: 'All cells in a table element that use the headers attribute mus
t only refer to other cells of that same table' |
| 4159 }, |
| 4160 'th-has-data-cells': { |
| 4161 description: 'Ensure that each table header in a data table refers to
data cells', |
| 4162 help: 'All th element and elements with role=columnheader/rowheader mu
st data cells which it describes' |
| 4163 }, |
| 4164 'valid-lang': { |
| 4165 description: 'Ensures lang attributes have valid values', |
| 4166 help: 'lang attribute must have a valid value' |
| 4167 }, |
| 4168 'video-caption': { |
| 4169 description: 'Ensures <video> elements have captions', |
| 4170 help: '<video> elements must have captions' |
| 4171 }, |
| 4172 'video-description': { |
| 4173 description: 'Ensures <video> elements have audio descriptions', |
| 4174 help: '<video> elements must have an audio description track' |
| 4175 } |
| 4176 }, |
| 4177 checks: { |
| 4178 accesskeys: { |
| 4179 impact: 'critical', |
| 4180 messages: { |
| 4181 pass: function anonymous(it) { |
| 4182 var out = 'Accesskey attribute value is unique'; |
| 4183 return out; |
| 4184 }, |
| 4185 fail: function anonymous(it) { |
| 4186 var out = 'Document has multiple elements with the same accesskey'
; |
| 4187 return out; |
| 4188 } |
| 4189 } |
| 4190 }, |
| 4191 'non-empty-alt': { |
| 4192 impact: 'critical', |
| 4193 messages: { |
| 4194 pass: function anonymous(it) { |
| 4195 var out = 'Element has a non-empty alt attribute'; |
| 4196 return out; |
| 4197 }, |
| 4198 fail: function anonymous(it) { |
| 4199 var out = 'Element has no alt attribute or the alt attribute is em
pty'; |
| 4200 return out; |
| 4201 } |
| 4202 } |
| 4203 }, |
| 4204 'non-empty-title': { |
| 4205 impact: 'critical', |
| 4206 messages: { |
| 4207 pass: function anonymous(it) { |
| 4208 var out = 'Element has a title attribute'; |
| 4209 return out; |
| 4210 }, |
| 4211 fail: function anonymous(it) { |
| 4212 var out = 'Element has no title attribute or the title attribute i
s empty'; |
| 4213 return out; |
| 4214 } |
| 4215 } |
| 4216 }, |
| 4217 'aria-label': { |
| 4218 impact: 'critical', |
| 4219 messages: { |
| 4220 pass: function anonymous(it) { |
| 4221 var out = 'aria-label attribute exists and is not empty'; |
| 4222 return out; |
| 4223 }, |
| 4224 fail: function anonymous(it) { |
| 4225 var out = 'aria-label attribute does not exist or is empty'; |
| 4226 return out; |
| 4227 } |
| 4228 } |
| 4229 }, |
| 4230 'aria-labelledby': { |
| 4231 impact: 'critical', |
| 4232 messages: { |
| 4233 pass: function anonymous(it) { |
| 4234 var out = 'aria-labelledby attribute exists and references element
s that are visible to screen readers'; |
| 4235 return out; |
| 4236 }, |
| 4237 fail: function anonymous(it) { |
| 4238 var out = 'aria-labelledby attribute does not exist, references el
ements that do not exist or references elements that are empty or not visible'; |
| 4239 return out; |
| 4240 } |
| 4241 } |
| 4242 }, |
| 4243 'aria-allowed-attr': { |
| 4244 impact: 'critical', |
| 4245 messages: { |
| 4246 pass: function anonymous(it) { |
| 4247 var out = 'ARIA attributes are used correctly for the defined role
'; |
| 4248 return out; |
| 4249 }, |
| 4250 fail: function anonymous(it) { |
| 4251 var out = 'ARIA attribute' + (it.data && it.data.length > 1 ? 's a
re' : ' is') + ' not allowed:'; |
| 4252 var arr1 = it.data; |
| 4253 if (arr1) { |
| 4254 var value, i1 = -1, l1 = arr1.length - 1; |
| 4255 while (i1 < l1) { |
| 4256 value = arr1[i1 += 1]; |
| 4257 out += ' ' + value; |
| 4258 } |
| 4259 } |
| 4260 return out; |
| 4261 } |
| 4262 } |
| 4263 }, |
| 4264 'aria-hidden-body': { |
| 4265 impact: 'critical', |
| 4266 messages: { |
| 4267 pass: function anonymous(it) { |
| 4268 var out = 'No aria-hidden attribute is present on document body'; |
| 4269 return out; |
| 4270 }, |
| 4271 fail: function anonymous(it) { |
| 4272 var out = 'aria-hidden=true should not be present on the document
body'; |
| 4273 return out; |
| 4274 } |
| 4275 } |
| 4276 }, |
| 4277 'aria-required-attr': { |
| 4278 impact: 'critical', |
| 4279 messages: { |
| 4280 pass: function anonymous(it) { |
| 4281 var out = 'All required ARIA attributes are present'; |
| 4282 return out; |
| 4283 }, |
| 4284 fail: function anonymous(it) { |
| 4285 var out = 'Required ARIA attribute' + (it.data && it.data.length >
1 ? 's' : '') + ' not present:'; |
| 4286 var arr1 = it.data; |
| 4287 if (arr1) { |
| 4288 var value, i1 = -1, l1 = arr1.length - 1; |
| 4289 while (i1 < l1) { |
| 4290 value = arr1[i1 += 1]; |
| 4291 out += ' ' + value; |
| 4292 } |
| 4293 } |
| 4294 return out; |
| 4295 } |
| 4296 } |
| 4297 }, |
| 4298 'aria-required-children': { |
| 4299 impact: 'critical', |
| 4300 messages: { |
| 4301 pass: function anonymous(it) { |
| 4302 var out = 'Required ARIA children are present'; |
| 4303 return out; |
| 4304 }, |
| 4305 fail: function anonymous(it) { |
| 4306 var out = 'Required ARIA ' + (it.data && it.data.length > 1 ? 'chi
ldren' : 'child') + ' role not present:'; |
| 4307 var arr1 = it.data; |
| 4308 if (arr1) { |
| 4309 var value, i1 = -1, l1 = arr1.length - 1; |
| 4310 while (i1 < l1) { |
| 4311 value = arr1[i1 += 1]; |
| 4312 out += ' ' + value; |
| 4313 } |
| 4314 } |
| 4315 return out; |
| 4316 } |
| 4317 } |
| 4318 }, |
| 4319 'aria-required-parent': { |
| 4320 impact: 'critical', |
| 4321 messages: { |
| 4322 pass: function anonymous(it) { |
| 4323 var out = 'Required ARIA parent role present'; |
| 4324 return out; |
| 4325 }, |
| 4326 fail: function anonymous(it) { |
| 4327 var out = 'Required ARIA parent' + (it.data && it.data.length > 1
? 's' : '') + ' role not present:'; |
| 4328 var arr1 = it.data; |
| 4329 if (arr1) { |
| 4330 var value, i1 = -1, l1 = arr1.length - 1; |
| 4331 while (i1 < l1) { |
| 4332 value = arr1[i1 += 1]; |
| 4333 out += ' ' + value; |
| 4334 } |
| 4335 } |
| 4336 return out; |
| 4337 } |
| 4338 } |
| 4339 }, |
| 4340 invalidrole: { |
| 4341 impact: 'critical', |
| 4342 messages: { |
| 4343 pass: function anonymous(it) { |
| 4344 var out = 'ARIA role is valid'; |
| 4345 return out; |
| 4346 }, |
| 4347 fail: function anonymous(it) { |
| 4348 var out = 'Role must be one of the valid ARIA roles'; |
| 4349 return out; |
| 4350 } |
| 4351 } |
| 4352 }, |
| 4353 abstractrole: { |
| 4354 impact: 'serious', |
| 4355 messages: { |
| 4356 pass: function anonymous(it) { |
| 4357 var out = 'Abstract roles are not used'; |
| 4358 return out; |
| 4359 }, |
| 4360 fail: function anonymous(it) { |
| 4361 var out = 'Abstract roles cannot be directly used'; |
| 4362 return out; |
| 4363 } |
| 4364 } |
| 4365 }, |
| 4366 'aria-valid-attr-value': { |
| 4367 impact: 'critical', |
| 4368 messages: { |
| 4369 pass: function anonymous(it) { |
| 4370 var out = 'ARIA attribute values are valid'; |
| 4371 return out; |
| 4372 }, |
| 4373 fail: function anonymous(it) { |
| 4374 var out = 'Invalid ARIA attribute value' + (it.data && it.data.len
gth > 1 ? 's' : '') + ':'; |
| 4375 var arr1 = it.data; |
| 4376 if (arr1) { |
| 4377 var value, i1 = -1, l1 = arr1.length - 1; |
| 4378 while (i1 < l1) { |
| 4379 value = arr1[i1 += 1]; |
| 4380 out += ' ' + value; |
| 4381 } |
| 4382 } |
| 4383 return out; |
| 4384 } |
| 4385 } |
| 4386 }, |
| 4387 'aria-valid-attr': { |
| 4388 impact: 'critical', |
| 4389 messages: { |
| 4390 pass: function anonymous(it) { |
| 4391 var out = 'ARIA attribute name' + (it.data && it.data.length > 1 ?
's' : '') + ' are valid'; |
| 4392 return out; |
| 4393 }, |
| 4394 fail: function anonymous(it) { |
| 4395 var out = 'Invalid ARIA attribute name' + (it.data && it.data.leng
th > 1 ? 's' : '') + ':'; |
| 4396 var arr1 = it.data; |
| 4397 if (arr1) { |
| 4398 var value, i1 = -1, l1 = arr1.length - 1; |
| 4399 while (i1 < l1) { |
| 4400 value = arr1[i1 += 1]; |
| 4401 out += ' ' + value; |
| 4402 } |
| 4403 } |
| 4404 return out; |
| 4405 } |
| 4406 } |
| 4407 }, |
| 4408 caption: { |
| 4409 impact: 'critical', |
| 4410 messages: { |
| 4411 pass: function anonymous(it) { |
| 4412 var out = 'The multimedia element has a captions track'; |
| 4413 return out; |
| 4414 }, |
| 4415 fail: function anonymous(it) { |
| 4416 var out = 'The multimedia element does not have a captions track'; |
| 4417 return out; |
| 4418 }, |
| 4419 incomplete: function anonymous(it) { |
| 4420 var out = 'A captions track for this element could not be found'; |
| 4421 return out; |
| 4422 } |
| 4423 } |
| 4424 }, |
| 4425 'is-on-screen': { |
| 4426 impact: 'minor', |
| 4427 messages: { |
| 4428 pass: function anonymous(it) { |
| 4429 var out = 'Element is not visible'; |
| 4430 return out; |
| 4431 }, |
| 4432 fail: function anonymous(it) { |
| 4433 var out = 'Element is visible'; |
| 4434 return out; |
| 4435 } |
| 4436 } |
| 4437 }, |
| 4438 'non-empty-if-present': { |
| 4439 impact: 'critical', |
| 4440 messages: { |
| 4441 pass: function anonymous(it) { |
| 4442 var out = 'Element '; |
| 4443 if (it.data) { |
| 4444 out += 'has a non-empty value attribute'; |
| 4445 } else { |
| 4446 out += 'does not have a value attribute'; |
| 4447 } |
| 4448 return out; |
| 4449 }, |
| 4450 fail: function anonymous(it) { |
| 4451 var out = 'Element has a value attribute and the value attribute i
s empty'; |
| 4452 return out; |
| 4453 } |
| 4454 } |
| 4455 }, |
| 4456 'non-empty-value': { |
| 4457 impact: 'critical', |
| 4458 messages: { |
| 4459 pass: function anonymous(it) { |
| 4460 var out = 'Element has a non-empty value attribute'; |
| 4461 return out; |
| 4462 }, |
| 4463 fail: function anonymous(it) { |
| 4464 var out = 'Element has no value attribute or the value attribute i
s empty'; |
| 4465 return out; |
| 4466 } |
| 4467 } |
| 4468 }, |
| 4469 'button-has-visible-text': { |
| 4470 impact: 'critical', |
| 4471 messages: { |
| 4472 pass: function anonymous(it) { |
| 4473 var out = 'Element has inner text that is visible to screen reader
s'; |
| 4474 return out; |
| 4475 }, |
| 4476 fail: function anonymous(it) { |
| 4477 var out = 'Element does not have inner text that is visible to scr
een readers'; |
| 4478 return out; |
| 4479 } |
| 4480 } |
| 4481 }, |
| 4482 'role-presentation': { |
| 4483 impact: 'moderate', |
| 4484 messages: { |
| 4485 pass: function anonymous(it) { |
| 4486 var out = 'Element\'s default semantics were overriden with role="
presentation"'; |
| 4487 return out; |
| 4488 }, |
| 4489 fail: function anonymous(it) { |
| 4490 var out = 'Element\'s default semantics were not overridden with r
ole="presentation"'; |
| 4491 return out; |
| 4492 } |
| 4493 } |
| 4494 }, |
| 4495 'role-none': { |
| 4496 impact: 'moderate', |
| 4497 messages: { |
| 4498 pass: function anonymous(it) { |
| 4499 var out = 'Element\'s default semantics were overriden with role="
none"'; |
| 4500 return out; |
| 4501 }, |
| 4502 fail: function anonymous(it) { |
| 4503 var out = 'Element\'s default semantics were not overridden with r
ole="none"'; |
| 4504 return out; |
| 4505 } |
| 4506 } |
| 4507 }, |
| 4508 'focusable-no-name': { |
| 4509 impact: 'serious', |
| 4510 messages: { |
| 4511 pass: function anonymous(it) { |
| 4512 var out = 'Element is not in tab order or has accessible text'; |
| 4513 return out; |
| 4514 }, |
| 4515 fail: function anonymous(it) { |
| 4516 var out = 'Element is in tab order and does not have accessible te
xt'; |
| 4517 return out; |
| 4518 } |
| 4519 } |
| 4520 }, |
| 4521 'internal-link-present': { |
| 4522 impact: 'critical', |
| 4523 messages: { |
| 4524 pass: function anonymous(it) { |
| 4525 var out = 'Valid skip link found'; |
| 4526 return out; |
| 4527 }, |
| 4528 fail: function anonymous(it) { |
| 4529 var out = 'No valid skip link found'; |
| 4530 return out; |
| 4531 } |
| 4532 } |
| 4533 }, |
| 4534 'header-present': { |
| 4535 impact: 'moderate', |
| 4536 messages: { |
| 4537 pass: function anonymous(it) { |
| 4538 var out = 'Page has a header'; |
| 4539 return out; |
| 4540 }, |
| 4541 fail: function anonymous(it) { |
| 4542 var out = 'Page does not have a header'; |
| 4543 return out; |
| 4544 } |
| 4545 } |
| 4546 }, |
| 4547 landmark: { |
| 4548 impact: 'serious', |
| 4549 messages: { |
| 4550 pass: function anonymous(it) { |
| 4551 var out = 'Page has a landmark region'; |
| 4552 return out; |
| 4553 }, |
| 4554 fail: function anonymous(it) { |
| 4555 var out = 'Page does not have a landmark region'; |
| 4556 return out; |
| 4557 } |
| 4558 } |
| 4559 }, |
| 4560 'group-labelledby': { |
| 4561 impact: 'critical', |
| 4562 messages: { |
| 4563 pass: function anonymous(it) { |
| 4564 var out = 'All elements with the name "' + it.data.name + '" refer
ence the same element with aria-labelledby'; |
| 4565 return out; |
| 4566 }, |
| 4567 fail: function anonymous(it) { |
| 4568 var out = 'All elements with the name "' + it.data.name + '" do no
t reference the same element with aria-labelledby'; |
| 4569 return out; |
| 4570 } |
| 4571 } |
| 4572 }, |
| 4573 fieldset: { |
| 4574 impact: 'critical', |
| 4575 messages: { |
| 4576 pass: function anonymous(it) { |
| 4577 var out = 'Element is contained in a fieldset'; |
| 4578 return out; |
| 4579 }, |
| 4580 fail: function anonymous(it) { |
| 4581 var out = ''; |
| 4582 var code = it.data && it.data.failureCode; |
| 4583 if (code === 'no-legend') { |
| 4584 out += 'Fieldset does not have a legend as its first child'; |
| 4585 } else if (code === 'empty-legend') { |
| 4586 out += 'Legend does not have text that is visible to screen read
ers'; |
| 4587 } else if (code === 'mixed-inputs') { |
| 4588 out += 'Fieldset contains unrelated inputs'; |
| 4589 } else if (code === 'no-group-label') { |
| 4590 out += 'ARIA group does not have aria-label or aria-labelledby'; |
| 4591 } else if (code === 'group-mixed-inputs') { |
| 4592 out += 'ARIA group contains unrelated inputs'; |
| 4593 } else { |
| 4594 out += 'Element does not have a containing fieldset or ARIA grou
p'; |
| 4595 } |
| 4596 return out; |
| 4597 } |
| 4598 } |
| 4599 }, |
| 4600 'color-contrast': { |
| 4601 impact: 'serious', |
| 4602 messages: { |
| 4603 pass: function anonymous(it) { |
| 4604 var out = 'Element has sufficient color contrast of ' + it.data.co
ntrastRatio; |
| 4605 return out; |
| 4606 }, |
| 4607 fail: function anonymous(it) { |
| 4608 var out = 'Element has insufficient color contrast of ' + it.data.
contrastRatio + ' (foreground color: ' + it.data.fgColor + ', background color:
' + it.data.bgColor + ', font size: ' + it.data.fontSize + ', font weight: ' + i
t.data.fontWeight + ')'; |
| 4609 return out; |
| 4610 }, |
| 4611 incomplete: { |
| 4612 bgImage: 'Element\'s background color could not be determined due
to a background image', |
| 4613 bgGradient: 'Element\'s background color could not be determined d
ue to a background gradient', |
| 4614 imgNode: 'Element\'s background color could not be determined beca
use element contains an image node', |
| 4615 bgOverlap: 'Element\'s background color could not be determined be
cause it is overlapped by another element', |
| 4616 fgAlpha: 'Element\'s foreground color could not be determined beca
use of alpha transparency', |
| 4617 elmPartiallyObscured: 'Element\'s background color could not be de
termined because it\'s partially obscured by another element', |
| 4618 equalRatio: 'Element has a 1:1 contrast ratio with the background'
, |
| 4619 default: 'Unable to determine contrast ratio' |
| 4620 } |
| 4621 } |
| 4622 }, |
| 4623 'structured-dlitems': { |
| 4624 impact: 'serious', |
| 4625 messages: { |
| 4626 pass: function anonymous(it) { |
| 4627 var out = 'When not empty, element has both <dt> and <dd> elements
'; |
| 4628 return out; |
| 4629 }, |
| 4630 fail: function anonymous(it) { |
| 4631 var out = 'When not empty, element does not have at least one <dt>
element followed by at least one <dd> element'; |
| 4632 return out; |
| 4633 } |
| 4634 } |
| 4635 }, |
| 4636 'only-dlitems': { |
| 4637 impact: 'serious', |
| 4638 messages: { |
| 4639 pass: function anonymous(it) { |
| 4640 var out = 'List element only has direct children that are allowed
inside <dt> or <dd> elements'; |
| 4641 return out; |
| 4642 }, |
| 4643 fail: function anonymous(it) { |
| 4644 var out = 'List element has direct children that are not allowed i
nside <dt> or <dd> elements'; |
| 4645 return out; |
| 4646 } |
| 4647 } |
| 4648 }, |
| 4649 dlitem: { |
| 4650 impact: 'serious', |
| 4651 messages: { |
| 4652 pass: function anonymous(it) { |
| 4653 var out = 'Description list item has a <dl> parent element'; |
| 4654 return out; |
| 4655 }, |
| 4656 fail: function anonymous(it) { |
| 4657 var out = 'Description list item does not have a <dl> parent eleme
nt'; |
| 4658 return out; |
| 4659 } |
| 4660 } |
| 4661 }, |
| 4662 'doc-has-title': { |
| 4663 impact: 'moderate', |
| 4664 messages: { |
| 4665 pass: function anonymous(it) { |
| 4666 var out = 'Document has a non-empty <title> element'; |
| 4667 return out; |
| 4668 }, |
| 4669 fail: function anonymous(it) { |
| 4670 var out = 'Document does not have a non-empty <title> element'; |
| 4671 return out; |
| 4672 } |
| 4673 } |
| 4674 }, |
| 4675 'duplicate-id': { |
| 4676 impact: 'moderate', |
| 4677 messages: { |
| 4678 pass: function anonymous(it) { |
| 4679 var out = 'Document has no elements that share the same id attribu
te'; |
| 4680 return out; |
| 4681 }, |
| 4682 fail: function anonymous(it) { |
| 4683 var out = 'Document has multiple elements with the same id attribu
te: ' + it.data; |
| 4684 return out; |
| 4685 } |
| 4686 } |
| 4687 }, |
| 4688 'has-visible-text': { |
| 4689 impact: 'moderate', |
| 4690 messages: { |
| 4691 pass: function anonymous(it) { |
| 4692 var out = 'Element has text that is visible to screen readers'; |
| 4693 return out; |
| 4694 }, |
| 4695 fail: function anonymous(it) { |
| 4696 var out = 'Element does not have text that is visible to screen re
aders'; |
| 4697 return out; |
| 4698 } |
| 4699 } |
| 4700 }, |
| 4701 'unique-frame-title': { |
| 4702 impact: 'serious', |
| 4703 messages: { |
| 4704 pass: function anonymous(it) { |
| 4705 var out = 'Element\'s title attribute is unique'; |
| 4706 return out; |
| 4707 }, |
| 4708 fail: function anonymous(it) { |
| 4709 var out = 'Element\'s title attribute is not unique'; |
| 4710 return out; |
| 4711 } |
| 4712 } |
| 4713 }, |
| 4714 'heading-order': { |
| 4715 impact: 'minor', |
| 4716 messages: { |
| 4717 pass: function anonymous(it) { |
| 4718 var out = 'Heading order valid'; |
| 4719 return out; |
| 4720 }, |
| 4721 fail: function anonymous(it) { |
| 4722 var out = 'Heading order invalid'; |
| 4723 return out; |
| 4724 } |
| 4725 } |
| 4726 }, |
| 4727 'hidden-content': { |
| 4728 impact: 'minor', |
| 4729 messages: { |
| 4730 pass: function anonymous(it) { |
| 4731 var out = 'All content on the page has been analyzed.'; |
| 4732 return out; |
| 4733 }, |
| 4734 fail: function anonymous(it) { |
| 4735 var out = 'There were problems analyzing the content on this page.
'; |
| 4736 return out; |
| 4737 }, |
| 4738 incomplete: function anonymous(it) { |
| 4739 var out = 'There is hidden content on the page that was not analyz
ed. You will need to trigger the display of this content in order to analyze it.
'; |
| 4740 return out; |
| 4741 } |
| 4742 } |
| 4743 }, |
| 4744 'href-no-hash': { |
| 4745 impact: 'moderate', |
| 4746 messages: { |
| 4747 pass: function anonymous(it) { |
| 4748 var out = 'Anchor does not have an href value of #'; |
| 4749 return out; |
| 4750 }, |
| 4751 fail: function anonymous(it) { |
| 4752 var out = 'Anchor has an href value of #'; |
| 4753 return out; |
| 4754 } |
| 4755 } |
| 4756 }, |
| 4757 'has-lang': { |
| 4758 impact: 'serious', |
| 4759 messages: { |
| 4760 pass: function anonymous(it) { |
| 4761 var out = 'The <html> element has a lang attribute'; |
| 4762 return out; |
| 4763 }, |
| 4764 fail: function anonymous(it) { |
| 4765 var out = 'The <html> element does not have a lang attribute'; |
| 4766 return out; |
| 4767 } |
| 4768 } |
| 4769 }, |
| 4770 'valid-lang': { |
| 4771 impact: 'serious', |
| 4772 messages: { |
| 4773 pass: function anonymous(it) { |
| 4774 var out = 'Value of lang attribute is included in the list of vali
d languages'; |
| 4775 return out; |
| 4776 }, |
| 4777 fail: function anonymous(it) { |
| 4778 var out = 'Value of lang attribute not included in the list of val
id languages'; |
| 4779 return out; |
| 4780 } |
| 4781 } |
| 4782 }, |
| 4783 'has-alt': { |
| 4784 impact: 'critical', |
| 4785 messages: { |
| 4786 pass: function anonymous(it) { |
| 4787 var out = 'Element has an alt attribute'; |
| 4788 return out; |
| 4789 }, |
| 4790 fail: function anonymous(it) { |
| 4791 var out = 'Element does not have an alt attribute'; |
| 4792 return out; |
| 4793 } |
| 4794 } |
| 4795 }, |
| 4796 'duplicate-img-label': { |
| 4797 impact: 'minor', |
| 4798 messages: { |
| 4799 pass: function anonymous(it) { |
| 4800 var out = 'Element does not duplicate existing text in <img> alt t
ext'; |
| 4801 return out; |
| 4802 }, |
| 4803 fail: function anonymous(it) { |
| 4804 var out = 'Element contains <img> element with alt text that dupli
cates existing text'; |
| 4805 return out; |
| 4806 } |
| 4807 } |
| 4808 }, |
| 4809 'title-only': { |
| 4810 impact: 'serious', |
| 4811 messages: { |
| 4812 pass: function anonymous(it) { |
| 4813 var out = 'Form element does not solely use title attribute for it
s label'; |
| 4814 return out; |
| 4815 }, |
| 4816 fail: function anonymous(it) { |
| 4817 var out = 'Only title used to generate label for form element'; |
| 4818 return out; |
| 4819 } |
| 4820 } |
| 4821 }, |
| 4822 'implicit-label': { |
| 4823 impact: 'critical', |
| 4824 messages: { |
| 4825 pass: function anonymous(it) { |
| 4826 var out = 'Form element has an implicit (wrapped) <label>'; |
| 4827 return out; |
| 4828 }, |
| 4829 fail: function anonymous(it) { |
| 4830 var out = 'Form element does not have an implicit (wrapped) <label
>'; |
| 4831 return out; |
| 4832 } |
| 4833 } |
| 4834 }, |
| 4835 'explicit-label': { |
| 4836 impact: 'critical', |
| 4837 messages: { |
| 4838 pass: function anonymous(it) { |
| 4839 var out = 'Form element has an explicit <label>'; |
| 4840 return out; |
| 4841 }, |
| 4842 fail: function anonymous(it) { |
| 4843 var out = 'Form element does not have an explicit <label>'; |
| 4844 return out; |
| 4845 } |
| 4846 } |
| 4847 }, |
| 4848 'help-same-as-label': { |
| 4849 impact: 'minor', |
| 4850 messages: { |
| 4851 pass: function anonymous(it) { |
| 4852 var out = 'Help text (title or aria-describedby) does not duplicat
e label text'; |
| 4853 return out; |
| 4854 }, |
| 4855 fail: function anonymous(it) { |
| 4856 var out = 'Help text (title or aria-describedby) text is the same
as the label text'; |
| 4857 return out; |
| 4858 } |
| 4859 } |
| 4860 }, |
| 4861 'multiple-label': { |
| 4862 impact: 'serious', |
| 4863 messages: { |
| 4864 pass: function anonymous(it) { |
| 4865 var out = 'Form element does not have multiple <label> elements'; |
| 4866 return out; |
| 4867 }, |
| 4868 fail: function anonymous(it) { |
| 4869 var out = 'Form element has multiple <label> elements'; |
| 4870 return out; |
| 4871 } |
| 4872 } |
| 4873 }, |
| 4874 'has-th': { |
| 4875 impact: 'serious', |
| 4876 messages: { |
| 4877 pass: function anonymous(it) { |
| 4878 var out = 'Layout table does not use <th> elements'; |
| 4879 return out; |
| 4880 }, |
| 4881 fail: function anonymous(it) { |
| 4882 var out = 'Layout table uses <th> elements'; |
| 4883 return out; |
| 4884 } |
| 4885 } |
| 4886 }, |
| 4887 'has-caption': { |
| 4888 impact: 'serious', |
| 4889 messages: { |
| 4890 pass: function anonymous(it) { |
| 4891 var out = 'Layout table does not use <caption> element'; |
| 4892 return out; |
| 4893 }, |
| 4894 fail: function anonymous(it) { |
| 4895 var out = 'Layout table uses <caption> element'; |
| 4896 return out; |
| 4897 } |
| 4898 } |
| 4899 }, |
| 4900 'has-summary': { |
| 4901 impact: 'serious', |
| 4902 messages: { |
| 4903 pass: function anonymous(it) { |
| 4904 var out = 'Layout table does not use summary attribute'; |
| 4905 return out; |
| 4906 }, |
| 4907 fail: function anonymous(it) { |
| 4908 var out = 'Layout table uses summary attribute'; |
| 4909 return out; |
| 4910 } |
| 4911 } |
| 4912 }, |
| 4913 'link-in-text-block': { |
| 4914 impact: 'critical', |
| 4915 messages: { |
| 4916 pass: function anonymous(it) { |
| 4917 var out = 'Links can be distinguished from surrounding text in a w
ay that does not rely on color'; |
| 4918 return out; |
| 4919 }, |
| 4920 fail: function anonymous(it) { |
| 4921 var out = 'Links can not be distinguished from surrounding text in
a way that does not rely on color'; |
| 4922 return out; |
| 4923 }, |
| 4924 incomplete: { |
| 4925 bgContrast: 'Element\'s contrast ratio could not be determined. Ch
eck for a distinct hover/focus style', |
| 4926 bgImage: 'Element\'s contrast ratio could not be determined due to
a background image', |
| 4927 bgGradient: 'Element\'s contrast ratio could not be determined due
to a background gradient', |
| 4928 imgNode: 'Element\'s contrast ratio could not be determined becaus
e element contains an image node', |
| 4929 bgOverlap: 'Element\'s contrast ratio could not be determined beca
use of element overlap', |
| 4930 default: 'Unable to determine contrast ratio' |
| 4931 } |
| 4932 } |
| 4933 }, |
| 4934 'only-listitems': { |
| 4935 impact: 'serious', |
| 4936 messages: { |
| 4937 pass: function anonymous(it) { |
| 4938 var out = 'List element only has direct children that are allowed
inside <li> elements'; |
| 4939 return out; |
| 4940 }, |
| 4941 fail: function anonymous(it) { |
| 4942 var out = 'List element has direct children that are not allowed i
nside <li> elements'; |
| 4943 return out; |
| 4944 } |
| 4945 } |
| 4946 }, |
| 4947 listitem: { |
| 4948 impact: 'critical', |
| 4949 messages: { |
| 4950 pass: function anonymous(it) { |
| 4951 var out = 'List item has a <ul>, <ol> or role="list" parent elemen
t'; |
| 4952 return out; |
| 4953 }, |
| 4954 fail: function anonymous(it) { |
| 4955 var out = 'List item does not have a <ul>, <ol> or role="list" par
ent element'; |
| 4956 return out; |
| 4957 } |
| 4958 } |
| 4959 }, |
| 4960 'meta-refresh': { |
| 4961 impact: 'critical', |
| 4962 messages: { |
| 4963 pass: function anonymous(it) { |
| 4964 var out = '<meta> tag does not immediately refresh the page'; |
| 4965 return out; |
| 4966 }, |
| 4967 fail: function anonymous(it) { |
| 4968 var out = '<meta> tag forces timed refresh of page'; |
| 4969 return out; |
| 4970 } |
| 4971 } |
| 4972 }, |
| 4973 'meta-viewport-large': { |
| 4974 impact: 'minor', |
| 4975 messages: { |
| 4976 pass: function anonymous(it) { |
| 4977 var out = '<meta> tag does not prevent significant zooming'; |
| 4978 return out; |
| 4979 }, |
| 4980 fail: function anonymous(it) { |
| 4981 var out = '<meta> tag limits zooming'; |
| 4982 return out; |
| 4983 } |
| 4984 } |
| 4985 }, |
| 4986 'meta-viewport': { |
| 4987 impact: 'critical', |
| 4988 messages: { |
| 4989 pass: function anonymous(it) { |
| 4990 var out = '<meta> tag does not disable zooming'; |
| 4991 return out; |
| 4992 }, |
| 4993 fail: function anonymous(it) { |
| 4994 var out = '<meta> tag disables zooming'; |
| 4995 return out; |
| 4996 } |
| 4997 } |
| 4998 }, |
| 4999 'p-as-heading': { |
| 5000 impact: 'critical', |
| 5001 messages: { |
| 5002 pass: function anonymous(it) { |
| 5003 var out = '<p> elements are not styled as headings'; |
| 5004 return out; |
| 5005 }, |
| 5006 fail: function anonymous(it) { |
| 5007 var out = 'Heading elements should be used instead of styled p ele
ments'; |
| 5008 return out; |
| 5009 } |
| 5010 } |
| 5011 }, |
| 5012 region: { |
| 5013 impact: 'moderate', |
| 5014 messages: { |
| 5015 pass: function anonymous(it) { |
| 5016 var out = 'Content contained by ARIA landmark'; |
| 5017 return out; |
| 5018 }, |
| 5019 fail: function anonymous(it) { |
| 5020 var out = 'Content not contained by an ARIA landmark'; |
| 5021 return out; |
| 5022 } |
| 5023 } |
| 5024 }, |
| 5025 'html5-scope': { |
| 5026 impact: 'serious', |
| 5027 messages: { |
| 5028 pass: function anonymous(it) { |
| 5029 var out = 'Scope attribute is only used on table header elements (
<th>)'; |
| 5030 return out; |
| 5031 }, |
| 5032 fail: function anonymous(it) { |
| 5033 var out = 'In HTML 5, scope attributes may only be used on table h
eader elements (<th>)'; |
| 5034 return out; |
| 5035 } |
| 5036 } |
| 5037 }, |
| 5038 'scope-value': { |
| 5039 impact: 'critical', |
| 5040 messages: { |
| 5041 pass: function anonymous(it) { |
| 5042 var out = 'Scope attribute is used correctly'; |
| 5043 return out; |
| 5044 }, |
| 5045 fail: function anonymous(it) { |
| 5046 var out = 'The value of the scope attribute may only be \'row\' or
\'col\''; |
| 5047 return out; |
| 5048 } |
| 5049 } |
| 5050 }, |
| 5051 exists: { |
| 5052 impact: 'minor', |
| 5053 messages: { |
| 5054 pass: function anonymous(it) { |
| 5055 var out = 'Element does not exist'; |
| 5056 return out; |
| 5057 }, |
| 5058 fail: function anonymous(it) { |
| 5059 var out = 'Element exists'; |
| 5060 return out; |
| 5061 } |
| 5062 } |
| 5063 }, |
| 5064 'skip-link': { |
| 5065 impact: 'critical', |
| 5066 messages: { |
| 5067 pass: function anonymous(it) { |
| 5068 var out = 'Valid skip link found'; |
| 5069 return out; |
| 5070 }, |
| 5071 fail: function anonymous(it) { |
| 5072 var out = 'No valid skip link found'; |
| 5073 return out; |
| 5074 } |
| 5075 } |
| 5076 }, |
| 5077 tabindex: { |
| 5078 impact: 'serious', |
| 5079 messages: { |
| 5080 pass: function anonymous(it) { |
| 5081 var out = 'Element does not have a tabindex greater than 0'; |
| 5082 return out; |
| 5083 }, |
| 5084 fail: function anonymous(it) { |
| 5085 var out = 'Element has a tabindex greater than 0'; |
| 5086 return out; |
| 5087 } |
| 5088 } |
| 5089 }, |
| 5090 'same-caption-summary': { |
| 5091 impact: 'moderate', |
| 5092 messages: { |
| 5093 pass: function anonymous(it) { |
| 5094 var out = 'Content of summary attribute and <caption> are not dupl
icated'; |
| 5095 return out; |
| 5096 }, |
| 5097 fail: function anonymous(it) { |
| 5098 var out = 'Content of summary attribute and <caption> element are
identical'; |
| 5099 return out; |
| 5100 } |
| 5101 } |
| 5102 }, |
| 5103 'caption-faked': { |
| 5104 impact: 'critical', |
| 5105 messages: { |
| 5106 pass: function anonymous(it) { |
| 5107 var out = 'The first row of a table is not used as a caption'; |
| 5108 return out; |
| 5109 }, |
| 5110 fail: function anonymous(it) { |
| 5111 var out = 'The first row of the table should be a caption instead
of a table cell'; |
| 5112 return out; |
| 5113 } |
| 5114 } |
| 5115 }, |
| 5116 'td-has-header': { |
| 5117 impact: 'critical', |
| 5118 messages: { |
| 5119 pass: function anonymous(it) { |
| 5120 var out = 'All non-empty data cells have table headers'; |
| 5121 return out; |
| 5122 }, |
| 5123 fail: function anonymous(it) { |
| 5124 var out = 'Some non-empty data cells do not have table headers'; |
| 5125 return out; |
| 5126 } |
| 5127 } |
| 5128 }, |
| 5129 'td-headers-attr': { |
| 5130 impact: 'serious', |
| 5131 messages: { |
| 5132 pass: function anonymous(it) { |
| 5133 var out = 'The headers attribute is exclusively used to refer to o
ther cells in the table'; |
| 5134 return out; |
| 5135 }, |
| 5136 fail: function anonymous(it) { |
| 5137 var out = 'The headers attribute is not exclusively used to refer
to other cells in the table'; |
| 5138 return out; |
| 5139 } |
| 5140 } |
| 5141 }, |
| 5142 'th-has-data-cells': { |
| 5143 impact: 'critical', |
| 5144 messages: { |
| 5145 pass: function anonymous(it) { |
| 5146 var out = 'All table header cells refer to data cells'; |
| 5147 return out; |
| 5148 }, |
| 5149 fail: function anonymous(it) { |
| 5150 var out = 'Not all table header cells refer to data cells'; |
| 5151 return out; |
| 5152 }, |
| 5153 incomplete: function anonymous(it) { |
| 5154 var out = 'Table data cells are missing or empty'; |
| 5155 return out; |
| 5156 } |
| 5157 } |
| 5158 }, |
| 5159 description: { |
| 5160 impact: 'serious', |
| 5161 messages: { |
| 5162 pass: function anonymous(it) { |
| 5163 var out = 'The multimedia element has an audio description track'; |
| 5164 return out; |
| 5165 }, |
| 5166 fail: function anonymous(it) { |
| 5167 var out = 'The multimedia element does not have an audio descripti
on track'; |
| 5168 return out; |
| 5169 }, |
| 5170 incomplete: function anonymous(it) { |
| 5171 var out = 'An audio description track for this element could not b
e found'; |
| 5172 return out; |
| 5173 } |
| 5174 } |
| 5175 } |
| 5176 }, |
| 5177 failureSummaries: { |
| 5178 any: { |
| 5179 failureMessage: function anonymous(it) { |
| 5180 var out = 'Fix any of the following:'; |
| 5181 var arr1 = it; |
| 5182 if (arr1) { |
| 5183 var value, i1 = -1, l1 = arr1.length - 1; |
| 5184 while (i1 < l1) { |
| 5185 value = arr1[i1 += 1]; |
| 5186 out += '\n ' + value.split('\n').join('\n '); |
| 5187 } |
| 5188 } |
| 5189 return out; |
| 5190 } |
| 5191 }, |
| 5192 none: { |
| 5193 failureMessage: function anonymous(it) { |
| 5194 var out = 'Fix all of the following:'; |
| 5195 var arr1 = it; |
| 5196 if (arr1) { |
| 5197 var value, i1 = -1, l1 = arr1.length - 1; |
| 5198 while (i1 < l1) { |
| 5199 value = arr1[i1 += 1]; |
| 5200 out += '\n ' + value.split('\n').join('\n '); |
| 5201 } |
| 5202 } |
| 5203 return out; |
| 5204 } |
| 5205 } |
| 5206 }, |
| 5207 incompleteFallbackMessage: function anonymous(it) { |
| 5208 var out = 'aXe couldn\'t tell the reason. Time to break out the element
inspector!'; |
| 5209 return out; |
| 5210 } |
| 5211 }, |
| 5212 rules: [ { |
| 5213 id: 'accesskeys', |
| 5214 selector: '[accesskey]', |
| 5215 excludeHidden: false, |
| 5216 tags: [ 'wcag2a', 'wcag211', 'cat.keyboard' ], |
| 5217 all: [], |
| 5218 any: [], |
| 5219 none: [ 'accesskeys' ] |
| 5220 }, { |
| 5221 id: 'area-alt', |
| 5222 selector: 'map area[href]', |
| 5223 excludeHidden: false, |
| 5224 tags: [ 'cat.text-alternatives', 'wcag2a', 'wcag111', 'section508', 'secti
on508.22.a' ], |
| 5225 all: [], |
| 5226 any: [ 'non-empty-alt', 'non-empty-title', 'aria-label', 'aria-labelledby'
], |
| 5227 none: [] |
| 5228 }, { |
| 5229 id: 'aria-allowed-attr', |
| 5230 matches: function matches(node) { |
| 5231 var role = node.getAttribute('role'); |
| 5232 if (!role) { |
| 5233 role = axe.commons.aria.implicitRole(node); |
| 5234 } |
| 5235 var allowed = axe.commons.aria.allowedAttr(role); |
| 5236 if (role && allowed) { |
| 5237 var aria = /^aria-/; |
| 5238 if (node.hasAttributes()) { |
| 5239 var attrs = node.attributes; |
| 5240 for (var i = 0, l = attrs.length; i < l; i++) { |
| 5241 if (aria.test(attrs[i].name)) { |
| 5242 return true; |
| 5243 } |
| 5244 } |
| 5245 } |
| 5246 } |
| 5247 return false; |
| 5248 }, |
| 5249 tags: [ 'cat.aria', 'wcag2a', 'wcag411', 'wcag412' ], |
| 5250 all: [], |
| 5251 any: [ 'aria-allowed-attr' ], |
| 5252 none: [] |
| 5253 }, { |
| 5254 id: 'aria-hidden-body', |
| 5255 selector: 'body', |
| 5256 excludeHidden: false, |
| 5257 tags: [ 'cat.aria', 'wcag2a', 'wcag412' ], |
| 5258 all: [], |
| 5259 any: [ 'aria-hidden-body' ], |
| 5260 none: [] |
| 5261 }, { |
| 5262 id: 'aria-required-attr', |
| 5263 selector: '[role]', |
| 5264 tags: [ 'cat.aria', 'wcag2a', 'wcag411', 'wcag412' ], |
| 5265 all: [], |
| 5266 any: [ 'aria-required-attr' ], |
| 5267 none: [] |
| 5268 }, { |
| 5269 id: 'aria-required-children', |
| 5270 selector: '[role]', |
| 5271 tags: [ 'cat.aria', 'wcag2a', 'wcag131' ], |
| 5272 all: [], |
| 5273 any: [ 'aria-required-children' ], |
| 5274 none: [] |
| 5275 }, { |
| 5276 id: 'aria-required-parent', |
| 5277 selector: '[role]', |
| 5278 tags: [ 'cat.aria', 'wcag2a', 'wcag131' ], |
| 5279 all: [], |
| 5280 any: [ 'aria-required-parent' ], |
| 5281 none: [] |
| 5282 }, { |
| 5283 id: 'aria-roles', |
| 5284 selector: '[role]', |
| 5285 tags: [ 'cat.aria', 'wcag2a', 'wcag131', 'wcag411', 'wcag412' ], |
| 5286 all: [], |
| 5287 any: [], |
| 5288 none: [ 'invalidrole', 'abstractrole' ] |
| 5289 }, { |
| 5290 id: 'aria-valid-attr-value', |
| 5291 matches: function matches(node) { |
| 5292 var aria = /^aria-/; |
| 5293 if (node.hasAttributes()) { |
| 5294 var attrs = node.attributes; |
| 5295 for (var i = 0, l = attrs.length; i < l; i++) { |
| 5296 if (aria.test(attrs[i].name)) { |
| 5297 return true; |
| 5298 } |
| 5299 } |
| 5300 } |
| 5301 return false; |
| 5302 }, |
| 5303 tags: [ 'cat.aria', 'wcag2a', 'wcag131', 'wcag411', 'wcag412' ], |
| 5304 all: [], |
| 5305 any: [ { |
| 5306 options: [], |
| 5307 id: 'aria-valid-attr-value' |
| 5308 } ], |
| 5309 none: [] |
| 5310 }, { |
| 5311 id: 'aria-valid-attr', |
| 5312 matches: function matches(node) { |
| 5313 var aria = /^aria-/; |
| 5314 if (node.hasAttributes()) { |
| 5315 var attrs = node.attributes; |
| 5316 for (var i = 0, l = attrs.length; i < l; i++) { |
| 5317 if (aria.test(attrs[i].name)) { |
| 5318 return true; |
| 5319 } |
| 5320 } |
| 5321 } |
| 5322 return false; |
| 5323 }, |
| 5324 tags: [ 'cat.aria', 'wcag2a', 'wcag411' ], |
| 5325 all: [], |
| 5326 any: [ { |
| 5327 options: [], |
| 5328 id: 'aria-valid-attr' |
| 5329 } ], |
| 5330 none: [] |
| 5331 }, { |
| 5332 id: 'audio-caption', |
| 5333 selector: 'audio', |
| 5334 excludeHidden: false, |
| 5335 tags: [ 'cat.time-and-media', 'wcag2a', 'wcag122', 'section508', 'section5
08.22.a' ], |
| 5336 all: [], |
| 5337 any: [], |
| 5338 none: [ 'caption' ] |
| 5339 }, { |
| 5340 id: 'blink', |
| 5341 selector: 'blink', |
| 5342 excludeHidden: false, |
| 5343 tags: [ 'cat.time-and-media', 'wcag2a', 'wcag222', 'section508', 'section5
08.22.j' ], |
| 5344 all: [], |
| 5345 any: [], |
| 5346 none: [ 'is-on-screen' ] |
| 5347 }, { |
| 5348 id: 'button-name', |
| 5349 selector: 'button, [role="button"], input[type="button"], input[type="subm
it"], input[type="reset"]', |
| 5350 tags: [ 'cat.name-role-value', 'wcag2a', 'wcag412', 'section508', 'section
508.22.a' ], |
| 5351 all: [], |
| 5352 any: [ 'non-empty-if-present', 'non-empty-value', 'button-has-visible-text
', 'aria-label', 'aria-labelledby', 'role-presentation', 'role-none' ], |
| 5353 none: [ 'focusable-no-name' ] |
| 5354 }, { |
| 5355 id: 'bypass', |
| 5356 selector: 'html', |
| 5357 pageLevel: true, |
| 5358 matches: function matches(node) { |
| 5359 return !!node.querySelector('a[href]'); |
| 5360 }, |
| 5361 tags: [ 'cat.keyboard', 'wcag2a', 'wcag241', 'section508', 'section508.22.
o' ], |
| 5362 all: [], |
| 5363 any: [ 'internal-link-present', 'header-present', 'landmark' ], |
| 5364 none: [] |
| 5365 }, { |
| 5366 id: 'checkboxgroup', |
| 5367 selector: 'input[type=checkbox][name]', |
| 5368 tags: [ 'cat.forms', 'best-practice' ], |
| 5369 all: [], |
| 5370 any: [ 'group-labelledby', 'fieldset' ], |
| 5371 none: [] |
| 5372 }, { |
| 5373 id: 'color-contrast', |
| 5374 matches: function matches(node) { |
| 5375 var nodeName = node.nodeName.toUpperCase(), nodeType = node.type, doc =
document; |
| 5376 if (node.getAttribute('aria-disabled') === 'true' || axe.commons.dom.fin
dUp(node, '[aria-disabled="true"]')) { |
| 5377 return false; |
| 5378 } |
| 5379 if (nodeName === 'INPUT') { |
| 5380 return [ 'hidden', 'range', 'color', 'checkbox', 'radio', 'image' ].in
dexOf(nodeType) === -1 && !node.disabled; |
| 5381 } |
| 5382 if (nodeName === 'SELECT') { |
| 5383 return !!node.options.length && !node.disabled; |
| 5384 } |
| 5385 if (nodeName === 'TEXTAREA') { |
| 5386 return !node.disabled; |
| 5387 } |
| 5388 if (nodeName === 'OPTION') { |
| 5389 return false; |
| 5390 } |
| 5391 if (nodeName === 'BUTTON' && node.disabled || axe.commons.dom.findUp(nod
e, 'button[disabled]')) { |
| 5392 return false; |
| 5393 } |
| 5394 if (nodeName === 'FIELDSET' && node.disabled || axe.commons.dom.findUp(n
ode, 'fieldset[disabled]')) { |
| 5395 return false; |
| 5396 } |
| 5397 var nodeParentLabel = axe.commons.dom.findUp(node, 'label'); |
| 5398 if (nodeName === 'LABEL' || nodeParentLabel) { |
| 5399 var relevantNode = node; |
| 5400 if (nodeParentLabel) { |
| 5401 relevantNode = nodeParentLabel; |
| 5402 } |
| 5403 var candidate = relevantNode.htmlFor && doc.getElementById(relevantNod
e.htmlFor); |
| 5404 if (candidate && candidate.disabled) { |
| 5405 return false; |
| 5406 } |
| 5407 var candidate = node.querySelector('input:not([type="hidden"]):not([ty
pe="image"])' + ':not([type="button"]):not([type="submit"]):not([type="reset"]),
select, textarea'); |
| 5408 if (candidate && candidate.disabled) { |
| 5409 return false; |
| 5410 } |
| 5411 } |
| 5412 if (node.id) { |
| 5413 var candidate = doc.querySelector('[aria-labelledby~=' + axe.commons.u
tils.escapeSelector(node.id) + ']'); |
| 5414 if (candidate && candidate.disabled) { |
| 5415 return false; |
| 5416 } |
| 5417 } |
| 5418 if (axe.commons.text.visible(node, false, true) === '') { |
| 5419 return false; |
| 5420 } |
| 5421 var range = document.createRange(), childNodes = node.childNodes, length
= childNodes.length, child, index; |
| 5422 for (index = 0; index < length; index++) { |
| 5423 child = childNodes[index]; |
| 5424 if (child.nodeType === 3 && axe.commons.text.sanitize(child.nodeValue)
!== '') { |
| 5425 range.selectNodeContents(child); |
| 5426 } |
| 5427 } |
| 5428 var rects = range.getClientRects(); |
| 5429 length = rects.length; |
| 5430 for (index = 0; index < length; index++) { |
| 5431 if (axe.commons.dom.visuallyOverlaps(rects[index], node)) { |
| 5432 return true; |
| 5433 } |
| 5434 } |
| 5435 return false; |
| 5436 }, |
| 5437 excludeHidden: false, |
| 5438 options: { |
| 5439 noScroll: false |
| 5440 }, |
| 5441 tags: [ 'cat.color', 'wcag2aa', 'wcag143' ], |
| 5442 all: [], |
| 5443 any: [ 'color-contrast' ], |
| 5444 none: [] |
| 5445 }, { |
| 5446 id: 'definition-list', |
| 5447 selector: 'dl', |
| 5448 matches: function matches(node) { |
| 5449 return !node.getAttribute('role'); |
| 5450 }, |
| 5451 tags: [ 'cat.structure', 'wcag2a', 'wcag131' ], |
| 5452 all: [], |
| 5453 any: [], |
| 5454 none: [ 'structured-dlitems', 'only-dlitems' ] |
| 5455 }, { |
| 5456 id: 'dlitem', |
| 5457 selector: 'dd, dt', |
| 5458 matches: function matches(node) { |
| 5459 return !node.getAttribute('role'); |
| 5460 }, |
| 5461 tags: [ 'cat.structure', 'wcag2a', 'wcag131' ], |
| 5462 all: [], |
| 5463 any: [ 'dlitem' ], |
| 5464 none: [] |
| 5465 }, { |
| 5466 id: 'document-title', |
| 5467 selector: 'html', |
| 5468 matches: function matches(node) { |
| 5469 return node.ownerDocument.defaultView.self === node.ownerDocument.defaul
tView.top; |
| 5470 }, |
| 5471 tags: [ 'cat.text-alternatives', 'wcag2a', 'wcag242' ], |
| 5472 all: [], |
| 5473 any: [ 'doc-has-title' ], |
| 5474 none: [] |
| 5475 }, { |
| 5476 id: 'duplicate-id', |
| 5477 selector: '[id]', |
| 5478 excludeHidden: false, |
| 5479 tags: [ 'cat.parsing', 'wcag2a', 'wcag411' ], |
| 5480 all: [], |
| 5481 any: [ 'duplicate-id' ], |
| 5482 none: [] |
| 5483 }, { |
| 5484 id: 'empty-heading', |
| 5485 selector: 'h1, h2, h3, h4, h5, h6, [role="heading"]', |
| 5486 enabled: true, |
| 5487 tags: [ 'cat.name-role-value', 'best-practice' ], |
| 5488 all: [], |
| 5489 any: [ 'has-visible-text', 'role-presentation', 'role-none' ], |
| 5490 none: [] |
| 5491 }, { |
| 5492 id: 'frame-title-unique', |
| 5493 selector: 'frame[title], iframe[title]', |
| 5494 matches: function matches(node) { |
| 5495 var title = node.getAttribute('title'); |
| 5496 return !!(title ? axe.commons.text.sanitize(title).trim() : ''); |
| 5497 }, |
| 5498 tags: [ 'cat.text-alternatives', 'best-practice' ], |
| 5499 all: [], |
| 5500 any: [], |
| 5501 none: [ 'unique-frame-title' ] |
| 5502 }, { |
| 5503 id: 'frame-title', |
| 5504 selector: 'frame, iframe', |
| 5505 tags: [ 'cat.text-alternatives', 'wcag2a', 'wcag241', 'section508', 'secti
on508.22.i' ], |
| 5506 all: [], |
| 5507 any: [ 'aria-label', 'aria-labelledby', 'non-empty-title', 'role-presentat
ion', 'role-none' ], |
| 5508 none: [] |
| 5509 }, { |
| 5510 id: 'heading-order', |
| 5511 selector: 'h1,h2,h3,h4,h5,h6,[role=heading]', |
| 5512 enabled: false, |
| 5513 tags: [ 'cat.semantics', 'best-practice' ], |
| 5514 all: [], |
| 5515 any: [ 'heading-order' ], |
| 5516 none: [] |
| 5517 }, { |
| 5518 id: 'hidden-content', |
| 5519 selector: '*', |
| 5520 excludeHidden: false, |
| 5521 tags: [ 'experimental', 'review-item' ], |
| 5522 all: [], |
| 5523 any: [ 'hidden-content' ], |
| 5524 none: [], |
| 5525 enabled: false |
| 5526 }, { |
| 5527 id: 'href-no-hash', |
| 5528 selector: 'a[href]', |
| 5529 enabled: false, |
| 5530 tags: [ 'cat.semantics', 'best-practice' ], |
| 5531 all: [], |
| 5532 any: [ 'href-no-hash' ], |
| 5533 none: [] |
| 5534 }, { |
| 5535 id: 'html-has-lang', |
| 5536 selector: 'html', |
| 5537 tags: [ 'cat.language', 'wcag2a', 'wcag311' ], |
| 5538 all: [], |
| 5539 any: [ 'has-lang' ], |
| 5540 none: [] |
| 5541 }, { |
| 5542 id: 'html-lang-valid', |
| 5543 selector: 'html[lang]', |
| 5544 tags: [ 'cat.language', 'wcag2a', 'wcag311' ], |
| 5545 all: [], |
| 5546 any: [], |
| 5547 none: [ 'valid-lang' ] |
| 5548 }, { |
| 5549 id: 'image-alt', |
| 5550 selector: 'img, [role=\'img\']', |
| 5551 tags: [ 'cat.text-alternatives', 'wcag2a', 'wcag111', 'section508', 'secti
on508.22.a' ], |
| 5552 all: [], |
| 5553 any: [ 'has-alt', 'aria-label', 'aria-labelledby', 'non-empty-title', 'rol
e-presentation', 'role-none' ], |
| 5554 none: [] |
| 5555 }, { |
| 5556 id: 'image-redundant-alt', |
| 5557 selector: 'button, [role="button"], a[href], p, li, td, th', |
| 5558 tags: [ 'cat.text-alternatives', 'best-practice' ], |
| 5559 all: [], |
| 5560 any: [], |
| 5561 none: [ 'duplicate-img-label' ] |
| 5562 }, { |
| 5563 id: 'input-image-alt', |
| 5564 selector: 'input[type="image"]', |
| 5565 tags: [ 'cat.text-alternatives', 'wcag2a', 'wcag111', 'section508', 'secti
on508.22.a' ], |
| 5566 all: [], |
| 5567 any: [ 'non-empty-alt', 'aria-label', 'aria-labelledby', 'non-empty-title'
], |
| 5568 none: [] |
| 5569 }, { |
| 5570 id: 'label-title-only', |
| 5571 selector: 'input, select, textarea', |
| 5572 matches: function matches(node) { |
| 5573 if (node.nodeName.toLowerCase() !== 'input') { |
| 5574 return true; |
| 5575 } |
| 5576 var t = node.getAttribute('type').toLowerCase(); |
| 5577 if (t === 'hidden' || t === 'image' || t === 'button' || t === 'submit'
|| t === 'reset') { |
| 5578 return false; |
| 5579 } |
| 5580 return true; |
| 5581 }, |
| 5582 enabled: false, |
| 5583 tags: [ 'cat.forms', 'best-practice' ], |
| 5584 all: [], |
| 5585 any: [], |
| 5586 none: [ 'title-only' ] |
| 5587 }, { |
| 5588 id: 'label', |
| 5589 selector: 'input, select, textarea', |
| 5590 matches: function matches(node) { |
| 5591 if (node.nodeName.toLowerCase() !== 'input') { |
| 5592 return true; |
| 5593 } |
| 5594 var t = node.getAttribute('type').toLowerCase(); |
| 5595 if (t === 'hidden' || t === 'image' || t === 'button' || t === 'submit'
|| t === 'reset') { |
| 5596 return false; |
| 5597 } |
| 5598 return true; |
| 5599 }, |
| 5600 tags: [ 'cat.forms', 'wcag2a', 'wcag332', 'wcag131', 'section508', 'sectio
n508.22.n' ], |
| 5601 all: [], |
| 5602 any: [ 'aria-label', 'aria-labelledby', 'implicit-label', 'explicit-label'
, 'non-empty-title' ], |
| 5603 none: [ 'help-same-as-label', 'multiple-label' ] |
| 5604 }, { |
| 5605 id: 'layout-table', |
| 5606 selector: 'table', |
| 5607 matches: function matches(node) { |
| 5608 return !axe.commons.table.isDataTable(node); |
| 5609 }, |
| 5610 tags: [ 'cat.semantics', 'wcag2a', 'wcag131' ], |
| 5611 all: [], |
| 5612 any: [], |
| 5613 none: [ 'has-th', 'has-caption', 'has-summary' ] |
| 5614 }, { |
| 5615 id: 'link-in-text-block', |
| 5616 selector: 'a[href], *[role=link]', |
| 5617 matches: function matches(node) { |
| 5618 var text = axe.commons.text.sanitize(node.textContent); |
| 5619 var role = node.getAttribute('role'); |
| 5620 if (role && role !== 'link') { |
| 5621 return false; |
| 5622 } |
| 5623 if (!text) { |
| 5624 return false; |
| 5625 } |
| 5626 if (!axe.commons.dom.isVisible(node, false)) { |
| 5627 return false; |
| 5628 } |
| 5629 return axe.commons.dom.isInTextBlock(node); |
| 5630 }, |
| 5631 excludeHidden: false, |
| 5632 tags: [ 'cat.color', 'experimental', 'wcag2a', 'wcag141' ], |
| 5633 all: [ 'link-in-text-block' ], |
| 5634 any: [], |
| 5635 none: [] |
| 5636 }, { |
| 5637 id: 'link-name', |
| 5638 selector: 'a[href], [role=link][href]', |
| 5639 matches: function matches(node) { |
| 5640 return node.getAttribute('role') !== 'button'; |
| 5641 }, |
| 5642 tags: [ 'cat.name-role-value', 'wcag2a', 'wcag111', 'wcag412', 'section508
', 'section508.22.a' ], |
| 5643 all: [], |
| 5644 any: [ 'has-visible-text', 'aria-label', 'aria-labelledby', 'role-presenta
tion', 'role-none' ], |
| 5645 none: [ 'focusable-no-name' ] |
| 5646 }, { |
| 5647 id: 'list', |
| 5648 selector: 'ul, ol', |
| 5649 matches: function matches(node) { |
| 5650 return !node.getAttribute('role'); |
| 5651 }, |
| 5652 tags: [ 'cat.structure', 'wcag2a', 'wcag131' ], |
| 5653 all: [], |
| 5654 any: [], |
| 5655 none: [ 'only-listitems' ] |
| 5656 }, { |
| 5657 id: 'listitem', |
| 5658 selector: 'li', |
| 5659 matches: function matches(node) { |
| 5660 return !node.getAttribute('role'); |
| 5661 }, |
| 5662 tags: [ 'cat.structure', 'wcag2a', 'wcag131' ], |
| 5663 all: [], |
| 5664 any: [ 'listitem' ], |
| 5665 none: [] |
| 5666 }, { |
| 5667 id: 'marquee', |
| 5668 selector: 'marquee', |
| 5669 excludeHidden: false, |
| 5670 tags: [ 'cat.parsing', 'wcag2a', 'wcag222' ], |
| 5671 all: [], |
| 5672 any: [], |
| 5673 none: [ 'is-on-screen' ] |
| 5674 }, { |
| 5675 id: 'meta-refresh', |
| 5676 selector: 'meta[http-equiv="refresh"]', |
| 5677 excludeHidden: false, |
| 5678 tags: [ 'cat.time', 'wcag2a', 'wcag2aaa', 'wcag221', 'wcag224', 'wcag325'
], |
| 5679 all: [], |
| 5680 any: [ 'meta-refresh' ], |
| 5681 none: [] |
| 5682 }, { |
| 5683 id: 'meta-viewport-large', |
| 5684 selector: 'meta[name="viewport"]', |
| 5685 excludeHidden: false, |
| 5686 tags: [ 'cat.sensory-and-visual-cues', 'best-practice' ], |
| 5687 all: [], |
| 5688 any: [ { |
| 5689 options: { |
| 5690 scaleMinimum: 5, |
| 5691 lowerBound: 2 |
| 5692 }, |
| 5693 id: 'meta-viewport-large' |
| 5694 } ], |
| 5695 none: [] |
| 5696 }, { |
| 5697 id: 'meta-viewport', |
| 5698 selector: 'meta[name="viewport"]', |
| 5699 excludeHidden: false, |
| 5700 tags: [ 'cat.sensory-and-visual-cues', 'wcag2aa', 'wcag144' ], |
| 5701 all: [], |
| 5702 any: [ { |
| 5703 options: { |
| 5704 scaleMinimum: 2 |
| 5705 }, |
| 5706 id: 'meta-viewport' |
| 5707 } ], |
| 5708 none: [] |
| 5709 }, { |
| 5710 id: 'object-alt', |
| 5711 selector: 'object', |
| 5712 tags: [ 'cat.text-alternatives', 'wcag2a', 'wcag111', 'section508', 'secti
on508.22.a' ], |
| 5713 all: [], |
| 5714 any: [ 'has-visible-text', 'aria-label', 'aria-labelledby', 'non-empty-tit
le' ], |
| 5715 none: [] |
| 5716 }, { |
| 5717 id: 'p-as-heading', |
| 5718 selector: 'p', |
| 5719 matches: function matches(node) { |
| 5720 var children = Array.from(node.parentNode.childNodes); |
| 5721 var nodeText = node.textContent.trim(); |
| 5722 var isSentence = /[.!?:;](?![.!?:;])/g; |
| 5723 if (nodeText.length === 0 || (nodeText.match(isSentence) || []).length >
= 2) { |
| 5724 return false; |
| 5725 } |
| 5726 var siblingsAfter = children.slice(children.indexOf(node) + 1).filter(fu
nction(elm) { |
| 5727 return elm.nodeName.toUpperCase() === 'P' && elm.textContent.trim() !=
= ''; |
| 5728 }); |
| 5729 return siblingsAfter.length !== 0; |
| 5730 }, |
| 5731 tags: [ 'cat.semantics', 'wcag2a', 'wcag131', 'experimental' ], |
| 5732 all: [ { |
| 5733 options: { |
| 5734 margins: [ { |
| 5735 weight: 150, |
| 5736 italic: true |
| 5737 }, { |
| 5738 weight: 150, |
| 5739 size: 1.15 |
| 5740 }, { |
| 5741 italic: true, |
| 5742 size: 1.15 |
| 5743 }, { |
| 5744 size: 1.4 |
| 5745 } ] |
| 5746 }, |
| 5747 id: 'p-as-heading' |
| 5748 } ], |
| 5749 any: [], |
| 5750 none: [] |
| 5751 }, { |
| 5752 id: 'radiogroup', |
| 5753 selector: 'input[type=radio][name]', |
| 5754 tags: [ 'cat.forms', 'best-practice' ], |
| 5755 all: [], |
| 5756 any: [ 'group-labelledby', 'fieldset' ], |
| 5757 none: [] |
| 5758 }, { |
| 5759 id: 'region', |
| 5760 selector: 'html', |
| 5761 pageLevel: true, |
| 5762 enabled: false, |
| 5763 tags: [ 'cat.keyboard', 'best-practice' ], |
| 5764 all: [], |
| 5765 any: [ 'region' ], |
| 5766 none: [] |
| 5767 }, { |
| 5768 id: 'scope-attr-valid', |
| 5769 selector: 'td[scope], th[scope]', |
| 5770 enabled: true, |
| 5771 tags: [ 'cat.tables', 'best-practice' ], |
| 5772 all: [ 'html5-scope', 'scope-value' ], |
| 5773 any: [], |
| 5774 none: [] |
| 5775 }, { |
| 5776 id: 'server-side-image-map', |
| 5777 selector: 'img[ismap]', |
| 5778 tags: [ 'cat.text-alternatives', 'wcag2a', 'wcag211', 'section508', 'secti
on508.22.f' ], |
| 5779 all: [], |
| 5780 any: [], |
| 5781 none: [ 'exists' ] |
| 5782 }, { |
| 5783 id: 'skip-link', |
| 5784 selector: 'a[href]', |
| 5785 pageLevel: true, |
| 5786 enabled: false, |
| 5787 tags: [ 'cat.keyboard', 'best-practice' ], |
| 5788 all: [], |
| 5789 any: [ 'skip-link' ], |
| 5790 none: [] |
| 5791 }, { |
| 5792 id: 'tabindex', |
| 5793 selector: '[tabindex]', |
| 5794 tags: [ 'cat.keyboard', 'best-practice' ], |
| 5795 all: [], |
| 5796 any: [ 'tabindex' ], |
| 5797 none: [] |
| 5798 }, { |
| 5799 id: 'table-duplicate-name', |
| 5800 selector: 'table', |
| 5801 tags: [ 'cat.tables', 'best-practice' ], |
| 5802 all: [], |
| 5803 any: [], |
| 5804 none: [ 'same-caption-summary' ] |
| 5805 }, { |
| 5806 id: 'table-fake-caption', |
| 5807 selector: 'table', |
| 5808 matches: function matches(node) { |
| 5809 return axe.commons.table.isDataTable(node); |
| 5810 }, |
| 5811 tags: [ 'cat.tables', 'experimental', 'wcag2a', 'wcag131', 'section508', '
section508.22.g' ], |
| 5812 all: [ 'caption-faked' ], |
| 5813 any: [], |
| 5814 none: [] |
| 5815 }, { |
| 5816 id: 'td-has-header', |
| 5817 selector: 'table', |
| 5818 matches: function matches(node) { |
| 5819 if (axe.commons.table.isDataTable(node)) { |
| 5820 var tableArray = axe.commons.table.toArray(node); |
| 5821 return tableArray.length >= 3 && tableArray[0].length >= 3 && tableArr
ay[1].length >= 3 && tableArray[2].length >= 3; |
| 5822 } |
| 5823 return false; |
| 5824 }, |
| 5825 tags: [ 'cat.tables', 'experimental', 'wcag2a', 'wcag131', 'section508', '
section508.22.g' ], |
| 5826 all: [ 'td-has-header' ], |
| 5827 any: [], |
| 5828 none: [] |
| 5829 }, { |
| 5830 id: 'td-headers-attr', |
| 5831 selector: 'table', |
| 5832 tags: [ 'cat.tables', 'wcag2a', 'wcag131', 'section508', 'section508.22.g'
], |
| 5833 all: [ 'td-headers-attr' ], |
| 5834 any: [], |
| 5835 none: [] |
| 5836 }, { |
| 5837 id: 'th-has-data-cells', |
| 5838 selector: 'table', |
| 5839 matches: function matches(node) { |
| 5840 return axe.commons.table.isDataTable(node); |
| 5841 }, |
| 5842 tags: [ 'cat.tables', 'wcag2a', 'wcag131', 'section508', 'section508.22.g'
], |
| 5843 all: [ 'th-has-data-cells' ], |
| 5844 any: [], |
| 5845 none: [] |
| 5846 }, { |
| 5847 id: 'valid-lang', |
| 5848 selector: '[lang], [xml\\:lang]', |
| 5849 matches: function matches(node) { |
| 5850 return node.nodeName.toLowerCase() !== 'html'; |
| 5851 }, |
| 5852 tags: [ 'cat.language', 'wcag2aa', 'wcag312' ], |
| 5853 all: [], |
| 5854 any: [], |
| 5855 none: [ 'valid-lang' ] |
| 5856 }, { |
| 5857 id: 'video-caption', |
| 5858 selector: 'video', |
| 5859 excludeHidden: false, |
| 5860 tags: [ 'cat.text-alternatives', 'wcag2a', 'wcag122', 'wcag123', 'section5
08', 'section508.22.a' ], |
| 5861 all: [], |
| 5862 any: [], |
| 5863 none: [ 'caption' ] |
| 5864 }, { |
| 5865 id: 'video-description', |
| 5866 selector: 'video', |
| 5867 excludeHidden: false, |
| 5868 tags: [ 'cat.text-alternatives', 'wcag2aa', 'wcag125', 'section508', 'sect
ion508.22.b' ], |
| 5869 all: [], |
| 5870 any: [], |
| 5871 none: [ 'description' ] |
| 5872 } ], |
| 5873 checks: [ { |
| 5874 id: 'abstractrole', |
| 5875 evaluate: function evaluate(node, options) { |
| 5876 return axe.commons.aria.getRoleType(node.getAttribute('role')) === 'abst
ract'; |
| 5877 } |
| 5878 }, { |
| 5879 id: 'aria-allowed-attr', |
| 5880 evaluate: function evaluate(node, options) { |
| 5881 var invalid = []; |
| 5882 var attr, attrName, allowed, role = node.getAttribute('role'), attrs = n
ode.attributes; |
| 5883 if (!role) { |
| 5884 role = axe.commons.aria.implicitRole(node); |
| 5885 } |
| 5886 allowed = axe.commons.aria.allowedAttr(role); |
| 5887 if (role && allowed) { |
| 5888 for (var i = 0, l = attrs.length; i < l; i++) { |
| 5889 attr = attrs[i]; |
| 5890 attrName = attr.name; |
| 5891 if (axe.commons.aria.validateAttr(attrName) && allowed.indexOf(attrN
ame) === -1) { |
| 5892 invalid.push(attrName + '="' + attr.nodeValue + '"'); |
| 5893 } |
| 5894 } |
| 5895 } |
| 5896 if (invalid.length) { |
| 5897 this.data(invalid); |
| 5898 return false; |
| 5899 } |
| 5900 return true; |
| 5901 } |
| 5902 }, { |
| 5903 id: 'aria-hidden-body', |
| 5904 evaluate: function evaluate(node, options) { |
| 5905 return node.getAttribute('aria-hidden') !== 'true'; |
| 5906 } |
| 5907 }, { |
| 5908 id: 'invalidrole', |
| 5909 evaluate: function evaluate(node, options) { |
| 5910 return !axe.commons.aria.isValidRole(node.getAttribute('role')); |
| 5911 } |
| 5912 }, { |
| 5913 id: 'aria-required-attr', |
| 5914 evaluate: function evaluate(node, options) { |
| 5915 var missing = []; |
| 5916 if (node.hasAttributes()) { |
| 5917 var attr, role = node.getAttribute('role'), required = axe.commons.ari
a.requiredAttr(role); |
| 5918 if (role && required) { |
| 5919 for (var i = 0, l = required.length; i < l; i++) { |
| 5920 attr = required[i]; |
| 5921 if (!node.getAttribute(attr)) { |
| 5922 missing.push(attr); |
| 5923 } |
| 5924 } |
| 5925 } |
| 5926 } |
| 5927 if (missing.length) { |
| 5928 this.data(missing); |
| 5929 return false; |
| 5930 } |
| 5931 return true; |
| 5932 } |
| 5933 }, { |
| 5934 id: 'aria-required-children', |
| 5935 evaluate: function evaluate(node, options) { |
| 5936 var requiredOwned = axe.commons.aria.requiredOwned, implicitNodes = axe.
commons.aria.implicitNodes, matchesSelector = axe.commons.utils.matchesSelector,
idrefs = axe.commons.dom.idrefs; |
| 5937 function owns(node, role, ariaOwned) { |
| 5938 if (node === null) { |
| 5939 return false; |
| 5940 } |
| 5941 var implicit = implicitNodes(role), selector = [ '[role="' + role + '"
]' ]; |
| 5942 if (implicit) { |
| 5943 selector = selector.concat(implicit); |
| 5944 } |
| 5945 selector = selector.join(','); |
| 5946 return ariaOwned ? matchesSelector(node, selector) || !!node.querySele
ctor(selector) : !!node.querySelector(selector); |
| 5947 } |
| 5948 function ariaOwns(nodes, role) { |
| 5949 var index, length; |
| 5950 for (index = 0, length = nodes.length; index < length; index++) { |
| 5951 if (nodes[index] === null) { |
| 5952 continue; |
| 5953 } |
| 5954 if (owns(nodes[index], role, true)) { |
| 5955 return true; |
| 5956 } |
| 5957 } |
| 5958 return false; |
| 5959 } |
| 5960 function missingRequiredChildren(node, childRoles, all) { |
| 5961 var i, l = childRoles.length, missing = [], ownedElements = idrefs(nod
e, 'aria-owns'); |
| 5962 for (i = 0; i < l; i++) { |
| 5963 var r = childRoles[i]; |
| 5964 if (owns(node, r) || ariaOwns(ownedElements, r)) { |
| 5965 if (!all) { |
| 5966 return null; |
| 5967 } |
| 5968 } else { |
| 5969 if (all) { |
| 5970 missing.push(r); |
| 5971 } |
| 5972 } |
| 5973 } |
| 5974 if (missing.length) { |
| 5975 return missing; |
| 5976 } |
| 5977 if (!all && childRoles.length) { |
| 5978 return childRoles; |
| 5979 } |
| 5980 return null; |
| 5981 } |
| 5982 var role = node.getAttribute('role'); |
| 5983 var required = requiredOwned(role); |
| 5984 if (!required) { |
| 5985 return true; |
| 5986 } |
| 5987 var all = false; |
| 5988 var childRoles = required.one; |
| 5989 if (!childRoles) { |
| 5990 var all = true; |
| 5991 childRoles = required.all; |
| 5992 } |
| 5993 var missing = missingRequiredChildren(node, childRoles, all); |
| 5994 if (!missing) { |
| 5995 return true; |
| 5996 } |
| 5997 this.data(missing); |
| 5998 return false; |
| 5999 } |
| 6000 }, { |
| 6001 id: 'aria-required-parent', |
| 6002 evaluate: function evaluate(node, options) { |
| 6003 function getSelector(role) { |
| 6004 var impliedNative = axe.commons.aria.implicitNodes(role) || []; |
| 6005 return impliedNative.concat('[role="' + role + '"]').join(','); |
| 6006 } |
| 6007 function getMissingContext(element, requiredContext, includeElement) { |
| 6008 var index, length, role = element.getAttribute('role'), missing = []; |
| 6009 if (!requiredContext) { |
| 6010 requiredContext = axe.commons.aria.requiredContext(role); |
| 6011 } |
| 6012 if (!requiredContext) { |
| 6013 return null; |
| 6014 } |
| 6015 for (index = 0, length = requiredContext.length; index < length; index
++) { |
| 6016 if (includeElement && axe.utils.matchesSelector(element, getSelector
(requiredContext[index]))) { |
| 6017 return null; |
| 6018 } |
| 6019 if (axe.commons.dom.findUp(element, getSelector(requiredContext[inde
x]))) { |
| 6020 return null; |
| 6021 } else { |
| 6022 missing.push(requiredContext[index]); |
| 6023 } |
| 6024 } |
| 6025 return missing; |
| 6026 } |
| 6027 function getAriaOwners(element) { |
| 6028 var owners = [], o = null; |
| 6029 while (element) { |
| 6030 if (element.id) { |
| 6031 o = document.querySelector('[aria-owns~=' + axe.commons.utils.esca
peSelector(element.id) + ']'); |
| 6032 if (o) { |
| 6033 owners.push(o); |
| 6034 } |
| 6035 } |
| 6036 element = element.parentNode; |
| 6037 } |
| 6038 return owners.length ? owners : null; |
| 6039 } |
| 6040 var missingParents = getMissingContext(node); |
| 6041 if (!missingParents) { |
| 6042 return true; |
| 6043 } |
| 6044 var owners = getAriaOwners(node); |
| 6045 if (owners) { |
| 6046 for (var i = 0, l = owners.length; i < l; i++) { |
| 6047 missingParents = getMissingContext(owners[i], missingParents, true); |
| 6048 if (!missingParents) { |
| 6049 return true; |
| 6050 } |
| 6051 } |
| 6052 } |
| 6053 this.data(missingParents); |
| 6054 return false; |
| 6055 } |
| 6056 }, { |
| 6057 id: 'aria-valid-attr-value', |
| 6058 evaluate: function evaluate(node, options) { |
| 6059 options = Array.isArray(options) ? options : []; |
| 6060 var invalid = [], aria = /^aria-/; |
| 6061 var attr, attrName, attrs = node.attributes; |
| 6062 for (var i = 0, l = attrs.length; i < l; i++) { |
| 6063 attr = attrs[i]; |
| 6064 attrName = attr.name; |
| 6065 if (options.indexOf(attrName) === -1 && aria.test(attrName) && !axe.co
mmons.aria.validateAttrValue(node, attrName)) { |
| 6066 invalid.push(attrName + '="' + attr.nodeValue + '"'); |
| 6067 } |
| 6068 } |
| 6069 if (invalid.length) { |
| 6070 this.data(invalid); |
| 6071 return false; |
| 6072 } |
| 6073 return true; |
| 6074 }, |
| 6075 options: [] |
| 6076 }, { |
| 6077 id: 'aria-valid-attr', |
| 6078 evaluate: function evaluate(node, options) { |
| 6079 options = Array.isArray(options) ? options : []; |
| 6080 var invalid = [], aria = /^aria-/; |
| 6081 var attr, attrs = node.attributes; |
| 6082 for (var i = 0, l = attrs.length; i < l; i++) { |
| 6083 attr = attrs[i].name; |
| 6084 if (options.indexOf(attr) === -1 && aria.test(attr) && !axe.commons.ar
ia.validateAttr(attr)) { |
| 6085 invalid.push(attr); |
| 6086 } |
| 6087 } |
| 6088 if (invalid.length) { |
| 6089 this.data(invalid); |
| 6090 return false; |
| 6091 } |
| 6092 return true; |
| 6093 }, |
| 6094 options: [] |
| 6095 }, { |
| 6096 id: 'color-contrast', |
| 6097 evaluate: function evaluate(node, options) { |
| 6098 if (!axe.commons.dom.isVisible(node, false)) { |
| 6099 return true; |
| 6100 } |
| 6101 var noScroll = !!(options || {}).noScroll; |
| 6102 var bgNodes = [], bgColor = axe.commons.color.getBackgroundColor(node, b
gNodes, noScroll), fgColor = axe.commons.color.getForegroundColor(node, noScroll
); |
| 6103 var nodeStyle = window.getComputedStyle(node); |
| 6104 var fontSize = parseFloat(nodeStyle.getPropertyValue('font-size')); |
| 6105 var fontWeight = nodeStyle.getPropertyValue('font-weight'); |
| 6106 var bold = [ 'bold', 'bolder', '600', '700', '800', '900' ].indexOf(font
Weight) !== -1; |
| 6107 var cr = axe.commons.color.hasValidContrastRatio(bgColor, fgColor, fontS
ize, bold); |
| 6108 var truncatedResult = Math.floor(cr.contrastRatio * 100) / 100; |
| 6109 var missing; |
| 6110 if (bgColor === null) { |
| 6111 missing = axe.commons.color.incompleteData.get('bgColor'); |
| 6112 } |
| 6113 var equalRatio = false; |
| 6114 if (truncatedResult === 1) { |
| 6115 equalRatio = true; |
| 6116 missing = axe.commons.color.incompleteData.set('bgColor', 'equalRatio'
); |
| 6117 } |
| 6118 var data = { |
| 6119 fgColor: fgColor ? fgColor.toHexString() : undefined, |
| 6120 bgColor: bgColor ? bgColor.toHexString() : undefined, |
| 6121 contrastRatio: cr ? truncatedResult : undefined, |
| 6122 fontSize: (fontSize * 72 / 96).toFixed(1) + 'pt', |
| 6123 fontWeight: bold ? 'bold' : 'normal', |
| 6124 missingData: missing |
| 6125 }; |
| 6126 this.data(data); |
| 6127 if (!cr.isValid || equalRatio) { |
| 6128 this.relatedNodes(bgNodes); |
| 6129 } |
| 6130 if (fgColor === null || bgColor === null || equalRatio) { |
| 6131 missing = null; |
| 6132 axe.commons.color.incompleteData.clear(); |
| 6133 return undefined; |
| 6134 } |
| 6135 return cr.isValid; |
| 6136 } |
| 6137 }, { |
| 6138 id: 'link-in-text-block', |
| 6139 evaluate: function evaluate(node, options) { |
| 6140 var color = axe.commons.color; |
| 6141 function getContrast(color1, color2) { |
| 6142 var c1lum = color1.getRelativeLuminance(); |
| 6143 var c2lum = color2.getRelativeLuminance(); |
| 6144 return (Math.max(c1lum, c2lum) + .05) / (Math.min(c1lum, c2lum) + .05)
; |
| 6145 } |
| 6146 var blockLike = [ 'block', 'list-item', 'table', 'flex', 'grid', 'inline
-block' ]; |
| 6147 function isBlock(elm) { |
| 6148 var display = window.getComputedStyle(elm).getPropertyValue('display')
; |
| 6149 return blockLike.indexOf(display) !== -1 || display.substr(0, 6) === '
table-'; |
| 6150 } |
| 6151 if (isBlock(node)) { |
| 6152 return false; |
| 6153 } |
| 6154 var parentBlock = node.parentNode; |
| 6155 while (parentBlock.nodeType === 1 && !isBlock(parentBlock)) { |
| 6156 parentBlock = parentBlock.parentNode; |
| 6157 } |
| 6158 if (color.elementIsDistinct(node, parentBlock)) { |
| 6159 return true; |
| 6160 } else { |
| 6161 var nodeColor, parentColor; |
| 6162 nodeColor = color.getForegroundColor(node); |
| 6163 parentColor = color.getForegroundColor(parentBlock); |
| 6164 if (!nodeColor || !parentColor) { |
| 6165 return undefined; |
| 6166 } |
| 6167 var contrast = getContrast(nodeColor, parentColor); |
| 6168 if (contrast === 1) { |
| 6169 return true; |
| 6170 } else if (contrast >= 3) { |
| 6171 axe.commons.color.incompleteData.set('fgColor', 'bgContrast'); |
| 6172 this.data({ |
| 6173 missingData: axe.commons.color.incompleteData.get('fgColor') |
| 6174 }); |
| 6175 axe.commons.color.incompleteData.clear(); |
| 6176 return undefined; |
| 6177 } |
| 6178 nodeColor = color.getBackgroundColor(node); |
| 6179 parentColor = color.getBackgroundColor(parentBlock); |
| 6180 if (!nodeColor || !parentColor || getContrast(nodeColor, parentColor)
>= 3) { |
| 6181 var reason = void 0; |
| 6182 if (!nodeColor || !parentColor) { |
| 6183 reason = axe.commons.color.incompleteData.get('bgColor'); |
| 6184 } else { |
| 6185 reason = 'bgContrast'; |
| 6186 } |
| 6187 axe.commons.color.incompleteData.set('fgColor', reason); |
| 6188 this.data({ |
| 6189 missingData: axe.commons.color.incompleteData.get('fgColor') |
| 6190 }); |
| 6191 axe.commons.color.incompleteData.clear(); |
| 6192 return undefined; |
| 6193 } |
| 6194 } |
| 6195 return false; |
| 6196 } |
| 6197 }, { |
| 6198 id: 'fieldset', |
| 6199 evaluate: function evaluate(node, options) { |
| 6200 var failureCode, self = this; |
| 6201 function getUnrelatedElements(parent, name) { |
| 6202 return axe.commons.utils.toArray(parent.querySelectorAll('select,texta
rea,button,input:not([name="' + name + '"]):not([type="hidden"])')); |
| 6203 } |
| 6204 function checkFieldset(group, name) { |
| 6205 var firstNode = group.firstElementChild; |
| 6206 if (!firstNode || firstNode.nodeName.toUpperCase() !== 'LEGEND') { |
| 6207 self.relatedNodes([ group ]); |
| 6208 failureCode = 'no-legend'; |
| 6209 return false; |
| 6210 } |
| 6211 if (!axe.commons.text.accessibleText(firstNode)) { |
| 6212 self.relatedNodes([ firstNode ]); |
| 6213 failureCode = 'empty-legend'; |
| 6214 return false; |
| 6215 } |
| 6216 var otherElements = getUnrelatedElements(group, name); |
| 6217 if (otherElements.length) { |
| 6218 self.relatedNodes(otherElements); |
| 6219 failureCode = 'mixed-inputs'; |
| 6220 return false; |
| 6221 } |
| 6222 return true; |
| 6223 } |
| 6224 function checkARIAGroup(group, name) { |
| 6225 var hasLabelledByText = axe.commons.dom.idrefs(group, 'aria-labelledby
').some(function(element) { |
| 6226 return element && axe.commons.text.accessibleText(element); |
| 6227 }); |
| 6228 var ariaLabel = group.getAttribute('aria-label'); |
| 6229 if (!hasLabelledByText && !(ariaLabel && axe.commons.text.sanitize(ari
aLabel))) { |
| 6230 self.relatedNodes(group); |
| 6231 failureCode = 'no-group-label'; |
| 6232 return false; |
| 6233 } |
| 6234 var otherElements = getUnrelatedElements(group, name); |
| 6235 if (otherElements.length) { |
| 6236 self.relatedNodes(otherElements); |
| 6237 failureCode = 'group-mixed-inputs'; |
| 6238 return false; |
| 6239 } |
| 6240 return true; |
| 6241 } |
| 6242 function spliceCurrentNode(nodes, current) { |
| 6243 return axe.commons.utils.toArray(nodes).filter(function(candidate) { |
| 6244 return candidate !== current; |
| 6245 }); |
| 6246 } |
| 6247 function runCheck(element) { |
| 6248 var name = axe.commons.utils.escapeSelector(node.name); |
| 6249 var matchingNodes = document.querySelectorAll('input[type="' + axe.com
mons.utils.escapeSelector(node.type) + '"][name="' + name + '"]'); |
| 6250 if (matchingNodes.length < 2) { |
| 6251 return true; |
| 6252 } |
| 6253 var fieldset = axe.commons.dom.findUp(element, 'fieldset'); |
| 6254 var group = axe.commons.dom.findUp(element, '[role="group"]' + (node.t
ype === 'radio' ? ',[role="radiogroup"]' : '')); |
| 6255 if (!group && !fieldset) { |
| 6256 failureCode = 'no-group'; |
| 6257 self.relatedNodes(spliceCurrentNode(matchingNodes, element)); |
| 6258 return false; |
| 6259 } |
| 6260 return fieldset ? checkFieldset(fieldset, name) : checkARIAGroup(group
, name); |
| 6261 } |
| 6262 var data = { |
| 6263 name: node.getAttribute('name'), |
| 6264 type: node.getAttribute('type') |
| 6265 }; |
| 6266 var result = runCheck(node); |
| 6267 if (!result) { |
| 6268 data.failureCode = failureCode; |
| 6269 } |
| 6270 this.data(data); |
| 6271 return result; |
| 6272 }, |
| 6273 after: function after(results, options) { |
| 6274 var seen = {}; |
| 6275 return results.filter(function(result) { |
| 6276 if (result.result) { |
| 6277 return true; |
| 6278 } |
| 6279 var data = result.data; |
| 6280 if (data) { |
| 6281 seen[data.type] = seen[data.type] || {}; |
| 6282 if (!seen[data.type][data.name]) { |
| 6283 seen[data.type][data.name] = [ data ]; |
| 6284 return true; |
| 6285 } |
| 6286 var hasBeenSeen = seen[data.type][data.name].some(function(candidate
) { |
| 6287 return candidate.failureCode === data.failureCode; |
| 6288 }); |
| 6289 if (!hasBeenSeen) { |
| 6290 seen[data.type][data.name].push(data); |
| 6291 } |
| 6292 return !hasBeenSeen; |
| 6293 } |
| 6294 return false; |
| 6295 }); |
| 6296 } |
| 6297 }, { |
| 6298 id: 'group-labelledby', |
| 6299 evaluate: function evaluate(node, options) { |
| 6300 this.data({ |
| 6301 name: node.getAttribute('name'), |
| 6302 type: node.getAttribute('type') |
| 6303 }); |
| 6304 var matchingNodes = document.querySelectorAll('input[type="' + axe.commo
ns.utils.escapeSelector(node.type) + '"][name="' + axe.commons.utils.escapeSelec
tor(node.name) + '"]'); |
| 6305 if (matchingNodes.length <= 1) { |
| 6306 return true; |
| 6307 } |
| 6308 return [].map.call(matchingNodes, function(m) { |
| 6309 var l = m.getAttribute('aria-labelledby'); |
| 6310 return l ? l.split(/\s+/) : []; |
| 6311 }).reduce(function(prev, curr) { |
| 6312 return prev.filter(function(n) { |
| 6313 return curr.indexOf(n) !== -1; |
| 6314 }); |
| 6315 }).filter(function(n) { |
| 6316 var labelNode = document.getElementById(n); |
| 6317 return labelNode && axe.commons.text.accessibleText(labelNode); |
| 6318 }).length !== 0; |
| 6319 }, |
| 6320 after: function after(results, options) { |
| 6321 var seen = {}; |
| 6322 return results.filter(function(result) { |
| 6323 var data = result.data; |
| 6324 if (data) { |
| 6325 seen[data.type] = seen[data.type] || {}; |
| 6326 if (!seen[data.type][data.name]) { |
| 6327 seen[data.type][data.name] = true; |
| 6328 return true; |
| 6329 } |
| 6330 } |
| 6331 return false; |
| 6332 }); |
| 6333 } |
| 6334 }, { |
| 6335 id: 'accesskeys', |
| 6336 evaluate: function evaluate(node, options) { |
| 6337 if (axe.commons.dom.isVisible(node, false)) { |
| 6338 this.data(node.getAttribute('accesskey')); |
| 6339 this.relatedNodes([ node ]); |
| 6340 } |
| 6341 return true; |
| 6342 }, |
| 6343 after: function after(results, options) { |
| 6344 var seen = {}; |
| 6345 return results.filter(function(r) { |
| 6346 if (!r.data) { |
| 6347 return false; |
| 6348 } |
| 6349 var key = r.data.toUpperCase(); |
| 6350 if (!seen[key]) { |
| 6351 seen[key] = r; |
| 6352 r.relatedNodes = []; |
| 6353 return true; |
| 6354 } |
| 6355 seen[key].relatedNodes.push(r.relatedNodes[0]); |
| 6356 return false; |
| 6357 }).map(function(r) { |
| 6358 r.result = !!r.relatedNodes.length; |
| 6359 return r; |
| 6360 }); |
| 6361 } |
| 6362 }, { |
| 6363 id: 'focusable-no-name', |
| 6364 evaluate: function evaluate(node, options) { |
| 6365 var tabIndex = node.getAttribute('tabindex'), isFocusable = axe.commons.
dom.isFocusable(node) && tabIndex > -1; |
| 6366 if (!isFocusable) { |
| 6367 return false; |
| 6368 } |
| 6369 return !axe.commons.text.accessibleText(node); |
| 6370 } |
| 6371 }, { |
| 6372 id: 'tabindex', |
| 6373 evaluate: function evaluate(node, options) { |
| 6374 return node.tabIndex <= 0; |
| 6375 } |
| 6376 }, { |
| 6377 id: 'duplicate-img-label', |
| 6378 evaluate: function evaluate(node, options) { |
| 6379 var imgs = node.querySelectorAll('img'); |
| 6380 var text = axe.commons.text.visible(node, true).toLowerCase(); |
| 6381 if (text === '') { |
| 6382 return false; |
| 6383 } |
| 6384 for (var i = 0, len = imgs.length; i < len; i++) { |
| 6385 var img = imgs[i]; |
| 6386 var imgAlt = axe.commons.text.accessibleText(img).toLowerCase(); |
| 6387 if (imgAlt === text && img.getAttribute('role') !== 'presentation' &&
axe.commons.dom.isVisible(img)) { |
| 6388 return true; |
| 6389 } |
| 6390 } |
| 6391 return false; |
| 6392 } |
| 6393 }, { |
| 6394 id: 'explicit-label', |
| 6395 evaluate: function evaluate(node, options) { |
| 6396 if (node.id) { |
| 6397 var label = document.querySelector('label[for="' + axe.commons.utils.e
scapeSelector(node.id) + '"]'); |
| 6398 if (label) { |
| 6399 return !!axe.commons.text.accessibleText(label); |
| 6400 } |
| 6401 } |
| 6402 return false; |
| 6403 } |
| 6404 }, { |
| 6405 id: 'help-same-as-label', |
| 6406 evaluate: function evaluate(node, options) { |
| 6407 var labelText = axe.commons.text.label(node), check = node.getAttribute(
'title'); |
| 6408 if (!labelText) { |
| 6409 return false; |
| 6410 } |
| 6411 if (!check) { |
| 6412 check = ''; |
| 6413 if (node.getAttribute('aria-describedby')) { |
| 6414 var ref = axe.commons.dom.idrefs(node, 'aria-describedby'); |
| 6415 check = ref.map(function(thing) { |
| 6416 return thing ? axe.commons.text.accessibleText(thing) : ''; |
| 6417 }).join(''); |
| 6418 } |
| 6419 } |
| 6420 return axe.commons.text.sanitize(check) === axe.commons.text.sanitize(la
belText); |
| 6421 }, |
| 6422 enabled: false |
| 6423 }, { |
| 6424 id: 'implicit-label', |
| 6425 evaluate: function evaluate(node, options) { |
| 6426 var label = axe.commons.dom.findUp(node, 'label'); |
| 6427 if (label) { |
| 6428 return !!axe.commons.text.accessibleText(label); |
| 6429 } |
| 6430 return false; |
| 6431 } |
| 6432 }, { |
| 6433 id: 'multiple-label', |
| 6434 evaluate: function evaluate(node, options) { |
| 6435 var labels = [].slice.call(document.querySelectorAll('label[for="' + axe
.commons.utils.escapeSelector(node.id) + '"]')), parent = node.parentNode; |
| 6436 if (labels.length) { |
| 6437 labels = labels.filter(function(label, index) { |
| 6438 if (index === 0 && !axe.commons.dom.isVisible(label, true) || axe.co
mmons.dom.isVisible(label, true)) { |
| 6439 return label; |
| 6440 } |
| 6441 }); |
| 6442 } |
| 6443 while (parent) { |
| 6444 if (parent.tagName === 'LABEL' && labels.indexOf(parent) === -1) { |
| 6445 labels.push(parent); |
| 6446 } |
| 6447 parent = parent.parentNode; |
| 6448 } |
| 6449 this.relatedNodes(labels); |
| 6450 return labels.length > 1; |
| 6451 } |
| 6452 }, { |
| 6453 id: 'title-only', |
| 6454 evaluate: function evaluate(node, options) { |
| 6455 var labelText = axe.commons.text.label(node); |
| 6456 return !labelText && !!(node.getAttribute('title') || node.getAttribute(
'aria-describedby')); |
| 6457 } |
| 6458 }, { |
| 6459 id: 'has-lang', |
| 6460 evaluate: function evaluate(node, options) { |
| 6461 return !!(node.getAttribute('lang') || node.getAttribute('xml:lang') ||
'').trim(); |
| 6462 } |
| 6463 }, { |
| 6464 id: 'valid-lang', |
| 6465 evaluate: function evaluate(node, options) { |
| 6466 function getBaseLang(lang) { |
| 6467 return lang.trim().split('-')[0].toLowerCase(); |
| 6468 } |
| 6469 var langs, invalid; |
| 6470 langs = (options ? options : axe.commons.utils.validLangs()).map(getBase
Lang); |
| 6471 invalid = [ 'lang', 'xml:lang' ].reduce(function(invalid, langAttr) { |
| 6472 var langVal = node.getAttribute(langAttr); |
| 6473 if (typeof langVal !== 'string') { |
| 6474 return invalid; |
| 6475 } |
| 6476 var baselangVal = getBaseLang(langVal); |
| 6477 if (baselangVal !== '' && langs.indexOf(baselangVal) === -1) { |
| 6478 invalid.push(langAttr + '="' + node.getAttribute(langAttr) + '"'); |
| 6479 } |
| 6480 return invalid; |
| 6481 }, []); |
| 6482 if (invalid.length) { |
| 6483 this.data(invalid); |
| 6484 return true; |
| 6485 } |
| 6486 return false; |
| 6487 } |
| 6488 }, { |
| 6489 id: 'dlitem', |
| 6490 evaluate: function evaluate(node, options) { |
| 6491 return node.parentNode.tagName === 'DL'; |
| 6492 } |
| 6493 }, { |
| 6494 id: 'has-listitem', |
| 6495 evaluate: function evaluate(node, options) { |
| 6496 var children = node.children; |
| 6497 if (children.length === 0) { |
| 6498 return true; |
| 6499 } |
| 6500 for (var i = 0; i < children.length; i++) { |
| 6501 if (children[i].nodeName.toUpperCase() === 'LI') { |
| 6502 return false; |
| 6503 } |
| 6504 } |
| 6505 return true; |
| 6506 } |
| 6507 }, { |
| 6508 id: 'listitem', |
| 6509 evaluate: function evaluate(node, options) { |
| 6510 if ([ 'UL', 'OL' ].indexOf(node.parentNode.nodeName.toUpperCase()) !== -
1) { |
| 6511 return true; |
| 6512 } |
| 6513 return node.parentNode.getAttribute('role') === 'list'; |
| 6514 } |
| 6515 }, { |
| 6516 id: 'only-dlitems', |
| 6517 evaluate: function evaluate(node, options) { |
| 6518 var child, nodeName, bad = [], children = node.childNodes, permitted = [
'STYLE', 'META', 'LINK', 'MAP', 'AREA', 'SCRIPT', 'DATALIST', 'TEMPLATE' ], has
NonEmptyTextNode = false; |
| 6519 for (var i = 0; i < children.length; i++) { |
| 6520 child = children[i]; |
| 6521 var nodeName = child.nodeName.toUpperCase(); |
| 6522 if (child.nodeType === 1 && nodeName !== 'DT' && nodeName !== 'DD' &&
permitted.indexOf(nodeName) === -1) { |
| 6523 bad.push(child); |
| 6524 } else if (child.nodeType === 3 && child.nodeValue.trim() !== '') { |
| 6525 hasNonEmptyTextNode = true; |
| 6526 } |
| 6527 } |
| 6528 if (bad.length) { |
| 6529 this.relatedNodes(bad); |
| 6530 } |
| 6531 var retVal = !!bad.length || hasNonEmptyTextNode; |
| 6532 return retVal; |
| 6533 } |
| 6534 }, { |
| 6535 id: 'only-listitems', |
| 6536 evaluate: function evaluate(node, options) { |
| 6537 var child, nodeName, bad = [], children = node.childNodes, permitted = [
'STYLE', 'META', 'LINK', 'MAP', 'AREA', 'SCRIPT', 'DATALIST', 'TEMPLATE' ], has
NonEmptyTextNode = false; |
| 6538 for (var i = 0; i < children.length; i++) { |
| 6539 child = children[i]; |
| 6540 nodeName = child.nodeName.toUpperCase(); |
| 6541 if (child.nodeType === 1 && nodeName !== 'LI' && permitted.indexOf(nod
eName) === -1) { |
| 6542 bad.push(child); |
| 6543 } else if (child.nodeType === 3 && child.nodeValue.trim() !== '') { |
| 6544 hasNonEmptyTextNode = true; |
| 6545 } |
| 6546 } |
| 6547 if (bad.length) { |
| 6548 this.relatedNodes(bad); |
| 6549 } |
| 6550 return !!bad.length || hasNonEmptyTextNode; |
| 6551 } |
| 6552 }, { |
| 6553 id: 'structured-dlitems', |
| 6554 evaluate: function evaluate(node, options) { |
| 6555 var children = node.children; |
| 6556 if (!children || !children.length) { |
| 6557 return false; |
| 6558 } |
| 6559 var hasDt = false, hasDd = false, nodeName; |
| 6560 for (var i = 0; i < children.length; i++) { |
| 6561 nodeName = children[i].nodeName.toUpperCase(); |
| 6562 if (nodeName === 'DT') { |
| 6563 hasDt = true; |
| 6564 } |
| 6565 if (hasDt && nodeName === 'DD') { |
| 6566 return false; |
| 6567 } |
| 6568 if (nodeName === 'DD') { |
| 6569 hasDd = true; |
| 6570 } |
| 6571 } |
| 6572 return hasDt || hasDd; |
| 6573 } |
| 6574 }, { |
| 6575 id: 'caption', |
| 6576 evaluate: function evaluate(node, options) { |
| 6577 var tracks = node.querySelectorAll('track'); |
| 6578 if (tracks.length) { |
| 6579 for (var i = 0; i < tracks.length; i++) { |
| 6580 var kind = tracks[i].getAttribute('kind'); |
| 6581 if (kind && kind === 'captions') { |
| 6582 return false; |
| 6583 } |
| 6584 } |
| 6585 return true; |
| 6586 } |
| 6587 return undefined; |
| 6588 } |
| 6589 }, { |
| 6590 id: 'description', |
| 6591 evaluate: function evaluate(node, options) { |
| 6592 var tracks = node.querySelectorAll('track'); |
| 6593 if (tracks.length) { |
| 6594 for (var i = 0; i < tracks.length; i++) { |
| 6595 var kind = tracks[i].getAttribute('kind'); |
| 6596 if (kind && kind === 'descriptions') { |
| 6597 return false; |
| 6598 } |
| 6599 } |
| 6600 return true; |
| 6601 } |
| 6602 return undefined; |
| 6603 } |
| 6604 }, { |
| 6605 id: 'meta-viewport-large', |
| 6606 evaluate: function evaluate(node, options) { |
| 6607 options = options || {}; |
| 6608 var params, content = node.getAttribute('content') || '', parsedParams =
content.split(/[;,]/), result = {}, minimum = options.scaleMinimum || 2, lowerB
ound = options.lowerBound || false; |
| 6609 for (var i = 0, l = parsedParams.length; i < l; i++) { |
| 6610 params = parsedParams[i].split('='); |
| 6611 var key = params.shift().toLowerCase(); |
| 6612 if (key && params.length) { |
| 6613 result[key.trim()] = params.shift().trim().toLowerCase(); |
| 6614 } |
| 6615 } |
| 6616 if (lowerBound && result['maximum-scale'] && parseFloat(result['maximum-
scale']) < lowerBound) { |
| 6617 return true; |
| 6618 } |
| 6619 if (!lowerBound && result['user-scalable'] === 'no') { |
| 6620 return false; |
| 6621 } |
| 6622 if (result['maximum-scale'] && parseFloat(result['maximum-scale']) < min
imum) { |
| 6623 return false; |
| 6624 } |
| 6625 return true; |
| 6626 }, |
| 6627 options: { |
| 6628 scaleMinimum: 5, |
| 6629 lowerBound: 2 |
| 6630 } |
| 6631 }, { |
| 6632 id: 'meta-viewport', |
| 6633 evaluate: function evaluate(node, options) { |
| 6634 options = options || {}; |
| 6635 var params, content = node.getAttribute('content') || '', parsedParams =
content.split(/[;,]/), result = {}, minimum = options.scaleMinimum || 2, lowerB
ound = options.lowerBound || false; |
| 6636 for (var i = 0, l = parsedParams.length; i < l; i++) { |
| 6637 params = parsedParams[i].split('='); |
| 6638 var key = params.shift().toLowerCase(); |
| 6639 if (key && params.length) { |
| 6640 result[key.trim()] = params.shift().trim().toLowerCase(); |
| 6641 } |
| 6642 } |
| 6643 if (lowerBound && result['maximum-scale'] && parseFloat(result['maximum-
scale']) < lowerBound) { |
| 6644 return true; |
| 6645 } |
| 6646 if (!lowerBound && result['user-scalable'] === 'no') { |
| 6647 return false; |
| 6648 } |
| 6649 if (result['maximum-scale'] && parseFloat(result['maximum-scale']) < min
imum) { |
| 6650 return false; |
| 6651 } |
| 6652 return true; |
| 6653 }, |
| 6654 options: { |
| 6655 scaleMinimum: 2 |
| 6656 } |
| 6657 }, { |
| 6658 id: 'header-present', |
| 6659 evaluate: function evaluate(node, options) { |
| 6660 return !!node.querySelector('h1, h2, h3, h4, h5, h6, [role="heading"]'); |
| 6661 } |
| 6662 }, { |
| 6663 id: 'heading-order', |
| 6664 evaluate: function evaluate(node, options) { |
| 6665 var ariaHeadingLevel = node.getAttribute('aria-level'); |
| 6666 if (ariaHeadingLevel !== null) { |
| 6667 this.data(parseInt(ariaHeadingLevel, 10)); |
| 6668 return true; |
| 6669 } |
| 6670 var headingLevel = node.tagName.match(/H(\d)/); |
| 6671 if (headingLevel) { |
| 6672 this.data(parseInt(headingLevel[1], 10)); |
| 6673 return true; |
| 6674 } |
| 6675 return true; |
| 6676 }, |
| 6677 after: function after(results, options) { |
| 6678 if (results.length < 2) { |
| 6679 return results; |
| 6680 } |
| 6681 var prevLevel = results[0].data; |
| 6682 for (var i = 1; i < results.length; i++) { |
| 6683 if (results[i].result && results[i].data > prevLevel + 1) { |
| 6684 results[i].result = false; |
| 6685 } |
| 6686 prevLevel = results[i].data; |
| 6687 } |
| 6688 return results; |
| 6689 } |
| 6690 }, { |
| 6691 id: 'href-no-hash', |
| 6692 evaluate: function evaluate(node, options) { |
| 6693 var href = node.getAttribute('href'); |
| 6694 if (href === '#') { |
| 6695 return false; |
| 6696 } |
| 6697 return true; |
| 6698 } |
| 6699 }, { |
| 6700 id: 'internal-link-present', |
| 6701 evaluate: function evaluate(node, options) { |
| 6702 return !!node.querySelector('a[href^="#"]'); |
| 6703 } |
| 6704 }, { |
| 6705 id: 'landmark', |
| 6706 evaluate: function evaluate(node, options) { |
| 6707 return node.getElementsByTagName('main').length > 0 || !!node.querySelec
tor('[role="main"]'); |
| 6708 } |
| 6709 }, { |
| 6710 id: 'meta-refresh', |
| 6711 evaluate: function evaluate(node, options) { |
| 6712 var content = node.getAttribute('content') || '', parsedParams = content
.split(/[;,]/); |
| 6713 return content === '' || parsedParams[0] === '0'; |
| 6714 } |
| 6715 }, { |
| 6716 id: 'p-as-heading', |
| 6717 evaluate: function evaluate(node, options) { |
| 6718 var siblings = Array.from(node.parentNode.children); |
| 6719 var currentIndex = siblings.indexOf(node); |
| 6720 options = options || {}; |
| 6721 var margins = options.margins || []; |
| 6722 var nextSibling = siblings.slice(currentIndex + 1).find(function(elm) { |
| 6723 return elm.nodeName.toUpperCase() === 'P'; |
| 6724 }); |
| 6725 var prevSibling = siblings.slice(0, currentIndex).reverse().find(functio
n(elm) { |
| 6726 return elm.nodeName.toUpperCase() === 'P'; |
| 6727 }); |
| 6728 function getTextContainer(elm) { |
| 6729 var nextNode = elm; |
| 6730 var outerText = elm.textContent.trim(); |
| 6731 var innerText = outerText; |
| 6732 while (innerText === outerText && nextNode !== undefined) { |
| 6733 var i = -1; |
| 6734 elm = nextNode; |
| 6735 if (elm.children.length === 0) { |
| 6736 return elm; |
| 6737 } |
| 6738 do { |
| 6739 i++; |
| 6740 innerText = elm.children[i].textContent.trim(); |
| 6741 } while (innerText === '' && i + 1 < elm.children.length); |
| 6742 nextNode = elm.children[i]; |
| 6743 } |
| 6744 return elm; |
| 6745 } |
| 6746 function normalizeFontWeight(weight) { |
| 6747 switch (weight) { |
| 6748 case 'lighter': |
| 6749 return 100; |
| 6750 |
| 6751 case 'normal': |
| 6752 return 400; |
| 6753 |
| 6754 case 'bold': |
| 6755 return 700; |
| 6756 |
| 6757 case 'bolder': |
| 6758 return 900; |
| 6759 } |
| 6760 weight = parseInt(weight); |
| 6761 return !isNaN(weight) ? weight : 400; |
| 6762 } |
| 6763 function getStyleValues(node) { |
| 6764 var style = window.getComputedStyle(getTextContainer(node)); |
| 6765 return { |
| 6766 fontWeight: normalizeFontWeight(style.getPropertyValue('font-weight'
)), |
| 6767 fontSize: parseInt(style.getPropertyValue('font-size')), |
| 6768 isItalic: style.getPropertyValue('font-style') === 'italic' |
| 6769 }; |
| 6770 } |
| 6771 function isHeaderStyle(styleA, styleB, margins) { |
| 6772 return margins.reduce(function(out, margin) { |
| 6773 return out || (!margin.size || styleA.fontSize / margin.size > style
B.fontSize) && (!margin.weight || styleA.fontWeight - margin.weight > styleB.fon
tWeight) && (!margin.italic || styleA.isItalic && !styleB.isItalic); |
| 6774 }, false); |
| 6775 } |
| 6776 var currStyle = getStyleValues(node); |
| 6777 var nextStyle = nextSibling ? getStyleValues(nextSibling) : null; |
| 6778 var prevStyle = prevSibling ? getStyleValues(prevSibling) : null; |
| 6779 if (!nextStyle || !isHeaderStyle(currStyle, nextStyle, margins)) { |
| 6780 return true; |
| 6781 } |
| 6782 var blockquote = axe.commons.dom.findUp(node, 'blockquote'); |
| 6783 if (blockquote && blockquote.nodeName.toUpperCase() === 'BLOCKQUOTE') { |
| 6784 return undefined; |
| 6785 } |
| 6786 if (prevStyle && !isHeaderStyle(currStyle, prevStyle, margins)) { |
| 6787 return undefined; |
| 6788 } |
| 6789 return false; |
| 6790 }, |
| 6791 options: { |
| 6792 margins: [ { |
| 6793 weight: 150, |
| 6794 italic: true |
| 6795 }, { |
| 6796 weight: 150, |
| 6797 size: 1.15 |
| 6798 }, { |
| 6799 italic: true, |
| 6800 size: 1.15 |
| 6801 }, { |
| 6802 size: 1.4 |
| 6803 } ] |
| 6804 } |
| 6805 }, { |
| 6806 id: 'region', |
| 6807 evaluate: function evaluate(node, options) { |
| 6808 var landmarkRoles = axe.commons.aria.getRolesByType('landmark'), firstLi
nk = node.querySelector('a[href]'); |
| 6809 function isSkipLink(n) { |
| 6810 return firstLink && axe.commons.dom.isFocusable(axe.commons.dom.getEle
mentByReference(firstLink, 'href')) && firstLink === n; |
| 6811 } |
| 6812 function isLandmark(n) { |
| 6813 var role = n.getAttribute('role'); |
| 6814 return role && landmarkRoles.indexOf(role) !== -1; |
| 6815 } |
| 6816 function checkRegion(n) { |
| 6817 if (isLandmark(n)) { |
| 6818 return null; |
| 6819 } |
| 6820 if (isSkipLink(n)) { |
| 6821 return getViolatingChildren(n); |
| 6822 } |
| 6823 if (axe.commons.dom.isVisible(n, true) && (axe.commons.text.visible(n,
true, true) || axe.commons.dom.isVisualContent(n))) { |
| 6824 return n; |
| 6825 } |
| 6826 return getViolatingChildren(n); |
| 6827 } |
| 6828 function getViolatingChildren(n) { |
| 6829 var children = axe.commons.utils.toArray(n.children); |
| 6830 if (children.length === 0) { |
| 6831 return []; |
| 6832 } |
| 6833 return children.map(checkRegion).filter(function(c) { |
| 6834 return c !== null; |
| 6835 }).reduce(function(a, b) { |
| 6836 return a.concat(b); |
| 6837 }, []); |
| 6838 } |
| 6839 var v = getViolatingChildren(node); |
| 6840 this.relatedNodes(v); |
| 6841 return !v.length; |
| 6842 }, |
| 6843 after: function after(results, options) { |
| 6844 return [ results[0] ]; |
| 6845 } |
| 6846 }, { |
| 6847 id: 'skip-link', |
| 6848 evaluate: function evaluate(node, options) { |
| 6849 return axe.commons.dom.isFocusable(axe.commons.dom.getElementByReference
(node, 'href')); |
| 6850 }, |
| 6851 after: function after(results, options) { |
| 6852 return [ results[0] ]; |
| 6853 } |
| 6854 }, { |
| 6855 id: 'unique-frame-title', |
| 6856 evaluate: function evaluate(node, options) { |
| 6857 var title = axe.commons.text.sanitize(node.title).trim().toLowerCase(); |
| 6858 this.data(title); |
| 6859 return true; |
| 6860 }, |
| 6861 after: function after(results, options) { |
| 6862 var titles = {}; |
| 6863 results.forEach(function(r) { |
| 6864 titles[r.data] = titles[r.data] !== undefined ? ++titles[r.data] : 0; |
| 6865 }); |
| 6866 results.forEach(function(r) { |
| 6867 r.result = !!titles[r.data]; |
| 6868 }); |
| 6869 return results; |
| 6870 } |
| 6871 }, { |
| 6872 id: 'aria-label', |
| 6873 evaluate: function evaluate(node, options) { |
| 6874 var label = node.getAttribute('aria-label'); |
| 6875 return !!(label ? axe.commons.text.sanitize(label).trim() : ''); |
| 6876 } |
| 6877 }, { |
| 6878 id: 'aria-labelledby', |
| 6879 evaluate: function evaluate(node, options) { |
| 6880 var getIdRefs = axe.commons.dom.idrefs; |
| 6881 return getIdRefs(node, 'aria-labelledby').some(function(elm) { |
| 6882 return elm && axe.commons.text.accessibleText(elm, true); |
| 6883 }); |
| 6884 } |
| 6885 }, { |
| 6886 id: 'button-has-visible-text', |
| 6887 evaluate: function evaluate(node, options) { |
| 6888 var nodeName = node.nodeName.toUpperCase(); |
| 6889 var role = node.getAttribute('role'); |
| 6890 var label = void 0; |
| 6891 if (nodeName === 'BUTTON' || role === 'button' && nodeName !== 'INPUT')
{ |
| 6892 label = axe.commons.text.accessibleText(node); |
| 6893 this.data(label); |
| 6894 return !!label; |
| 6895 } else { |
| 6896 return false; |
| 6897 } |
| 6898 } |
| 6899 }, { |
| 6900 id: 'doc-has-title', |
| 6901 evaluate: function evaluate(node, options) { |
| 6902 var title = document.title; |
| 6903 return !!(title ? axe.commons.text.sanitize(title).trim() : ''); |
| 6904 } |
| 6905 }, { |
| 6906 id: 'duplicate-id', |
| 6907 evaluate: function evaluate(node, options) { |
| 6908 if (!node.id.trim()) { |
| 6909 return true; |
| 6910 } |
| 6911 var matchingNodes = document.querySelectorAll('[id="' + axe.commons.util
s.escapeSelector(node.id) + '"]'); |
| 6912 var related = []; |
| 6913 for (var i = 0; i < matchingNodes.length; i++) { |
| 6914 if (matchingNodes[i] !== node) { |
| 6915 related.push(matchingNodes[i]); |
| 6916 } |
| 6917 } |
| 6918 if (related.length) { |
| 6919 this.relatedNodes(related); |
| 6920 } |
| 6921 this.data(node.getAttribute('id')); |
| 6922 return matchingNodes.length <= 1; |
| 6923 }, |
| 6924 after: function after(results, options) { |
| 6925 var uniqueIds = []; |
| 6926 return results.filter(function(r) { |
| 6927 if (uniqueIds.indexOf(r.data) === -1) { |
| 6928 uniqueIds.push(r.data); |
| 6929 return true; |
| 6930 } |
| 6931 return false; |
| 6932 }); |
| 6933 } |
| 6934 }, { |
| 6935 id: 'exists', |
| 6936 evaluate: function evaluate(node, options) { |
| 6937 return true; |
| 6938 } |
| 6939 }, { |
| 6940 id: 'has-alt', |
| 6941 evaluate: function evaluate(node, options) { |
| 6942 var nn = node.nodeName.toLowerCase(); |
| 6943 return node.hasAttribute('alt') && (nn === 'img' || nn === 'input' || nn
=== 'area'); |
| 6944 } |
| 6945 }, { |
| 6946 id: 'has-visible-text', |
| 6947 evaluate: function evaluate(node, options) { |
| 6948 return axe.commons.text.accessibleText(node).length > 0; |
| 6949 } |
| 6950 }, { |
| 6951 id: 'is-on-screen', |
| 6952 evaluate: function evaluate(node, options) { |
| 6953 return axe.commons.dom.isVisible(node, false) && !axe.commons.dom.isOffs
creen(node); |
| 6954 } |
| 6955 }, { |
| 6956 id: 'non-empty-alt', |
| 6957 evaluate: function evaluate(node, options) { |
| 6958 var label = node.getAttribute('alt'); |
| 6959 return !!(label ? axe.commons.text.sanitize(label).trim() : ''); |
| 6960 } |
| 6961 }, { |
| 6962 id: 'non-empty-if-present', |
| 6963 evaluate: function evaluate(node, options) { |
| 6964 var nodeName = node.nodeName.toUpperCase(); |
| 6965 var type = (node.getAttribute('type') || '').toLowerCase(); |
| 6966 var label = node.getAttribute('value'); |
| 6967 this.data(label); |
| 6968 if (nodeName === 'INPUT' && [ 'submit', 'reset' ].indexOf(type) !== -1)
{ |
| 6969 return label === null; |
| 6970 } |
| 6971 return false; |
| 6972 } |
| 6973 }, { |
| 6974 id: 'non-empty-title', |
| 6975 evaluate: function evaluate(node, options) { |
| 6976 var title = node.getAttribute('title'); |
| 6977 return !!(title ? axe.commons.text.sanitize(title).trim() : ''); |
| 6978 } |
| 6979 }, { |
| 6980 id: 'non-empty-value', |
| 6981 evaluate: function evaluate(node, options) { |
| 6982 var label = node.getAttribute('value'); |
| 6983 return !!(label ? axe.commons.text.sanitize(label).trim() : ''); |
| 6984 } |
| 6985 }, { |
| 6986 id: 'role-none', |
| 6987 evaluate: function evaluate(node, options) { |
| 6988 return node.getAttribute('role') === 'none'; |
| 6989 } |
| 6990 }, { |
| 6991 id: 'role-presentation', |
| 6992 evaluate: function evaluate(node, options) { |
| 6993 return node.getAttribute('role') === 'presentation'; |
| 6994 } |
| 6995 }, { |
| 6996 id: 'caption-faked', |
| 6997 evaluate: function evaluate(node, options) { |
| 6998 var table = axe.commons.table.toGrid(node); |
| 6999 var firstRow = table[0]; |
| 7000 if (table.length <= 1 || firstRow.length <= 1 || node.rows.length <= 1)
{ |
| 7001 return true; |
| 7002 } |
| 7003 return firstRow.reduce(function(out, curr, i) { |
| 7004 return out || curr !== firstRow[i + 1] && firstRow[i + 1] !== undefine
d; |
| 7005 }, false); |
| 7006 } |
| 7007 }, { |
| 7008 id: 'has-caption', |
| 7009 evaluate: function evaluate(node, options) { |
| 7010 return !!node.caption; |
| 7011 } |
| 7012 }, { |
| 7013 id: 'has-summary', |
| 7014 evaluate: function evaluate(node, options) { |
| 7015 return !!node.summary; |
| 7016 } |
| 7017 }, { |
| 7018 id: 'has-th', |
| 7019 evaluate: function evaluate(node, options) { |
| 7020 var row, cell, badCells = []; |
| 7021 for (var rowIndex = 0, rowLength = node.rows.length; rowIndex < rowLengt
h; rowIndex++) { |
| 7022 row = node.rows[rowIndex]; |
| 7023 for (var cellIndex = 0, cellLength = row.cells.length; cellIndex < cel
lLength; cellIndex++) { |
| 7024 cell = row.cells[cellIndex]; |
| 7025 if (cell.nodeName.toUpperCase() === 'TH' || [ 'rowheader', 'columnhe
ader' ].indexOf(cell.getAttribute('role')) !== -1) { |
| 7026 badCells.push(cell); |
| 7027 } |
| 7028 } |
| 7029 } |
| 7030 if (badCells.length) { |
| 7031 this.relatedNodes(badCells); |
| 7032 return true; |
| 7033 } |
| 7034 return false; |
| 7035 } |
| 7036 }, { |
| 7037 id: 'html5-scope', |
| 7038 evaluate: function evaluate(node, options) { |
| 7039 if (!axe.commons.dom.isHTML5(document)) { |
| 7040 return true; |
| 7041 } |
| 7042 return node.nodeName.toUpperCase() === 'TH'; |
| 7043 } |
| 7044 }, { |
| 7045 id: 'same-caption-summary', |
| 7046 evaluate: function evaluate(node, options) { |
| 7047 return !!(node.summary && node.caption) && node.summary === axe.commons.
text.accessibleText(node.caption); |
| 7048 } |
| 7049 }, { |
| 7050 id: 'scope-value', |
| 7051 evaluate: function evaluate(node, options) { |
| 7052 options = options || {}; |
| 7053 var value = node.getAttribute('scope').toLowerCase(); |
| 7054 var validVals = [ 'row', 'col', 'rowgroup', 'colgroup' ] || options.valu
es; |
| 7055 return validVals.indexOf(value) !== -1; |
| 7056 } |
| 7057 }, { |
| 7058 id: 'td-has-header', |
| 7059 evaluate: function evaluate(node, options) { |
| 7060 var tableUtils = axe.commons.table; |
| 7061 var badCells = []; |
| 7062 var cells = tableUtils.getAllCells(node); |
| 7063 cells.forEach(function(cell) { |
| 7064 if (axe.commons.dom.hasContent(cell) && tableUtils.isDataCell(cell) &&
!axe.commons.aria.label(cell)) { |
| 7065 var hasHeaders = tableUtils.getHeaders(cell); |
| 7066 hasHeaders = hasHeaders.reduce(function(hasHeaders, header) { |
| 7067 return hasHeaders || header !== null && !!axe.commons.dom.hasConte
nt(header); |
| 7068 }, false); |
| 7069 if (!hasHeaders) { |
| 7070 badCells.push(cell); |
| 7071 } |
| 7072 } |
| 7073 }); |
| 7074 if (badCells.length) { |
| 7075 this.relatedNodes(badCells); |
| 7076 return false; |
| 7077 } |
| 7078 return true; |
| 7079 } |
| 7080 }, { |
| 7081 id: 'td-headers-attr', |
| 7082 evaluate: function evaluate(node, options) { |
| 7083 var cells = []; |
| 7084 for (var rowIndex = 0, rowLength = node.rows.length; rowIndex < rowLengt
h; rowIndex++) { |
| 7085 var row = node.rows[rowIndex]; |
| 7086 for (var cellIndex = 0, cellLength = row.cells.length; cellIndex < cel
lLength; cellIndex++) { |
| 7087 cells.push(row.cells[cellIndex]); |
| 7088 } |
| 7089 } |
| 7090 var ids = cells.reduce(function(ids, cell) { |
| 7091 if (cell.id) { |
| 7092 ids.push(cell.id); |
| 7093 } |
| 7094 return ids; |
| 7095 }, []); |
| 7096 var badCells = cells.reduce(function(badCells, cell) { |
| 7097 var isSelf, notOfTable; |
| 7098 var headers = (cell.getAttribute('headers') || '').split(/\s/).reduce(
function(headers, header) { |
| 7099 header = header.trim(); |
| 7100 if (header) { |
| 7101 headers.push(header); |
| 7102 } |
| 7103 return headers; |
| 7104 }, []); |
| 7105 if (headers.length !== 0) { |
| 7106 if (cell.id) { |
| 7107 isSelf = headers.indexOf(cell.id.trim()) !== -1; |
| 7108 } |
| 7109 notOfTable = headers.reduce(function(fail, header) { |
| 7110 return fail || ids.indexOf(header) === -1; |
| 7111 }, false); |
| 7112 if (isSelf || notOfTable) { |
| 7113 badCells.push(cell); |
| 7114 } |
| 7115 } |
| 7116 return badCells; |
| 7117 }, []); |
| 7118 if (badCells.length > 0) { |
| 7119 this.relatedNodes(badCells); |
| 7120 return false; |
| 7121 } else { |
| 7122 return true; |
| 7123 } |
| 7124 } |
| 7125 }, { |
| 7126 id: 'th-has-data-cells', |
| 7127 evaluate: function evaluate(node, options) { |
| 7128 var tableUtils = axe.commons.table; |
| 7129 var cells = tableUtils.getAllCells(node); |
| 7130 var checkResult = this; |
| 7131 var reffedHeaders = []; |
| 7132 cells.forEach(function(cell) { |
| 7133 var headers = cell.getAttribute('headers'); |
| 7134 if (headers) { |
| 7135 reffedHeaders = reffedHeaders.concat(headers.split(/\s+/)); |
| 7136 } |
| 7137 var ariaLabel = cell.getAttribute('aria-labelledby'); |
| 7138 if (ariaLabel) { |
| 7139 reffedHeaders = reffedHeaders.concat(ariaLabel.split(/\s+/)); |
| 7140 } |
| 7141 }); |
| 7142 var headers = cells.filter(function(cell) { |
| 7143 if (axe.commons.text.sanitize(cell.textContent) === '') { |
| 7144 return false; |
| 7145 } |
| 7146 return cell.nodeName.toUpperCase() === 'TH' || [ 'rowheader', 'columnh
eader' ].indexOf(cell.getAttribute('role')) !== -1; |
| 7147 }); |
| 7148 var tableGrid = tableUtils.toGrid(node); |
| 7149 var out = headers.reduce(function(res, header) { |
| 7150 if (header.id && reffedHeaders.indexOf(header.id) !== -1) { |
| 7151 return !res ? res : true; |
| 7152 } |
| 7153 var hasCell = false; |
| 7154 var pos = tableUtils.getCellPosition(header, tableGrid); |
| 7155 if (tableUtils.isColumnHeader(header)) { |
| 7156 hasCell = tableUtils.traverse('down', pos, tableGrid).reduce(functio
n(out, cell) { |
| 7157 return out || axe.commons.dom.hasContent(cell) && !tableUtils.isCo
lumnHeader(cell); |
| 7158 }, false); |
| 7159 } |
| 7160 if (!hasCell && tableUtils.isRowHeader(header)) { |
| 7161 hasCell = tableUtils.traverse('right', pos, tableGrid).reduce(functi
on(out, cell) { |
| 7162 return out || axe.commons.dom.hasContent(cell) && !tableUtils.isRo
wHeader(cell); |
| 7163 }, false); |
| 7164 } |
| 7165 if (!hasCell) { |
| 7166 checkResult.relatedNodes(header); |
| 7167 } |
| 7168 return res && hasCell; |
| 7169 }, true); |
| 7170 return out ? true : undefined; |
| 7171 } |
| 7172 }, { |
| 7173 id: 'hidden-content', |
| 7174 evaluate: function evaluate(node, options) { |
| 7175 var styles = window.getComputedStyle(node); |
| 7176 var whitelist = [ 'SCRIPT', 'HEAD', 'TITLE', 'NOSCRIPT', 'STYLE', 'TEMPL
ATE' ]; |
| 7177 if (!whitelist.includes(node.tagName.toUpperCase()) && axe.commons.dom.h
asContent(node)) { |
| 7178 if (styles.getPropertyValue('display') === 'none') { |
| 7179 return undefined; |
| 7180 } else if (styles.getPropertyValue('visibility') === 'hidden') { |
| 7181 if (node.parentNode) { |
| 7182 var parentStyle = window.getComputedStyle(node.parentNode); |
| 7183 } |
| 7184 if (!parentStyle || parentStyle.getPropertyValue('visibility') !== '
hidden') { |
| 7185 return undefined; |
| 7186 } |
| 7187 } |
| 7188 } |
| 7189 return true; |
| 7190 } |
| 7191 } ], |
| 7192 commons: function() { |
| 7193 var commons = {}; |
| 7194 var aria = commons.aria = {}, lookupTables = aria._lut = {}; |
| 7195 lookupTables.attributes = { |
| 7196 'aria-activedescendant': { |
| 7197 type: 'idref' |
| 7198 }, |
| 7199 'aria-atomic': { |
| 7200 type: 'boolean', |
| 7201 values: [ 'true', 'false' ] |
| 7202 }, |
| 7203 'aria-autocomplete': { |
| 7204 type: 'nmtoken', |
| 7205 values: [ 'inline', 'list', 'both', 'none' ] |
| 7206 }, |
| 7207 'aria-busy': { |
| 7208 type: 'boolean', |
| 7209 values: [ 'true', 'false' ] |
| 7210 }, |
| 7211 'aria-checked': { |
| 7212 type: 'nmtoken', |
| 7213 values: [ 'true', 'false', 'mixed', 'undefined' ] |
| 7214 }, |
| 7215 'aria-colcount': { |
| 7216 type: 'int' |
| 7217 }, |
| 7218 'aria-colindex': { |
| 7219 type: 'int' |
| 7220 }, |
| 7221 'aria-colspan': { |
| 7222 type: 'int' |
| 7223 }, |
| 7224 'aria-controls': { |
| 7225 type: 'idrefs' |
| 7226 }, |
| 7227 'aria-current': { |
| 7228 type: 'nmtoken', |
| 7229 values: [ 'page', 'step', 'location', 'date', 'time', 'true', 'false'
] |
| 7230 }, |
| 7231 'aria-describedby': { |
| 7232 type: 'idrefs' |
| 7233 }, |
| 7234 'aria-disabled': { |
| 7235 type: 'boolean', |
| 7236 values: [ 'true', 'false' ] |
| 7237 }, |
| 7238 'aria-dropeffect': { |
| 7239 type: 'nmtokens', |
| 7240 values: [ 'copy', 'move', 'reference', 'execute', 'popup', 'none' ] |
| 7241 }, |
| 7242 'aria-expanded': { |
| 7243 type: 'nmtoken', |
| 7244 values: [ 'true', 'false', 'undefined' ] |
| 7245 }, |
| 7246 'aria-flowto': { |
| 7247 type: 'idrefs' |
| 7248 }, |
| 7249 'aria-grabbed': { |
| 7250 type: 'nmtoken', |
| 7251 values: [ 'true', 'false', 'undefined' ] |
| 7252 }, |
| 7253 'aria-haspopup': { |
| 7254 type: 'boolean', |
| 7255 values: [ 'true', 'false' ] |
| 7256 }, |
| 7257 'aria-hidden': { |
| 7258 type: 'boolean', |
| 7259 values: [ 'true', 'false' ] |
| 7260 }, |
| 7261 'aria-invalid': { |
| 7262 type: 'nmtoken', |
| 7263 values: [ 'true', 'false', 'spelling', 'grammar' ] |
| 7264 }, |
| 7265 'aria-label': { |
| 7266 type: 'string' |
| 7267 }, |
| 7268 'aria-labelledby': { |
| 7269 type: 'idrefs' |
| 7270 }, |
| 7271 'aria-level': { |
| 7272 type: 'int' |
| 7273 }, |
| 7274 'aria-live': { |
| 7275 type: 'nmtoken', |
| 7276 values: [ 'off', 'polite', 'assertive' ] |
| 7277 }, |
| 7278 'aria-multiline': { |
| 7279 type: 'boolean', |
| 7280 values: [ 'true', 'false' ] |
| 7281 }, |
| 7282 'aria-multiselectable': { |
| 7283 type: 'boolean', |
| 7284 values: [ 'true', 'false' ] |
| 7285 }, |
| 7286 'aria-orientation': { |
| 7287 type: 'nmtoken', |
| 7288 values: [ 'horizontal', 'vertical' ] |
| 7289 }, |
| 7290 'aria-owns': { |
| 7291 type: 'idrefs' |
| 7292 }, |
| 7293 'aria-posinset': { |
| 7294 type: 'int' |
| 7295 }, |
| 7296 'aria-pressed': { |
| 7297 type: 'nmtoken', |
| 7298 values: [ 'true', 'false', 'mixed', 'undefined' ] |
| 7299 }, |
| 7300 'aria-readonly': { |
| 7301 type: 'boolean', |
| 7302 values: [ 'true', 'false' ] |
| 7303 }, |
| 7304 'aria-relevant': { |
| 7305 type: 'nmtokens', |
| 7306 values: [ 'additions', 'removals', 'text', 'all' ] |
| 7307 }, |
| 7308 'aria-required': { |
| 7309 type: 'boolean', |
| 7310 values: [ 'true', 'false' ] |
| 7311 }, |
| 7312 'aria-rowcount': { |
| 7313 type: 'int' |
| 7314 }, |
| 7315 'aria-rowindex': { |
| 7316 type: 'int' |
| 7317 }, |
| 7318 'aria-rowspan': { |
| 7319 type: 'int' |
| 7320 }, |
| 7321 'aria-selected': { |
| 7322 type: 'nmtoken', |
| 7323 values: [ 'true', 'false', 'undefined' ] |
| 7324 }, |
| 7325 'aria-setsize': { |
| 7326 type: 'int' |
| 7327 }, |
| 7328 'aria-sort': { |
| 7329 type: 'nmtoken', |
| 7330 values: [ 'ascending', 'descending', 'other', 'none' ] |
| 7331 }, |
| 7332 'aria-valuemax': { |
| 7333 type: 'decimal' |
| 7334 }, |
| 7335 'aria-valuemin': { |
| 7336 type: 'decimal' |
| 7337 }, |
| 7338 'aria-valuenow': { |
| 7339 type: 'decimal' |
| 7340 }, |
| 7341 'aria-valuetext': { |
| 7342 type: 'string' |
| 7343 } |
| 7344 }; |
| 7345 lookupTables.globalAttributes = [ 'aria-atomic', 'aria-busy', 'aria-contro
ls', 'aria-current', 'aria-describedby', 'aria-disabled', 'aria-dropeffect', 'ar
ia-flowto', 'aria-grabbed', 'aria-haspopup', 'aria-hidden', 'aria-invalid', 'ari
a-label', 'aria-labelledby', 'aria-live', 'aria-owns', 'aria-relevant' ]; |
| 7346 lookupTables.role = { |
| 7347 alert: { |
| 7348 type: 'widget', |
| 7349 attributes: { |
| 7350 allowed: [ 'aria-expanded' ] |
| 7351 }, |
| 7352 owned: null, |
| 7353 nameFrom: [ 'author' ], |
| 7354 context: null |
| 7355 }, |
| 7356 alertdialog: { |
| 7357 type: 'widget', |
| 7358 attributes: { |
| 7359 allowed: [ 'aria-expanded' ] |
| 7360 }, |
| 7361 owned: null, |
| 7362 nameFrom: [ 'author' ], |
| 7363 context: null |
| 7364 }, |
| 7365 application: { |
| 7366 type: 'landmark', |
| 7367 attributes: { |
| 7368 allowed: [ 'aria-expanded' ] |
| 7369 }, |
| 7370 owned: null, |
| 7371 nameFrom: [ 'author' ], |
| 7372 context: null |
| 7373 }, |
| 7374 article: { |
| 7375 type: 'structure', |
| 7376 attributes: { |
| 7377 allowed: [ 'aria-expanded' ] |
| 7378 }, |
| 7379 owned: null, |
| 7380 nameFrom: [ 'author' ], |
| 7381 context: null, |
| 7382 implicit: [ 'article' ] |
| 7383 }, |
| 7384 banner: { |
| 7385 type: 'landmark', |
| 7386 attributes: { |
| 7387 allowed: [ 'aria-expanded' ] |
| 7388 }, |
| 7389 owned: null, |
| 7390 nameFrom: [ 'author' ], |
| 7391 context: null, |
| 7392 implicit: [ 'header' ] |
| 7393 }, |
| 7394 button: { |
| 7395 type: 'widget', |
| 7396 attributes: { |
| 7397 allowed: [ 'aria-expanded', 'aria-pressed' ] |
| 7398 }, |
| 7399 owned: null, |
| 7400 nameFrom: [ 'author', 'contents' ], |
| 7401 context: null, |
| 7402 implicit: [ 'button', 'input[type="button"]', 'input[type="image"]', '
input[type="reset"]', 'input[type="submit"]', 'summary' ] |
| 7403 }, |
| 7404 cell: { |
| 7405 type: 'structure', |
| 7406 attributes: { |
| 7407 allowed: [ 'aria-colindex', 'aria-colspan', 'aria-rowindex', 'aria-r
owspan' ] |
| 7408 }, |
| 7409 owned: null, |
| 7410 nameFrom: [ 'author', 'contents' ], |
| 7411 context: [ 'row' ], |
| 7412 implicit: [ 'td', 'th' ] |
| 7413 }, |
| 7414 checkbox: { |
| 7415 type: 'widget', |
| 7416 attributes: { |
| 7417 required: [ 'aria-checked' ] |
| 7418 }, |
| 7419 owned: null, |
| 7420 nameFrom: [ 'author', 'contents' ], |
| 7421 context: null, |
| 7422 implicit: [ 'input[type="checkbox"]' ] |
| 7423 }, |
| 7424 columnheader: { |
| 7425 type: 'structure', |
| 7426 attributes: { |
| 7427 allowed: [ 'aria-expanded', 'aria-sort', 'aria-readonly', 'aria-sele
cted', 'aria-required' ] |
| 7428 }, |
| 7429 owned: null, |
| 7430 nameFrom: [ 'author', 'contents' ], |
| 7431 context: [ 'row' ], |
| 7432 implicit: [ 'th' ] |
| 7433 }, |
| 7434 combobox: { |
| 7435 type: 'composite', |
| 7436 attributes: { |
| 7437 required: [ 'aria-expanded' ], |
| 7438 allowed: [ 'aria-autocomplete', 'aria-required', 'aria-activedescend
ant' ] |
| 7439 }, |
| 7440 owned: { |
| 7441 all: [ 'listbox', 'textbox' ] |
| 7442 }, |
| 7443 nameFrom: [ 'author' ], |
| 7444 context: null |
| 7445 }, |
| 7446 command: { |
| 7447 nameFrom: [ 'author' ], |
| 7448 type: 'abstract' |
| 7449 }, |
| 7450 complementary: { |
| 7451 type: 'landmark', |
| 7452 attributes: { |
| 7453 allowed: [ 'aria-expanded' ] |
| 7454 }, |
| 7455 owned: null, |
| 7456 nameFrom: [ 'author' ], |
| 7457 context: null, |
| 7458 implicit: [ 'aside' ] |
| 7459 }, |
| 7460 composite: { |
| 7461 nameFrom: [ 'author' ], |
| 7462 type: 'abstract' |
| 7463 }, |
| 7464 contentinfo: { |
| 7465 type: 'landmark', |
| 7466 attributes: { |
| 7467 allowed: [ 'aria-expanded' ] |
| 7468 }, |
| 7469 owned: null, |
| 7470 nameFrom: [ 'author' ], |
| 7471 context: null, |
| 7472 implicit: [ 'footer' ] |
| 7473 }, |
| 7474 definition: { |
| 7475 type: 'structure', |
| 7476 attributes: { |
| 7477 allowed: [ 'aria-expanded' ] |
| 7478 }, |
| 7479 owned: null, |
| 7480 nameFrom: [ 'author' ], |
| 7481 context: null, |
| 7482 implicit: [ 'dd' ] |
| 7483 }, |
| 7484 dialog: { |
| 7485 type: 'widget', |
| 7486 attributes: { |
| 7487 allowed: [ 'aria-expanded' ] |
| 7488 }, |
| 7489 owned: null, |
| 7490 nameFrom: [ 'author' ], |
| 7491 context: null, |
| 7492 implicit: [ 'dialog' ] |
| 7493 }, |
| 7494 directory: { |
| 7495 type: 'structure', |
| 7496 attributes: { |
| 7497 allowed: [ 'aria-expanded' ] |
| 7498 }, |
| 7499 owned: null, |
| 7500 nameFrom: [ 'author', 'contents' ], |
| 7501 context: null |
| 7502 }, |
| 7503 document: { |
| 7504 type: 'structure', |
| 7505 attributes: { |
| 7506 allowed: [ 'aria-expanded' ] |
| 7507 }, |
| 7508 owned: null, |
| 7509 nameFrom: [ 'author' ], |
| 7510 context: null, |
| 7511 implicit: [ 'body' ] |
| 7512 }, |
| 7513 form: { |
| 7514 type: 'landmark', |
| 7515 attributes: { |
| 7516 allowed: [ 'aria-expanded' ] |
| 7517 }, |
| 7518 owned: null, |
| 7519 nameFrom: [ 'author' ], |
| 7520 context: null, |
| 7521 implicit: [ 'form' ] |
| 7522 }, |
| 7523 grid: { |
| 7524 type: 'composite', |
| 7525 attributes: { |
| 7526 allowed: [ 'aria-level', 'aria-multiselectable', 'aria-readonly', 'a
ria-activedescendant', 'aria-expanded' ] |
| 7527 }, |
| 7528 owned: { |
| 7529 one: [ 'rowgroup', 'row' ] |
| 7530 }, |
| 7531 nameFrom: [ 'author' ], |
| 7532 context: null, |
| 7533 implicit: [ 'table' ] |
| 7534 }, |
| 7535 gridcell: { |
| 7536 type: 'widget', |
| 7537 attributes: { |
| 7538 allowed: [ 'aria-selected', 'aria-readonly', 'aria-expanded', 'aria-
required' ] |
| 7539 }, |
| 7540 owned: null, |
| 7541 nameFrom: [ 'author', 'contents' ], |
| 7542 context: [ 'row' ], |
| 7543 implicit: [ 'td', 'th' ] |
| 7544 }, |
| 7545 group: { |
| 7546 type: 'structure', |
| 7547 attributes: { |
| 7548 allowed: [ 'aria-activedescendant', 'aria-expanded' ] |
| 7549 }, |
| 7550 owned: null, |
| 7551 nameFrom: [ 'author' ], |
| 7552 context: null, |
| 7553 implicit: [ 'details', 'optgroup' ] |
| 7554 }, |
| 7555 heading: { |
| 7556 type: 'structure', |
| 7557 attributes: { |
| 7558 allowed: [ 'aria-level', 'aria-expanded' ] |
| 7559 }, |
| 7560 owned: null, |
| 7561 nameFrom: [ 'author', 'contents' ], |
| 7562 context: null, |
| 7563 implicit: [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' ] |
| 7564 }, |
| 7565 img: { |
| 7566 type: 'structure', |
| 7567 attributes: { |
| 7568 allowed: [ 'aria-expanded' ] |
| 7569 }, |
| 7570 owned: null, |
| 7571 nameFrom: [ 'author' ], |
| 7572 context: null, |
| 7573 implicit: [ 'img' ] |
| 7574 }, |
| 7575 input: { |
| 7576 nameFrom: [ 'author' ], |
| 7577 type: 'abstract' |
| 7578 }, |
| 7579 landmark: { |
| 7580 nameFrom: [ 'author' ], |
| 7581 type: 'abstract' |
| 7582 }, |
| 7583 link: { |
| 7584 type: 'widget', |
| 7585 attributes: { |
| 7586 allowed: [ 'aria-expanded' ] |
| 7587 }, |
| 7588 owned: null, |
| 7589 nameFrom: [ 'author', 'contents' ], |
| 7590 context: null, |
| 7591 implicit: [ 'a[href]' ] |
| 7592 }, |
| 7593 list: { |
| 7594 type: 'structure', |
| 7595 attributes: { |
| 7596 allowed: [ 'aria-expanded' ] |
| 7597 }, |
| 7598 owned: { |
| 7599 all: [ 'listitem' ] |
| 7600 }, |
| 7601 nameFrom: [ 'author' ], |
| 7602 context: null, |
| 7603 implicit: [ 'ol', 'ul', 'dl' ] |
| 7604 }, |
| 7605 listbox: { |
| 7606 type: 'composite', |
| 7607 attributes: { |
| 7608 allowed: [ 'aria-activedescendant', 'aria-multiselectable', 'aria-re
quired', 'aria-expanded' ] |
| 7609 }, |
| 7610 owned: { |
| 7611 all: [ 'option' ] |
| 7612 }, |
| 7613 nameFrom: [ 'author' ], |
| 7614 context: null, |
| 7615 implicit: [ 'select' ] |
| 7616 }, |
| 7617 listitem: { |
| 7618 type: 'structure', |
| 7619 attributes: { |
| 7620 allowed: [ 'aria-level', 'aria-posinset', 'aria-setsize', 'aria-expa
nded' ] |
| 7621 }, |
| 7622 owned: null, |
| 7623 nameFrom: [ 'author', 'contents' ], |
| 7624 context: [ 'list' ], |
| 7625 implicit: [ 'li', 'dt' ] |
| 7626 }, |
| 7627 log: { |
| 7628 type: 'widget', |
| 7629 attributes: { |
| 7630 allowed: [ 'aria-expanded' ] |
| 7631 }, |
| 7632 owned: null, |
| 7633 nameFrom: [ 'author' ], |
| 7634 context: null |
| 7635 }, |
| 7636 main: { |
| 7637 type: 'landmark', |
| 7638 attributes: { |
| 7639 allowed: [ 'aria-expanded' ] |
| 7640 }, |
| 7641 owned: null, |
| 7642 nameFrom: [ 'author' ], |
| 7643 context: null, |
| 7644 implicit: [ 'main' ] |
| 7645 }, |
| 7646 marquee: { |
| 7647 type: 'widget', |
| 7648 attributes: { |
| 7649 allowed: [ 'aria-expanded' ] |
| 7650 }, |
| 7651 owned: null, |
| 7652 nameFrom: [ 'author' ], |
| 7653 context: null |
| 7654 }, |
| 7655 math: { |
| 7656 type: 'structure', |
| 7657 attributes: { |
| 7658 allowed: [ 'aria-expanded' ] |
| 7659 }, |
| 7660 owned: null, |
| 7661 nameFrom: [ 'author' ], |
| 7662 context: null, |
| 7663 implicit: [ 'math' ] |
| 7664 }, |
| 7665 menu: { |
| 7666 type: 'composite', |
| 7667 attributes: { |
| 7668 allowed: [ 'aria-activedescendant', 'aria-expanded' ] |
| 7669 }, |
| 7670 owned: { |
| 7671 one: [ 'menuitem', 'menuitemradio', 'menuitemcheckbox' ] |
| 7672 }, |
| 7673 nameFrom: [ 'author' ], |
| 7674 context: null, |
| 7675 implicit: [ 'menu[type="context"]' ] |
| 7676 }, |
| 7677 menubar: { |
| 7678 type: 'composite', |
| 7679 attributes: { |
| 7680 allowed: [ 'aria-activedescendant', 'aria-expanded' ] |
| 7681 }, |
| 7682 owned: null, |
| 7683 nameFrom: [ 'author' ], |
| 7684 context: null |
| 7685 }, |
| 7686 menuitem: { |
| 7687 type: 'widget', |
| 7688 attributes: null, |
| 7689 owned: null, |
| 7690 nameFrom: [ 'author', 'contents' ], |
| 7691 context: [ 'menu', 'menubar' ], |
| 7692 implicit: [ 'menuitem[type="command"]' ] |
| 7693 }, |
| 7694 menuitemcheckbox: { |
| 7695 type: 'widget', |
| 7696 attributes: { |
| 7697 required: [ 'aria-checked' ] |
| 7698 }, |
| 7699 owned: null, |
| 7700 nameFrom: [ 'author', 'contents' ], |
| 7701 context: [ 'menu', 'menubar' ], |
| 7702 implicit: [ 'menuitem[type="checkbox"]' ] |
| 7703 }, |
| 7704 menuitemradio: { |
| 7705 type: 'widget', |
| 7706 attributes: { |
| 7707 allowed: [ 'aria-selected', 'aria-posinset', 'aria-setsize' ], |
| 7708 required: [ 'aria-checked' ] |
| 7709 }, |
| 7710 owned: null, |
| 7711 nameFrom: [ 'author', 'contents' ], |
| 7712 context: [ 'menu', 'menubar' ], |
| 7713 implicit: [ 'menuitem[type="radio"]' ] |
| 7714 }, |
| 7715 navigation: { |
| 7716 type: 'landmark', |
| 7717 attributes: { |
| 7718 allowed: [ 'aria-expanded' ] |
| 7719 }, |
| 7720 owned: null, |
| 7721 nameFrom: [ 'author' ], |
| 7722 context: null, |
| 7723 implicit: [ 'nav' ] |
| 7724 }, |
| 7725 none: { |
| 7726 type: 'structure', |
| 7727 attributes: null, |
| 7728 owned: null, |
| 7729 nameFrom: [ 'author' ], |
| 7730 context: null |
| 7731 }, |
| 7732 note: { |
| 7733 type: 'structure', |
| 7734 attributes: { |
| 7735 allowed: [ 'aria-expanded' ] |
| 7736 }, |
| 7737 owned: null, |
| 7738 nameFrom: [ 'author' ], |
| 7739 context: null |
| 7740 }, |
| 7741 option: { |
| 7742 type: 'widget', |
| 7743 attributes: { |
| 7744 allowed: [ 'aria-selected', 'aria-posinset', 'aria-setsize', 'aria-c
hecked' ] |
| 7745 }, |
| 7746 owned: null, |
| 7747 nameFrom: [ 'author', 'contents' ], |
| 7748 context: [ 'listbox' ], |
| 7749 implicit: [ 'option' ] |
| 7750 }, |
| 7751 presentation: { |
| 7752 type: 'structure', |
| 7753 attributes: null, |
| 7754 owned: null, |
| 7755 nameFrom: [ 'author' ], |
| 7756 context: null |
| 7757 }, |
| 7758 progressbar: { |
| 7759 type: 'widget', |
| 7760 attributes: { |
| 7761 allowed: [ 'aria-valuetext', 'aria-valuenow', 'aria-valuemax', 'aria
-valuemin' ] |
| 7762 }, |
| 7763 owned: null, |
| 7764 nameFrom: [ 'author' ], |
| 7765 context: null, |
| 7766 implicit: [ 'progress' ] |
| 7767 }, |
| 7768 radio: { |
| 7769 type: 'widget', |
| 7770 attributes: { |
| 7771 allowed: [ 'aria-selected', 'aria-posinset', 'aria-setsize' ], |
| 7772 required: [ 'aria-checked' ] |
| 7773 }, |
| 7774 owned: null, |
| 7775 nameFrom: [ 'author', 'contents' ], |
| 7776 context: null, |
| 7777 implicit: [ 'input[type="radio"]' ] |
| 7778 }, |
| 7779 radiogroup: { |
| 7780 type: 'composite', |
| 7781 attributes: { |
| 7782 allowed: [ 'aria-activedescendant', 'aria-required', 'aria-expanded'
] |
| 7783 }, |
| 7784 owned: { |
| 7785 all: [ 'radio' ] |
| 7786 }, |
| 7787 nameFrom: [ 'author' ], |
| 7788 context: null |
| 7789 }, |
| 7790 range: { |
| 7791 nameFrom: [ 'author' ], |
| 7792 type: 'abstract' |
| 7793 }, |
| 7794 region: { |
| 7795 type: 'structure', |
| 7796 attributes: { |
| 7797 allowed: [ 'aria-expanded' ] |
| 7798 }, |
| 7799 owned: null, |
| 7800 nameFrom: [ 'author' ], |
| 7801 context: null, |
| 7802 implicit: [ 'section' ] |
| 7803 }, |
| 7804 roletype: { |
| 7805 type: 'abstract' |
| 7806 }, |
| 7807 row: { |
| 7808 type: 'structure', |
| 7809 attributes: { |
| 7810 allowed: [ 'aria-level', 'aria-selected', 'aria-activedescendant', '
aria-expanded' ] |
| 7811 }, |
| 7812 owned: { |
| 7813 one: [ 'cell', 'columnheader', 'rowheader', 'gridcell' ] |
| 7814 }, |
| 7815 nameFrom: [ 'author', 'contents' ], |
| 7816 context: [ 'rowgroup', 'grid', 'treegrid', 'table' ], |
| 7817 implicit: [ 'tr' ] |
| 7818 }, |
| 7819 rowgroup: { |
| 7820 type: 'structure', |
| 7821 attributes: { |
| 7822 allowed: [ 'aria-activedescendant', 'aria-expanded' ] |
| 7823 }, |
| 7824 owned: { |
| 7825 all: [ 'row' ] |
| 7826 }, |
| 7827 nameFrom: [ 'author', 'contents' ], |
| 7828 context: [ 'grid', 'table' ], |
| 7829 implicit: [ 'tbody', 'thead', 'tfoot' ] |
| 7830 }, |
| 7831 rowheader: { |
| 7832 type: 'structure', |
| 7833 attributes: { |
| 7834 allowed: [ 'aria-sort', 'aria-required', 'aria-readonly', 'aria-expa
nded', 'aria-selected' ] |
| 7835 }, |
| 7836 owned: null, |
| 7837 nameFrom: [ 'author', 'contents' ], |
| 7838 context: [ 'row' ], |
| 7839 implicit: [ 'th' ] |
| 7840 }, |
| 7841 scrollbar: { |
| 7842 type: 'widget', |
| 7843 attributes: { |
| 7844 required: [ 'aria-controls', 'aria-orientation', 'aria-valuenow', 'a
ria-valuemax', 'aria-valuemin' ], |
| 7845 allowed: [ 'aria-valuetext' ] |
| 7846 }, |
| 7847 owned: null, |
| 7848 nameFrom: [ 'author' ], |
| 7849 context: null |
| 7850 }, |
| 7851 search: { |
| 7852 type: 'landmark', |
| 7853 attributes: { |
| 7854 allowed: [ 'aria-expanded' ] |
| 7855 }, |
| 7856 owned: null, |
| 7857 nameFrom: [ 'author' ], |
| 7858 context: null |
| 7859 }, |
| 7860 searchbox: { |
| 7861 type: 'widget', |
| 7862 attributes: { |
| 7863 allowed: [ 'aria-activedescendant', 'aria-autocomplete', 'aria-multi
line', 'aria-readonly', 'aria-required' ] |
| 7864 }, |
| 7865 owned: null, |
| 7866 nameFrom: [ 'author' ], |
| 7867 context: null, |
| 7868 implicit: [ 'input[type="search"]' ] |
| 7869 }, |
| 7870 section: { |
| 7871 nameFrom: [ 'author', 'contents' ], |
| 7872 type: 'abstract' |
| 7873 }, |
| 7874 sectionhead: { |
| 7875 nameFrom: [ 'author', 'contents' ], |
| 7876 type: 'abstract' |
| 7877 }, |
| 7878 select: { |
| 7879 nameFrom: [ 'author' ], |
| 7880 type: 'abstract' |
| 7881 }, |
| 7882 separator: { |
| 7883 type: 'structure', |
| 7884 attributes: { |
| 7885 allowed: [ 'aria-expanded', 'aria-orientation' ] |
| 7886 }, |
| 7887 owned: null, |
| 7888 nameFrom: [ 'author' ], |
| 7889 context: null, |
| 7890 implicit: [ 'hr' ] |
| 7891 }, |
| 7892 slider: { |
| 7893 type: 'widget', |
| 7894 attributes: { |
| 7895 allowed: [ 'aria-valuetext', 'aria-orientation' ], |
| 7896 required: [ 'aria-valuenow', 'aria-valuemax', 'aria-valuemin' ] |
| 7897 }, |
| 7898 owned: null, |
| 7899 nameFrom: [ 'author' ], |
| 7900 context: null, |
| 7901 implicit: [ 'input[type="range"]' ] |
| 7902 }, |
| 7903 spinbutton: { |
| 7904 type: 'widget', |
| 7905 attributes: { |
| 7906 allowed: [ 'aria-valuetext', 'aria-required' ], |
| 7907 required: [ 'aria-valuenow', 'aria-valuemax', 'aria-valuemin' ] |
| 7908 }, |
| 7909 owned: null, |
| 7910 nameFrom: [ 'author' ], |
| 7911 context: null, |
| 7912 implicit: [ 'input[type="number"]' ] |
| 7913 }, |
| 7914 status: { |
| 7915 type: 'widget', |
| 7916 attributes: { |
| 7917 allowed: [ 'aria-expanded' ] |
| 7918 }, |
| 7919 owned: null, |
| 7920 nameFrom: [ 'author' ], |
| 7921 context: null, |
| 7922 implicit: [ 'output' ] |
| 7923 }, |
| 7924 structure: { |
| 7925 type: 'abstract' |
| 7926 }, |
| 7927 switch: { |
| 7928 type: 'widget', |
| 7929 attributes: { |
| 7930 required: [ 'aria-checked' ] |
| 7931 }, |
| 7932 owned: null, |
| 7933 nameFrom: [ 'author', 'contents' ], |
| 7934 context: null |
| 7935 }, |
| 7936 tab: { |
| 7937 type: 'widget', |
| 7938 attributes: { |
| 7939 allowed: [ 'aria-selected', 'aria-expanded' ] |
| 7940 }, |
| 7941 owned: null, |
| 7942 nameFrom: [ 'author', 'contents' ], |
| 7943 context: [ 'tablist' ] |
| 7944 }, |
| 7945 table: { |
| 7946 type: 'structure', |
| 7947 attributes: { |
| 7948 allowed: [ 'aria-colcount', 'aria-rowcount' ] |
| 7949 }, |
| 7950 owned: { |
| 7951 one: [ 'rowgroup', 'row' ] |
| 7952 }, |
| 7953 nameFrom: [ 'author' ], |
| 7954 context: null, |
| 7955 implicit: [ 'table' ] |
| 7956 }, |
| 7957 tablist: { |
| 7958 type: 'composite', |
| 7959 attributes: { |
| 7960 allowed: [ 'aria-activedescendant', 'aria-expanded', 'aria-level', '
aria-multiselectable' ] |
| 7961 }, |
| 7962 owned: { |
| 7963 all: [ 'tab' ] |
| 7964 }, |
| 7965 nameFrom: [ 'author' ], |
| 7966 context: null |
| 7967 }, |
| 7968 tabpanel: { |
| 7969 type: 'widget', |
| 7970 attributes: { |
| 7971 allowed: [ 'aria-expanded' ] |
| 7972 }, |
| 7973 owned: null, |
| 7974 nameFrom: [ 'author' ], |
| 7975 context: null |
| 7976 }, |
| 7977 text: { |
| 7978 type: 'structure', |
| 7979 owned: null, |
| 7980 nameFrom: [ 'author', 'contents' ], |
| 7981 context: null |
| 7982 }, |
| 7983 textbox: { |
| 7984 type: 'widget', |
| 7985 attributes: { |
| 7986 allowed: [ 'aria-activedescendant', 'aria-autocomplete', 'aria-multi
line', 'aria-readonly', 'aria-required' ] |
| 7987 }, |
| 7988 owned: null, |
| 7989 nameFrom: [ 'author' ], |
| 7990 context: null, |
| 7991 implicit: [ 'input[type="text"]', 'input[type="email"]', 'input[type="
password"]', 'input[type="tel"]', 'input[type="url"]', 'input:not([type])', 'tex
tarea' ] |
| 7992 }, |
| 7993 timer: { |
| 7994 type: 'widget', |
| 7995 attributes: { |
| 7996 allowed: [ 'aria-expanded' ] |
| 7997 }, |
| 7998 owned: null, |
| 7999 nameFrom: [ 'author' ], |
| 8000 context: null |
| 8001 }, |
| 8002 toolbar: { |
| 8003 type: 'structure', |
| 8004 attributes: { |
| 8005 allowed: [ 'aria-activedescendant', 'aria-expanded' ] |
| 8006 }, |
| 8007 owned: null, |
| 8008 nameFrom: [ 'author' ], |
| 8009 context: null, |
| 8010 implicit: [ 'menu[type="toolbar"]' ] |
| 8011 }, |
| 8012 tooltip: { |
| 8013 type: 'widget', |
| 8014 attributes: { |
| 8015 allowed: [ 'aria-expanded' ] |
| 8016 }, |
| 8017 owned: null, |
| 8018 nameFrom: [ 'author', 'contents' ], |
| 8019 context: null |
| 8020 }, |
| 8021 tree: { |
| 8022 type: 'composite', |
| 8023 attributes: { |
| 8024 allowed: [ 'aria-activedescendant', 'aria-multiselectable', 'aria-re
quired', 'aria-expanded' ] |
| 8025 }, |
| 8026 owned: { |
| 8027 all: [ 'treeitem' ] |
| 8028 }, |
| 8029 nameFrom: [ 'author' ], |
| 8030 context: null |
| 8031 }, |
| 8032 treegrid: { |
| 8033 type: 'composite', |
| 8034 attributes: { |
| 8035 allowed: [ 'aria-activedescendant', 'aria-expanded', 'aria-level', '
aria-multiselectable', 'aria-readonly', 'aria-required' ] |
| 8036 }, |
| 8037 owned: { |
| 8038 all: [ 'treeitem' ] |
| 8039 }, |
| 8040 nameFrom: [ 'author' ], |
| 8041 context: null |
| 8042 }, |
| 8043 treeitem: { |
| 8044 type: 'widget', |
| 8045 attributes: { |
| 8046 allowed: [ 'aria-checked', 'aria-selected', 'aria-expanded', 'aria-l
evel', 'aria-posinset', 'aria-setsize' ] |
| 8047 }, |
| 8048 owned: null, |
| 8049 nameFrom: [ 'author', 'contents' ], |
| 8050 context: [ 'treegrid', 'tree' ] |
| 8051 }, |
| 8052 widget: { |
| 8053 type: 'abstract' |
| 8054 }, |
| 8055 window: { |
| 8056 nameFrom: [ 'author' ], |
| 8057 type: 'abstract' |
| 8058 } |
| 8059 }; |
| 8060 var color = {}; |
| 8061 commons.color = color; |
| 8062 var dom = commons.dom = {}; |
| 8063 var table = commons.table = {}; |
| 8064 var text = commons.text = {}; |
| 8065 var utils = commons.utils = axe.utils; |
| 8066 aria.requiredAttr = function(role) { |
| 8067 'use strict'; |
| 8068 var roles = lookupTables.role[role], attr = roles && roles.attributes &&
roles.attributes.required; |
| 8069 return attr || []; |
| 8070 }; |
| 8071 aria.allowedAttr = function(role) { |
| 8072 'use strict'; |
| 8073 var roles = lookupTables.role[role], attr = roles && roles.attributes &&
roles.attributes.allowed || [], requiredAttr = roles && roles.attributes && rol
es.attributes.required || []; |
| 8074 return attr.concat(lookupTables.globalAttributes).concat(requiredAttr); |
| 8075 }; |
| 8076 aria.validateAttr = function(att) { |
| 8077 'use strict'; |
| 8078 return !!lookupTables.attributes[att]; |
| 8079 }; |
| 8080 aria.validateAttrValue = function(node, attr) { |
| 8081 'use strict'; |
| 8082 var matches, list, value = node.getAttribute(attr), attrInfo = lookupTab
les.attributes[attr]; |
| 8083 var doc = dom.getRootNode(node); |
| 8084 if (!attrInfo) { |
| 8085 return true; |
| 8086 } |
| 8087 switch (attrInfo.type) { |
| 8088 case 'boolean': |
| 8089 case 'nmtoken': |
| 8090 return typeof value === 'string' && attrInfo.values.indexOf(value.toLo
werCase()) !== -1; |
| 8091 |
| 8092 case 'nmtokens': |
| 8093 list = axe.utils.tokenList(value); |
| 8094 return list.reduce(function(result, token) { |
| 8095 return result && attrInfo.values.indexOf(token) !== -1; |
| 8096 }, list.length !== 0); |
| 8097 |
| 8098 case 'idref': |
| 8099 return !!(value && doc.getElementById(value)); |
| 8100 |
| 8101 case 'idrefs': |
| 8102 list = axe.utils.tokenList(value); |
| 8103 return list.reduce(function(result, token) { |
| 8104 return !!(result && doc.getElementById(token)); |
| 8105 }, list.length !== 0); |
| 8106 |
| 8107 case 'string': |
| 8108 return true; |
| 8109 |
| 8110 case 'decimal': |
| 8111 matches = value.match(/^[-+]?([0-9]*)\.?([0-9]*)$/); |
| 8112 return !!(matches && (matches[1] || matches[2])); |
| 8113 |
| 8114 case 'int': |
| 8115 return /^[-+]?[0-9]+$/.test(value); |
| 8116 } |
| 8117 }; |
| 8118 aria.label = function(node) { |
| 8119 var ref, candidate; |
| 8120 if (node.actualNode.getAttribute('aria-labelledby')) { |
| 8121 ref = dom.idrefs(node.actualNode, 'aria-labelledby'); |
| 8122 candidate = ref.map(function(thing) { |
| 8123 var vNode = axe.utils.getNodeFromTree(axe._tree[0], thing); |
| 8124 return vNode ? text.visible(vNode, true) : ''; |
| 8125 }).join(' ').trim(); |
| 8126 if (candidate) { |
| 8127 return candidate; |
| 8128 } |
| 8129 } |
| 8130 candidate = node.actualNode.getAttribute('aria-label'); |
| 8131 if (candidate) { |
| 8132 candidate = text.sanitize(candidate).trim(); |
| 8133 if (candidate) { |
| 8134 return candidate; |
| 8135 } |
| 8136 } |
| 8137 return null; |
| 8138 }; |
| 8139 aria.isValidRole = function(role) { |
| 8140 'use strict'; |
| 8141 if (lookupTables.role[role]) { |
| 8142 return true; |
| 8143 } |
| 8144 return false; |
| 8145 }; |
| 8146 aria.getRolesWithNameFromContents = function() { |
| 8147 return Object.keys(lookupTables.role).filter(function(r) { |
| 8148 return lookupTables.role[r].nameFrom && lookupTables.role[r].nameFrom.
indexOf('contents') !== -1; |
| 8149 }); |
| 8150 }; |
| 8151 aria.getRolesByType = function(roleType) { |
| 8152 return Object.keys(lookupTables.role).filter(function(r) { |
| 8153 return lookupTables.role[r].type === roleType; |
| 8154 }); |
| 8155 }; |
| 8156 aria.getRoleType = function(role) { |
| 8157 var r = lookupTables.role[role]; |
| 8158 return r && r.type || null; |
| 8159 }; |
| 8160 aria.requiredOwned = function(role) { |
| 8161 'use strict'; |
| 8162 var owned = null, roles = lookupTables.role[role]; |
| 8163 if (roles) { |
| 8164 owned = axe.utils.clone(roles.owned); |
| 8165 } |
| 8166 return owned; |
| 8167 }; |
| 8168 aria.requiredContext = function(role) { |
| 8169 'use strict'; |
| 8170 var context = null, roles = lookupTables.role[role]; |
| 8171 if (roles) { |
| 8172 context = axe.utils.clone(roles.context); |
| 8173 } |
| 8174 return context; |
| 8175 }; |
| 8176 aria.implicitNodes = function(role) { |
| 8177 'use strict'; |
| 8178 var implicit = null, roles = lookupTables.role[role]; |
| 8179 if (roles && roles.implicit) { |
| 8180 implicit = axe.utils.clone(roles.implicit); |
| 8181 } |
| 8182 return implicit; |
| 8183 }; |
| 8184 aria.implicitRole = function(node) { |
| 8185 'use strict'; |
| 8186 var isValidImplicitRole = function isValidImplicitRole(set, role) { |
| 8187 var validForNodeType = function validForNodeType(implicitNodeTypeSelec
tor) { |
| 8188 return axe.utils.matchesSelector(node, implicitNodeTypeSelector); |
| 8189 }; |
| 8190 if (role.implicit && role.implicit.some(validForNodeType)) { |
| 8191 set.push(role.name); |
| 8192 } |
| 8193 return set; |
| 8194 }; |
| 8195 var sortRolesByOptimalAriaContext = function sortRolesByOptimalAriaConte
xt(roles, ariaAttributes) { |
| 8196 var getScore = function getScore(role) { |
| 8197 var allowedAriaAttributes = aria.allowedAttr(role); |
| 8198 return allowedAriaAttributes.reduce(function(score, attribute) { |
| 8199 return score + (ariaAttributes.indexOf(attribute) > -1 ? 1 : 0); |
| 8200 }, 0); |
| 8201 }; |
| 8202 var scored = roles.map(function(role) { |
| 8203 return { |
| 8204 score: getScore(role), |
| 8205 name: role |
| 8206 }; |
| 8207 }); |
| 8208 var sorted = scored.sort(function(scoredRoleA, scoredRoleB) { |
| 8209 return scoredRoleB.score - scoredRoleA.score; |
| 8210 }); |
| 8211 return sorted.map(function(sortedRole) { |
| 8212 return sortedRole.name; |
| 8213 }); |
| 8214 }; |
| 8215 var roles = Object.keys(lookupTables.role).map(function(role) { |
| 8216 var lookup = lookupTables.role[role]; |
| 8217 return { |
| 8218 name: role, |
| 8219 implicit: lookup && lookup.implicit |
| 8220 }; |
| 8221 }); |
| 8222 var availableImplicitRoles = roles.reduce(isValidImplicitRole, []); |
| 8223 if (!availableImplicitRoles.length) { |
| 8224 return null; |
| 8225 } |
| 8226 var nodeAttributes = node.attributes; |
| 8227 var ariaAttributes = []; |
| 8228 for (var i = 0, j = nodeAttributes.length; i < j; i++) { |
| 8229 var attr = nodeAttributes[i]; |
| 8230 if (attr.name.match(/^aria-/)) { |
| 8231 ariaAttributes.push(attr.name); |
| 8232 } |
| 8233 } |
| 8234 return sortRolesByOptimalAriaContext(availableImplicitRoles, ariaAttribu
tes).shift(); |
| 8235 }; |
| 8236 color.Color = function(red, green, blue, alpha) { |
| 8237 this.red = red; |
| 8238 this.green = green; |
| 8239 this.blue = blue; |
| 8240 this.alpha = alpha; |
| 8241 this.toHexString = function() { |
| 8242 var redString = Math.round(this.red).toString(16); |
| 8243 var greenString = Math.round(this.green).toString(16); |
| 8244 var blueString = Math.round(this.blue).toString(16); |
| 8245 return '#' + (this.red > 15.5 ? redString : '0' + redString) + (this.g
reen > 15.5 ? greenString : '0' + greenString) + (this.blue > 15.5 ? blueString
: '0' + blueString); |
| 8246 }; |
| 8247 var rgbRegex = /^rgb\((\d+), (\d+), (\d+)\)$/; |
| 8248 var rgbaRegex = /^rgba\((\d+), (\d+), (\d+), (\d*(\.\d+)?)\)/; |
| 8249 this.parseRgbString = function(colorString) { |
| 8250 if (colorString === 'transparent') { |
| 8251 this.red = 0; |
| 8252 this.green = 0; |
| 8253 this.blue = 0; |
| 8254 this.alpha = 0; |
| 8255 return; |
| 8256 } |
| 8257 var match = colorString.match(rgbRegex); |
| 8258 if (match) { |
| 8259 this.red = parseInt(match[1], 10); |
| 8260 this.green = parseInt(match[2], 10); |
| 8261 this.blue = parseInt(match[3], 10); |
| 8262 this.alpha = 1; |
| 8263 return; |
| 8264 } |
| 8265 match = colorString.match(rgbaRegex); |
| 8266 if (match) { |
| 8267 this.red = parseInt(match[1], 10); |
| 8268 this.green = parseInt(match[2], 10); |
| 8269 this.blue = parseInt(match[3], 10); |
| 8270 this.alpha = parseFloat(match[4]); |
| 8271 return; |
| 8272 } |
| 8273 }; |
| 8274 this.getRelativeLuminance = function() { |
| 8275 var rSRGB = this.red / 255; |
| 8276 var gSRGB = this.green / 255; |
| 8277 var bSRGB = this.blue / 255; |
| 8278 var r = rSRGB <= .03928 ? rSRGB / 12.92 : Math.pow((rSRGB + .055) / 1.
055, 2.4); |
| 8279 var g = gSRGB <= .03928 ? gSRGB / 12.92 : Math.pow((gSRGB + .055) / 1.
055, 2.4); |
| 8280 var b = bSRGB <= .03928 ? bSRGB / 12.92 : Math.pow((bSRGB + .055) / 1.
055, 2.4); |
| 8281 return .2126 * r + .7152 * g + .0722 * b; |
| 8282 }; |
| 8283 }; |
| 8284 color.flattenColors = function(fgColor, bgColor) { |
| 8285 var alpha = fgColor.alpha; |
| 8286 var r = (1 - alpha) * bgColor.red + alpha * fgColor.red; |
| 8287 var g = (1 - alpha) * bgColor.green + alpha * fgColor.green; |
| 8288 var b = (1 - alpha) * bgColor.blue + alpha * fgColor.blue; |
| 8289 var a = fgColor.alpha + bgColor.alpha * (1 - fgColor.alpha); |
| 8290 return new color.Color(r, g, b, a); |
| 8291 }; |
| 8292 color.getContrast = function(bgColor, fgColor) { |
| 8293 if (!fgColor || !bgColor) { |
| 8294 return null; |
| 8295 } |
| 8296 if (fgColor.alpha < 1) { |
| 8297 fgColor = color.flattenColors(fgColor, bgColor); |
| 8298 } |
| 8299 var bL = bgColor.getRelativeLuminance(); |
| 8300 var fL = fgColor.getRelativeLuminance(); |
| 8301 return (Math.max(fL, bL) + .05) / (Math.min(fL, bL) + .05); |
| 8302 }; |
| 8303 color.hasValidContrastRatio = function(bg, fg, fontSize, isBold) { |
| 8304 var contrast = color.getContrast(bg, fg); |
| 8305 var isSmallFont = isBold && Math.ceil(fontSize * 72) / 96 < 14 || !isBol
d && Math.ceil(fontSize * 72) / 96 < 18; |
| 8306 return { |
| 8307 isValid: isSmallFont && contrast >= 4.5 || !isSmallFont && contrast >=
3, |
| 8308 contrastRatio: contrast |
| 8309 }; |
| 8310 }; |
| 8311 function _getFonts(style) { |
| 8312 return style.getPropertyValue('font-family').split(/[,;]/g).map(function
(font) { |
| 8313 return font.trim().toLowerCase(); |
| 8314 }); |
| 8315 } |
| 8316 function elementIsDistinct(node, ancestorNode) { |
| 8317 var nodeStyle = window.getComputedStyle(node); |
| 8318 if (nodeStyle.getPropertyValue('background-image') !== 'none') { |
| 8319 return true; |
| 8320 } |
| 8321 var hasBorder = [ 'border-bottom', 'border-top', 'outline' ].reduce(func
tion(result, edge) { |
| 8322 var borderClr = new color.Color(); |
| 8323 borderClr.parseRgbString(nodeStyle.getPropertyValue(edge + '-color')); |
| 8324 return result || nodeStyle.getPropertyValue(edge + '-style') !== 'none
' && parseFloat(nodeStyle.getPropertyValue(edge + '-width')) > 0 && borderClr.al
pha !== 0; |
| 8325 }, false); |
| 8326 if (hasBorder) { |
| 8327 return true; |
| 8328 } |
| 8329 var parentStyle = window.getComputedStyle(ancestorNode); |
| 8330 if (_getFonts(nodeStyle)[0] !== _getFonts(parentStyle)[0]) { |
| 8331 return true; |
| 8332 } |
| 8333 var hasStyle = [ 'text-decoration-line', 'text-decoration-style', 'font-
weight', 'font-style', 'font-size' ].reduce(function(result, cssProp) { |
| 8334 return result || nodeStyle.getPropertyValue(cssProp) !== parentStyle.g
etPropertyValue(cssProp); |
| 8335 }, false); |
| 8336 var tDec = nodeStyle.getPropertyValue('text-decoration'); |
| 8337 if (tDec.split(' ').length < 3) { |
| 8338 hasStyle = hasStyle || tDec !== parentStyle.getPropertyValue('text-dec
oration'); |
| 8339 } |
| 8340 return hasStyle; |
| 8341 } |
| 8342 color.elementIsDistinct = elementIsDistinct; |
| 8343 var graphicNodes = [ 'IMG', 'CANVAS', 'OBJECT', 'IFRAME', 'VIDEO', 'SVG' ]
; |
| 8344 function elmHasImage(elm, style) { |
| 8345 var nodeName = elm.nodeName.toUpperCase(); |
| 8346 if (graphicNodes.includes(nodeName)) { |
| 8347 axe.commons.color.incompleteData.set('bgColor', 'imgNode'); |
| 8348 return true; |
| 8349 } |
| 8350 style = style || window.getComputedStyle(elm); |
| 8351 var bgImageStyle = style.getPropertyValue('background-image'); |
| 8352 var hasBgImage = bgImageStyle !== 'none'; |
| 8353 if (hasBgImage) { |
| 8354 var hasGradient = /gradient/.test(bgImageStyle); |
| 8355 axe.commons.color.incompleteData.set('bgColor', hasGradient ? 'bgGradi
ent' : 'bgImage'); |
| 8356 } |
| 8357 return hasBgImage; |
| 8358 } |
| 8359 function getBgColor(elm, elmStyle) { |
| 8360 elmStyle = elmStyle || window.getComputedStyle(elm); |
| 8361 var bgColor = new color.Color(); |
| 8362 bgColor.parseRgbString(elmStyle.getPropertyValue('background-color')); |
| 8363 if (bgColor.alpha !== 0) { |
| 8364 var opacity = elmStyle.getPropertyValue('opacity'); |
| 8365 bgColor.alpha = bgColor.alpha * opacity; |
| 8366 } |
| 8367 return bgColor; |
| 8368 } |
| 8369 function contentOverlapping(targetElement, bgNode) { |
| 8370 var targetRect = targetElement.getClientRects()[0]; |
| 8371 var obscuringElements = document.elementsFromPoint(targetRect.left, targ
etRect.top); |
| 8372 if (obscuringElements) { |
| 8373 for (var i = 0; i < obscuringElements.length; i++) { |
| 8374 if (obscuringElements[i] !== targetElement && obscuringElements[i] =
== bgNode) { |
| 8375 return true; |
| 8376 } |
| 8377 } |
| 8378 } |
| 8379 return false; |
| 8380 } |
| 8381 function calculateObscuringAlpha(elmIndex, elmStack, originalElm) { |
| 8382 var totalAlpha = 0; |
| 8383 if (elmIndex > 0) { |
| 8384 for (var i = elmIndex - 1; i >= 0; i--) { |
| 8385 var bgElm = elmStack[i]; |
| 8386 var bgElmStyle = window.getComputedStyle(bgElm); |
| 8387 var bgColor = getBgColor(bgElm, bgElmStyle); |
| 8388 if (bgColor.alpha && contentOverlapping(originalElm, bgElm)) { |
| 8389 totalAlpha += bgColor.alpha; |
| 8390 } else { |
| 8391 elmStack.splice(i, 1); |
| 8392 } |
| 8393 } |
| 8394 } |
| 8395 return totalAlpha; |
| 8396 } |
| 8397 function elmPartiallyObscured(elm, bgElm, bgColor) { |
| 8398 var obscured = elm !== bgElm && !dom.visuallyContains(elm, bgElm) && bgC
olor.alpha !== 0; |
| 8399 if (obscured) { |
| 8400 axe.commons.color.incompleteData.set('bgColor', 'elmPartiallyObscured'
); |
| 8401 } |
| 8402 return obscured; |
| 8403 } |
| 8404 function includeMissingElements(elmStack, elm) { |
| 8405 var elementMap = { |
| 8406 TD: 'TR', |
| 8407 INPUT: 'LABEL' |
| 8408 }; |
| 8409 var tagArray = elmStack.map(function(elm) { |
| 8410 return elm.tagName; |
| 8411 }); |
| 8412 var bgNodes = elmStack; |
| 8413 for (var candidate in elementMap) { |
| 8414 if (elementMap.hasOwnProperty(candidate)) { |
| 8415 if (elm.tagName === candidate) { |
| 8416 var ancestorMatch = axe.commons.dom.findUp(elm, elementMap[candida
te]); |
| 8417 if (ancestorMatch && elmStack.indexOf(ancestorMatch) === -1) { |
| 8418 var overlaps = axe.commons.dom.visuallyOverlaps(elm.getBoundingC
lientRect(), ancestorMatch); |
| 8419 if (overlaps) { |
| 8420 bgNodes.splice(elmStack.indexOf(elm) + 1, 0, ancestorMatch); |
| 8421 } |
| 8422 } |
| 8423 } |
| 8424 if (elm.tagName === elementMap[candidate] && tagArray.indexOf(elm.ta
gName) === -1) { |
| 8425 bgNodes.splice(tagArray.indexOf(candidate) + 1, 0, elm); |
| 8426 } |
| 8427 } |
| 8428 } |
| 8429 return bgNodes; |
| 8430 } |
| 8431 function sortPageBackground(elmStack) { |
| 8432 var bodyIndex = elmStack.indexOf(document.body); |
| 8433 var bgNodes = elmStack; |
| 8434 if (bodyIndex > 1 && !elmHasImage(document.documentElement) && getBgColo
r(document.documentElement).alpha === 0) { |
| 8435 bgNodes.splice(bodyIndex, 1); |
| 8436 bgNodes.splice(elmStack.indexOf(document.documentElement), 1); |
| 8437 bgNodes.push(document.body); |
| 8438 } |
| 8439 return bgNodes; |
| 8440 } |
| 8441 color.getBackgroundStack = function(elm) { |
| 8442 var rect = elm.getBoundingClientRect(); |
| 8443 var x = void 0, y = void 0; |
| 8444 if (rect.left > window.innerWidth) { |
| 8445 return; |
| 8446 } |
| 8447 if (rect.top > window.innerHeight) { |
| 8448 return; |
| 8449 } |
| 8450 x = Math.min(Math.ceil(rect.left + rect.width / 2), window.innerWidth -
1); |
| 8451 y = Math.min(Math.ceil(rect.top + rect.height / 2), window.innerHeight -
1); |
| 8452 var elmStack = document.elementsFromPoint(x, y); |
| 8453 elmStack = includeMissingElements(elmStack, elm); |
| 8454 elmStack = dom.reduceToElementsBelowFloating(elmStack, elm); |
| 8455 elmStack = sortPageBackground(elmStack); |
| 8456 var elmIndex = elmStack.indexOf(elm); |
| 8457 if (calculateObscuringAlpha(elmIndex, elmStack, elm) >= .99) { |
| 8458 axe.commons.color.incompleteData.set('bgColor', 'bgOverlap'); |
| 8459 return null; |
| 8460 } |
| 8461 return elmIndex !== -1 ? elmStack : null; |
| 8462 }; |
| 8463 color.getBackgroundColor = function(elm) { |
| 8464 var bgElms = arguments.length > 1 && arguments[1] !== undefined ? argume
nts[1] : []; |
| 8465 var noScroll = arguments.length > 2 && arguments[2] !== undefined ? argu
ments[2] : false; |
| 8466 if (noScroll !== true) { |
| 8467 elm.scrollIntoView(); |
| 8468 } |
| 8469 var bgColors = []; |
| 8470 var elmStack = color.getBackgroundStack(elm); |
| 8471 (elmStack || []).some(function(bgElm) { |
| 8472 var bgElmStyle = window.getComputedStyle(bgElm); |
| 8473 var bgColor = getBgColor(bgElm, bgElmStyle); |
| 8474 if (elmPartiallyObscured(elm, bgElm, bgColor) || elmHasImage(bgElm, bg
ElmStyle)) { |
| 8475 bgColors = null; |
| 8476 bgElms.push(bgElm); |
| 8477 return true; |
| 8478 } |
| 8479 if (bgColor.alpha !== 0) { |
| 8480 bgElms.push(bgElm); |
| 8481 bgColors.push(bgColor); |
| 8482 return bgColor.alpha === 1; |
| 8483 } else { |
| 8484 return false; |
| 8485 } |
| 8486 }); |
| 8487 if (bgColors !== null && elmStack !== null) { |
| 8488 bgColors.push(new color.Color(255, 255, 255, 1)); |
| 8489 var colors = bgColors.reduce(color.flattenColors); |
| 8490 return colors; |
| 8491 } |
| 8492 return null; |
| 8493 }; |
| 8494 dom.isOpaque = function(node) { |
| 8495 var style = window.getComputedStyle(node); |
| 8496 return elmHasImage(node, style) || getBgColor(node, style).alpha === 1; |
| 8497 }; |
| 8498 color.getForegroundColor = function(node, noScroll) { |
| 8499 var nodeStyle = window.getComputedStyle(node); |
| 8500 var fgColor = new color.Color(); |
| 8501 fgColor.parseRgbString(nodeStyle.getPropertyValue('color')); |
| 8502 var opacity = nodeStyle.getPropertyValue('opacity'); |
| 8503 fgColor.alpha = fgColor.alpha * opacity; |
| 8504 if (fgColor.alpha === 1) { |
| 8505 return fgColor; |
| 8506 } |
| 8507 var bgColor = color.getBackgroundColor(node, [], noScroll); |
| 8508 if (bgColor === null) { |
| 8509 var reason = axe.commons.color.incompleteData.get('bgColor'); |
| 8510 axe.commons.color.incompleteData.set('fgColor', reason); |
| 8511 return null; |
| 8512 } |
| 8513 return color.flattenColors(fgColor, bgColor); |
| 8514 }; |
| 8515 color.incompleteData = function() { |
| 8516 var data = {}; |
| 8517 return { |
| 8518 set: function set(key, reason) { |
| 8519 if (typeof key !== 'string') { |
| 8520 throw new Error('Incomplete data: key must be a string'); |
| 8521 } |
| 8522 if (reason) { |
| 8523 data[key] = reason; |
| 8524 } |
| 8525 return data[key]; |
| 8526 }, |
| 8527 get: function get(key) { |
| 8528 return data[key]; |
| 8529 }, |
| 8530 clear: function clear() { |
| 8531 data = {}; |
| 8532 } |
| 8533 }; |
| 8534 }(); |
| 8535 dom.reduceToElementsBelowFloating = function(elements, targetNode) { |
| 8536 var floatingPositions = [ 'fixed', 'sticky' ], finalElements = [], targe
tFound = false, index, currentNode, style; |
| 8537 for (index = 0; index < elements.length; ++index) { |
| 8538 currentNode = elements[index]; |
| 8539 if (currentNode === targetNode) { |
| 8540 targetFound = true; |
| 8541 } |
| 8542 style = window.getComputedStyle(currentNode); |
| 8543 if (!targetFound && floatingPositions.indexOf(style.position) !== -1)
{ |
| 8544 finalElements = []; |
| 8545 continue; |
| 8546 } |
| 8547 finalElements.push(currentNode); |
| 8548 } |
| 8549 return finalElements; |
| 8550 }; |
| 8551 dom.findUp = function(element, target) { |
| 8552 'use strict'; |
| 8553 var parent, doc = axe.commons.dom.getRootNode(element), matches; |
| 8554 matches = doc.querySelectorAll(target); |
| 8555 matches = axe.utils.toArray(matches); |
| 8556 if (doc === document && !matches.length) { |
| 8557 return null; |
| 8558 } |
| 8559 parent = element.assignedSlot ? element.assignedSlot : element.parentNod
e; |
| 8560 if (parent.nodeType === 11) { |
| 8561 parent = parent.host; |
| 8562 } |
| 8563 while (parent && matches.indexOf(parent) === -1) { |
| 8564 parent = parent.assignedSlot ? parent.assignedSlot : parent.parentNode
; |
| 8565 if (parent && parent.nodeType === 11) { |
| 8566 parent = parent.host; |
| 8567 doc = axe.commons.dom.getRootNode(parent); |
| 8568 matches = doc.querySelectorAll(target); |
| 8569 matches = axe.utils.toArray(matches); |
| 8570 if (doc === document && !matches.length) { |
| 8571 return null; |
| 8572 } |
| 8573 } |
| 8574 } |
| 8575 return parent; |
| 8576 }; |
| 8577 dom.getElementByReference = function(node, attr) { |
| 8578 'use strict'; |
| 8579 var candidate, fragment = node.getAttribute(attr), doc = document; |
| 8580 if (fragment && fragment.charAt(0) === '#') { |
| 8581 fragment = fragment.substring(1); |
| 8582 candidate = doc.getElementById(fragment); |
| 8583 if (candidate) { |
| 8584 return candidate; |
| 8585 } |
| 8586 candidate = doc.getElementsByName(fragment); |
| 8587 if (candidate.length) { |
| 8588 return candidate[0]; |
| 8589 } |
| 8590 } |
| 8591 return null; |
| 8592 }; |
| 8593 dom.getElementCoordinates = function(element) { |
| 8594 'use strict'; |
| 8595 var scrollOffset = dom.getScrollOffset(document), xOffset = scrollOffset
.left, yOffset = scrollOffset.top, coords = element.getBoundingClientRect(); |
| 8596 return { |
| 8597 top: coords.top + yOffset, |
| 8598 right: coords.right + xOffset, |
| 8599 bottom: coords.bottom + yOffset, |
| 8600 left: coords.left + xOffset, |
| 8601 width: coords.right - coords.left, |
| 8602 height: coords.bottom - coords.top |
| 8603 }; |
| 8604 }; |
| 8605 dom.getRootNode = function(node) { |
| 8606 var doc = node.getRootNode && node.getRootNode() || document; |
| 8607 if (doc === node) { |
| 8608 doc = document; |
| 8609 } |
| 8610 return doc; |
| 8611 }; |
| 8612 dom.getScrollOffset = function(element) { |
| 8613 'use strict'; |
| 8614 if (!element.nodeType && element.document) { |
| 8615 element = element.document; |
| 8616 } |
| 8617 if (element.nodeType === 9) { |
| 8618 var docElement = element.documentElement, body = element.body; |
| 8619 return { |
| 8620 left: docElement && docElement.scrollLeft || body && body.scrollLeft
|| 0, |
| 8621 top: docElement && docElement.scrollTop || body && body.scrollTop ||
0 |
| 8622 }; |
| 8623 } |
| 8624 return { |
| 8625 left: element.scrollLeft, |
| 8626 top: element.scrollTop |
| 8627 }; |
| 8628 }; |
| 8629 dom.getViewportSize = function(win) { |
| 8630 'use strict'; |
| 8631 var body, doc = win.document, docElement = doc.documentElement; |
| 8632 if (win.innerWidth) { |
| 8633 return { |
| 8634 width: win.innerWidth, |
| 8635 height: win.innerHeight |
| 8636 }; |
| 8637 } |
| 8638 if (docElement) { |
| 8639 return { |
| 8640 width: docElement.clientWidth, |
| 8641 height: docElement.clientHeight |
| 8642 }; |
| 8643 } |
| 8644 body = doc.body; |
| 8645 return { |
| 8646 width: body.clientWidth, |
| 8647 height: body.clientHeight |
| 8648 }; |
| 8649 }; |
| 8650 dom.hasContent = function hasContent(elm) { |
| 8651 if (elm.actualNode.textContent.trim() || aria.label(elm)) { |
| 8652 return true; |
| 8653 } |
| 8654 var contentElms = axe.utils.querySelectorAll(elm, '*'); |
| 8655 for (var i = 0; i < contentElms.length; i++) { |
| 8656 if (aria.label(contentElms[i]) || dom.isVisualContent(contentElms[i].a
ctualNode)) { |
| 8657 return true; |
| 8658 } |
| 8659 } |
| 8660 return false; |
| 8661 }; |
| 8662 dom.idrefs = function(node, attr) { |
| 8663 'use strict'; |
| 8664 var index, length, doc = dom.getRootNode(node), result = [], idrefs = no
de.getAttribute(attr); |
| 8665 if (idrefs) { |
| 8666 idrefs = axe.utils.tokenList(idrefs); |
| 8667 for (index = 0, length = idrefs.length; index < length; index++) { |
| 8668 result.push(doc.getElementById(idrefs[index])); |
| 8669 } |
| 8670 } |
| 8671 return result; |
| 8672 }; |
| 8673 dom.isFocusable = function(el) { |
| 8674 'use strict'; |
| 8675 if (!el || el.disabled || !dom.isVisible(el) && el.nodeName.toUpperCase(
) !== 'AREA') { |
| 8676 return false; |
| 8677 } |
| 8678 switch (el.nodeName.toUpperCase()) { |
| 8679 case 'A': |
| 8680 case 'AREA': |
| 8681 if (el.href) { |
| 8682 return true; |
| 8683 } |
| 8684 break; |
| 8685 |
| 8686 case 'INPUT': |
| 8687 return el.type !== 'hidden'; |
| 8688 |
| 8689 case 'TEXTAREA': |
| 8690 case 'SELECT': |
| 8691 case 'DETAILS': |
| 8692 case 'BUTTON': |
| 8693 return true; |
| 8694 } |
| 8695 var tabindex = el.getAttribute('tabindex'); |
| 8696 if (tabindex && !isNaN(parseInt(tabindex, 10))) { |
| 8697 return true; |
| 8698 } |
| 8699 return false; |
| 8700 }; |
| 8701 dom.isHTML5 = function(doc) { |
| 8702 var node = doc.doctype; |
| 8703 if (node === null) { |
| 8704 return false; |
| 8705 } |
| 8706 return node.name === 'html' && !node.publicId && !node.systemId; |
| 8707 }; |
| 8708 function walkDomNode(node, functor) { |
| 8709 'use strict'; |
| 8710 var shouldWalk = functor(node); |
| 8711 node = node.firstChild; |
| 8712 while (node) { |
| 8713 if (shouldWalk !== false) { |
| 8714 walkDomNode(node, functor); |
| 8715 } |
| 8716 node = node.nextSibling; |
| 8717 } |
| 8718 } |
| 8719 var blockLike = [ 'block', 'list-item', 'table', 'flex', 'grid', 'inline-b
lock' ]; |
| 8720 function isBlock(elm) { |
| 8721 'use strict'; |
| 8722 var display = window.getComputedStyle(elm).getPropertyValue('display'); |
| 8723 return blockLike.indexOf(display) !== -1 || display.substr(0, 6) === 'ta
ble-'; |
| 8724 } |
| 8725 dom.isInTextBlock = function isInTextBlock(node) { |
| 8726 'use strict'; |
| 8727 if (isBlock(node)) { |
| 8728 return false; |
| 8729 } |
| 8730 var parentBlock = node.parentNode; |
| 8731 while (parentBlock.nodeType === 1 && !isBlock(parentBlock)) { |
| 8732 parentBlock = parentBlock.parentNode; |
| 8733 } |
| 8734 var parentText = ''; |
| 8735 var linkText = ''; |
| 8736 var inBrBlock = 0; |
| 8737 walkDomNode(parentBlock, function(currNode) { |
| 8738 if (inBrBlock === 2) { |
| 8739 return false; |
| 8740 } |
| 8741 if (currNode.nodeType === 3) { |
| 8742 parentText += currNode.nodeValue; |
| 8743 } |
| 8744 if (currNode.nodeType !== 1) { |
| 8745 return; |
| 8746 } |
| 8747 var nodeName = (currNode.nodeName || '').toUpperCase(); |
| 8748 if ([ 'BR', 'HR' ].indexOf(nodeName) !== -1) { |
| 8749 if (inBrBlock === 0) { |
| 8750 parentText = ''; |
| 8751 linkText = ''; |
| 8752 } else { |
| 8753 inBrBlock = 2; |
| 8754 } |
| 8755 } else if (currNode.style.display === 'none' || currNode.style.overflo
w === 'hidden' || [ '', null, 'none' ].indexOf(currNode.style.float) === -1 || [
'', null, 'relative' ].indexOf(currNode.style.position) === -1) { |
| 8756 return false; |
| 8757 } else if (nodeName === 'A' && currNode.href || (currNode.getAttribute
('role') || '').toLowerCase() === 'link') { |
| 8758 if (currNode === node) { |
| 8759 inBrBlock = 1; |
| 8760 } |
| 8761 linkText += currNode.textContent; |
| 8762 return false; |
| 8763 } |
| 8764 }); |
| 8765 parentText = axe.commons.text.sanitize(parentText); |
| 8766 linkText = axe.commons.text.sanitize(linkText); |
| 8767 return parentText.length > linkText.length; |
| 8768 }; |
| 8769 dom.isNode = function(candidate) { |
| 8770 'use strict'; |
| 8771 return candidate instanceof Node; |
| 8772 }; |
| 8773 dom.isOffscreen = function(element) { |
| 8774 'use strict'; |
| 8775 var noParentScrolled = function noParentScrolled(element, offset) { |
| 8776 element = element.parentNode; |
| 8777 while (element.nodeName.toLowerCase() !== 'html') { |
| 8778 if (element.scrollTop) { |
| 8779 offset += element.scrollTop; |
| 8780 if (offset >= 0) { |
| 8781 return false; |
| 8782 } |
| 8783 } |
| 8784 element = element.parentNode; |
| 8785 } |
| 8786 return true; |
| 8787 }; |
| 8788 var leftBoundary, docElement = document.documentElement, styl = window.g
etComputedStyle(element), dir = window.getComputedStyle(document.body || docElem
ent).getPropertyValue('direction'), coords = dom.getElementCoordinates(element); |
| 8789 if (coords.bottom < 0 && (noParentScrolled(element, coords.bottom) || st
yl.position === 'absolute')) { |
| 8790 return true; |
| 8791 } |
| 8792 if (coords.left === 0 && coords.right === 0) { |
| 8793 return false; |
| 8794 } |
| 8795 if (dir === 'ltr') { |
| 8796 if (coords.right <= 0) { |
| 8797 return true; |
| 8798 } |
| 8799 } else { |
| 8800 leftBoundary = Math.max(docElement.scrollWidth, dom.getViewportSize(wi
ndow).width); |
| 8801 if (coords.left >= leftBoundary) { |
| 8802 return true; |
| 8803 } |
| 8804 } |
| 8805 return false; |
| 8806 }; |
| 8807 function isClipped(clip) { |
| 8808 'use strict'; |
| 8809 var matches = clip.match(/rect\s*\(([0-9]+)px,?\s*([0-9]+)px,?\s*([0-9]+
)px,?\s*([0-9]+)px\s*\)/); |
| 8810 if (matches && matches.length === 5) { |
| 8811 return matches[3] - matches[1] <= 0 && matches[2] - matches[4] <= 0; |
| 8812 } |
| 8813 return false; |
| 8814 } |
| 8815 dom.isVisible = function(el, screenReader, recursed) { |
| 8816 'use strict'; |
| 8817 var style, nodeName, parent; |
| 8818 if (el.nodeType === 9) { |
| 8819 return true; |
| 8820 } |
| 8821 if (el.nodeType === 11) { |
| 8822 el = el.host; |
| 8823 } |
| 8824 style = window.getComputedStyle(el, null); |
| 8825 if (style === null) { |
| 8826 return false; |
| 8827 } |
| 8828 nodeName = el.nodeName.toUpperCase(); |
| 8829 if (style.getPropertyValue('display') === 'none' || nodeName.toUpperCase
() === 'STYLE' || nodeName.toUpperCase() === 'SCRIPT' || !screenReader && isClip
ped(style.getPropertyValue('clip')) || !recursed && (style.getPropertyValue('vis
ibility') === 'hidden' || !screenReader && dom.isOffscreen(el)) || screenReader
&& el.getAttribute('aria-hidden') === 'true') { |
| 8830 return false; |
| 8831 } |
| 8832 parent = el.assignedSlot ? el.assignedSlot : el.parentNode; |
| 8833 if (parent) { |
| 8834 return dom.isVisible(parent, screenReader, true); |
| 8835 } |
| 8836 return false; |
| 8837 }; |
| 8838 var visualRoles = [ 'checkbox', 'img', 'radio', 'range', 'slider', 'spinbu
tton', 'textbox' ]; |
| 8839 dom.isVisualContent = function(candidate) { |
| 8840 var role = candidate.getAttribute('role'); |
| 8841 if (role) { |
| 8842 return visualRoles.indexOf(role) !== -1; |
| 8843 } |
| 8844 switch (candidate.tagName.toUpperCase()) { |
| 8845 case 'IMG': |
| 8846 case 'IFRAME': |
| 8847 case 'OBJECT': |
| 8848 case 'VIDEO': |
| 8849 case 'AUDIO': |
| 8850 case 'CANVAS': |
| 8851 case 'SVG': |
| 8852 case 'MATH': |
| 8853 case 'BUTTON': |
| 8854 case 'SELECT': |
| 8855 case 'TEXTAREA': |
| 8856 case 'KEYGEN': |
| 8857 case 'PROGRESS': |
| 8858 case 'METER': |
| 8859 return true; |
| 8860 |
| 8861 case 'INPUT': |
| 8862 return candidate.type !== 'hidden'; |
| 8863 |
| 8864 default: |
| 8865 return false; |
| 8866 } |
| 8867 }; |
| 8868 dom.visuallyContains = function(node, parent) { |
| 8869 var rectBound = node.getBoundingClientRect(); |
| 8870 var margin = .01; |
| 8871 var rect = { |
| 8872 top: rectBound.top + margin, |
| 8873 bottom: rectBound.bottom - margin, |
| 8874 left: rectBound.left + margin, |
| 8875 right: rectBound.right - margin |
| 8876 }; |
| 8877 var parentRect = parent.getBoundingClientRect(); |
| 8878 var parentTop = parentRect.top; |
| 8879 var parentLeft = parentRect.left; |
| 8880 var parentScrollArea = { |
| 8881 top: parentTop - parent.scrollTop, |
| 8882 bottom: parentTop - parent.scrollTop + parent.scrollHeight, |
| 8883 left: parentLeft - parent.scrollLeft, |
| 8884 right: parentLeft - parent.scrollLeft + parent.scrollWidth |
| 8885 }; |
| 8886 var style = window.getComputedStyle(parent); |
| 8887 if (style.getPropertyValue('display') === 'inline') { |
| 8888 return true; |
| 8889 } |
| 8890 if (rect.left < parentScrollArea.left && rect.left < parentRect.left ||
rect.top < parentScrollArea.top && rect.top < parentRect.top || rect.right > par
entScrollArea.right && rect.right > parentRect.right || rect.bottom > parentScro
llArea.bottom && rect.bottom > parentRect.bottom) { |
| 8891 return false; |
| 8892 } |
| 8893 if (rect.right > parentRect.right || rect.bottom > parentRect.bottom) { |
| 8894 return style.overflow === 'scroll' || style.overflow === 'auto' || sty
le.overflow === 'hidden' || parent instanceof HTMLBodyElement || parent instance
of HTMLHtmlElement; |
| 8895 } |
| 8896 return true; |
| 8897 }; |
| 8898 dom.visuallyOverlaps = function(rect, parent) { |
| 8899 var parentRect = parent.getBoundingClientRect(); |
| 8900 var parentTop = parentRect.top; |
| 8901 var parentLeft = parentRect.left; |
| 8902 var parentScrollArea = { |
| 8903 top: parentTop - parent.scrollTop, |
| 8904 bottom: parentTop - parent.scrollTop + parent.scrollHeight, |
| 8905 left: parentLeft - parent.scrollLeft, |
| 8906 right: parentLeft - parent.scrollLeft + parent.scrollWidth |
| 8907 }; |
| 8908 if (rect.left > parentScrollArea.right && rect.left > parentRect.right |
| rect.top > parentScrollArea.bottom && rect.top > parentRect.bottom || rect.rig
ht < parentScrollArea.left && rect.right < parentRect.left || rect.bottom < pare
ntScrollArea.top && rect.bottom < parentRect.top) { |
| 8909 return false; |
| 8910 } |
| 8911 var style = window.getComputedStyle(parent); |
| 8912 if (rect.left > parentRect.right || rect.top > parentRect.bottom) { |
| 8913 return style.overflow === 'scroll' || style.overflow === 'auto' || par
ent instanceof HTMLBodyElement || parent instanceof HTMLHtmlElement; |
| 8914 } |
| 8915 return true; |
| 8916 }; |
| 8917 table.getAllCells = function(tableElm) { |
| 8918 var rowIndex, cellIndex, rowLength, cellLength; |
| 8919 var cells = []; |
| 8920 for (rowIndex = 0, rowLength = tableElm.rows.length; rowIndex < rowLengt
h; rowIndex++) { |
| 8921 for (cellIndex = 0, cellLength = tableElm.rows[rowIndex].cells.length;
cellIndex < cellLength; cellIndex++) { |
| 8922 cells.push(tableElm.rows[rowIndex].cells[cellIndex]); |
| 8923 } |
| 8924 } |
| 8925 return cells; |
| 8926 }; |
| 8927 table.getCellPosition = function(cell, tableGrid) { |
| 8928 var rowIndex, index; |
| 8929 if (!tableGrid) { |
| 8930 tableGrid = table.toGrid(dom.findUp(cell, 'table')); |
| 8931 } |
| 8932 for (rowIndex = 0; rowIndex < tableGrid.length; rowIndex++) { |
| 8933 if (tableGrid[rowIndex]) { |
| 8934 index = tableGrid[rowIndex].indexOf(cell); |
| 8935 if (index !== -1) { |
| 8936 return { |
| 8937 x: index, |
| 8938 y: rowIndex |
| 8939 }; |
| 8940 } |
| 8941 } |
| 8942 } |
| 8943 }; |
| 8944 table.getHeaders = function(cell) { |
| 8945 if (cell.hasAttribute('headers')) { |
| 8946 return commons.dom.idrefs(cell, 'headers'); |
| 8947 } |
| 8948 var tableGrid = commons.table.toGrid(commons.dom.findUp(cell, 'table')); |
| 8949 var position = commons.table.getCellPosition(cell, tableGrid); |
| 8950 var rowHeaders = table.traverse('left', position, tableGrid).filter(func
tion(cell) { |
| 8951 return table.isRowHeader(cell); |
| 8952 }); |
| 8953 var colHeaders = table.traverse('up', position, tableGrid).filter(functi
on(cell) { |
| 8954 return table.isColumnHeader(cell); |
| 8955 }); |
| 8956 return [].concat(rowHeaders, colHeaders).reverse(); |
| 8957 }; |
| 8958 table.getScope = function(cell) { |
| 8959 var scope = cell.getAttribute('scope'); |
| 8960 var role = cell.getAttribute('role'); |
| 8961 if (cell instanceof Element === false || [ 'TD', 'TH' ].indexOf(cell.nod
eName.toUpperCase()) === -1) { |
| 8962 throw new TypeError('Expected TD or TH element'); |
| 8963 } |
| 8964 if (role === 'columnheader') { |
| 8965 return 'col'; |
| 8966 } else if (role === 'rowheader') { |
| 8967 return 'row'; |
| 8968 } else if (scope === 'col' || scope === 'row') { |
| 8969 return scope; |
| 8970 } else if (cell.nodeName.toUpperCase() !== 'TH') { |
| 8971 return false; |
| 8972 } |
| 8973 var tableGrid = table.toGrid(dom.findUp(cell, 'table')); |
| 8974 var pos = table.getCellPosition(cell); |
| 8975 var headerRow = tableGrid[pos.y].reduce(function(headerRow, cell) { |
| 8976 return headerRow && cell.nodeName.toUpperCase() === 'TH'; |
| 8977 }, true); |
| 8978 if (headerRow) { |
| 8979 return 'col'; |
| 8980 } |
| 8981 var headerCol = tableGrid.map(function(col) { |
| 8982 return col[pos.x]; |
| 8983 }).reduce(function(headerCol, cell) { |
| 8984 return headerCol && cell.nodeName.toUpperCase() === 'TH'; |
| 8985 }, true); |
| 8986 if (headerCol) { |
| 8987 return 'row'; |
| 8988 } |
| 8989 return 'auto'; |
| 8990 }; |
| 8991 table.isColumnHeader = function(node) { |
| 8992 return [ 'col', 'auto' ].indexOf(table.getScope(node)) !== -1; |
| 8993 }; |
| 8994 table.isDataCell = function(cell) { |
| 8995 if (!cell.children.length && !cell.textContent.trim()) { |
| 8996 return false; |
| 8997 } |
| 8998 return cell.nodeName.toUpperCase() === 'TD'; |
| 8999 }; |
| 9000 table.isDataTable = function(node) { |
| 9001 var role = node.getAttribute('role'); |
| 9002 if ((role === 'presentation' || role === 'none') && !dom.isFocusable(nod
e)) { |
| 9003 return false; |
| 9004 } |
| 9005 if (node.getAttribute('contenteditable') === 'true' || dom.findUp(node,
'[contenteditable="true"]')) { |
| 9006 return true; |
| 9007 } |
| 9008 if (role === 'grid' || role === 'treegrid' || role === 'table') { |
| 9009 return true; |
| 9010 } |
| 9011 if (commons.aria.getRoleType(role) === 'landmark') { |
| 9012 return true; |
| 9013 } |
| 9014 if (node.getAttribute('datatable') === '0') { |
| 9015 return false; |
| 9016 } |
| 9017 if (node.getAttribute('summary')) { |
| 9018 return true; |
| 9019 } |
| 9020 if (node.tHead || node.tFoot || node.caption) { |
| 9021 return true; |
| 9022 } |
| 9023 for (var childIndex = 0, childLength = node.children.length; childIndex
< childLength; childIndex++) { |
| 9024 if (node.children[childIndex].nodeName.toUpperCase() === 'COLGROUP') { |
| 9025 return true; |
| 9026 } |
| 9027 } |
| 9028 var cells = 0; |
| 9029 var rowLength = node.rows.length; |
| 9030 var row, cell; |
| 9031 var hasBorder = false; |
| 9032 for (var rowIndex = 0; rowIndex < rowLength; rowIndex++) { |
| 9033 row = node.rows[rowIndex]; |
| 9034 for (var cellIndex = 0, cellLength = row.cells.length; cellIndex < cel
lLength; cellIndex++) { |
| 9035 cell = row.cells[cellIndex]; |
| 9036 if (cell.nodeName.toUpperCase() === 'TH') { |
| 9037 return true; |
| 9038 } |
| 9039 if (!hasBorder && (cell.offsetWidth !== cell.clientWidth || cell.off
setHeight !== cell.clientHeight)) { |
| 9040 hasBorder = true; |
| 9041 } |
| 9042 if (cell.getAttribute('scope') || cell.getAttribute('headers') || ce
ll.getAttribute('abbr')) { |
| 9043 return true; |
| 9044 } |
| 9045 if ([ 'columnheader', 'rowheader' ].indexOf(cell.getAttribute('role'
)) !== -1) { |
| 9046 return true; |
| 9047 } |
| 9048 if (cell.children.length === 1 && cell.children[0].nodeName.toUpperC
ase() === 'ABBR') { |
| 9049 return true; |
| 9050 } |
| 9051 cells++; |
| 9052 } |
| 9053 } |
| 9054 if (node.getElementsByTagName('table').length) { |
| 9055 return false; |
| 9056 } |
| 9057 if (rowLength < 2) { |
| 9058 return false; |
| 9059 } |
| 9060 var sampleRow = node.rows[Math.ceil(rowLength / 2)]; |
| 9061 if (sampleRow.cells.length === 1 && sampleRow.cells[0].colSpan === 1) { |
| 9062 return false; |
| 9063 } |
| 9064 if (sampleRow.cells.length >= 5) { |
| 9065 return true; |
| 9066 } |
| 9067 if (hasBorder) { |
| 9068 return true; |
| 9069 } |
| 9070 var bgColor, bgImage; |
| 9071 for (rowIndex = 0; rowIndex < rowLength; rowIndex++) { |
| 9072 row = node.rows[rowIndex]; |
| 9073 if (bgColor && bgColor !== window.getComputedStyle(row).getPropertyVal
ue('background-color')) { |
| 9074 return true; |
| 9075 } else { |
| 9076 bgColor = window.getComputedStyle(row).getPropertyValue('background-
color'); |
| 9077 } |
| 9078 if (bgImage && bgImage !== window.getComputedStyle(row).getPropertyVal
ue('background-image')) { |
| 9079 return true; |
| 9080 } else { |
| 9081 bgImage = window.getComputedStyle(row).getPropertyValue('background-
image'); |
| 9082 } |
| 9083 } |
| 9084 if (rowLength >= 20) { |
| 9085 return true; |
| 9086 } |
| 9087 if (dom.getElementCoordinates(node).width > dom.getViewportSize(window).
width * .95) { |
| 9088 return false; |
| 9089 } |
| 9090 if (cells < 10) { |
| 9091 return false; |
| 9092 } |
| 9093 if (node.querySelector('object, embed, iframe, applet')) { |
| 9094 return false; |
| 9095 } |
| 9096 return true; |
| 9097 }; |
| 9098 table.isHeader = function(cell) { |
| 9099 if (table.isColumnHeader(cell) || table.isRowHeader(cell)) { |
| 9100 return true; |
| 9101 } |
| 9102 if (cell.id) { |
| 9103 return !!document.querySelector('[headers~="' + axe.utils.escapeSelect
or(cell.id) + '"]'); |
| 9104 } |
| 9105 return false; |
| 9106 }; |
| 9107 table.isRowHeader = function(node) { |
| 9108 return [ 'row', 'auto' ].indexOf(table.getScope(node)) !== -1; |
| 9109 }; |
| 9110 table.toGrid = function(node) { |
| 9111 var table = []; |
| 9112 var rows = node.rows; |
| 9113 for (var i = 0, rowLength = rows.length; i < rowLength; i++) { |
| 9114 var cells = rows[i].cells; |
| 9115 table[i] = table[i] || []; |
| 9116 var columnIndex = 0; |
| 9117 for (var j = 0, cellLength = cells.length; j < cellLength; j++) { |
| 9118 for (var colSpan = 0; colSpan < cells[j].colSpan; colSpan++) { |
| 9119 for (var rowSpan = 0; rowSpan < cells[j].rowSpan; rowSpan++) { |
| 9120 table[i + rowSpan] = table[i + rowSpan] || []; |
| 9121 while (table[i + rowSpan][columnIndex]) { |
| 9122 columnIndex++; |
| 9123 } |
| 9124 table[i + rowSpan][columnIndex] = cells[j]; |
| 9125 } |
| 9126 columnIndex++; |
| 9127 } |
| 9128 } |
| 9129 } |
| 9130 return table; |
| 9131 }; |
| 9132 table.toArray = table.toGrid; |
| 9133 (function(table) { |
| 9134 var traverseTable = function traverseTable(dir, position, tableGrid, cal
lback) { |
| 9135 var result; |
| 9136 var cell = tableGrid[position.y] ? tableGrid[position.y][position.x] :
undefined; |
| 9137 if (!cell) { |
| 9138 return []; |
| 9139 } |
| 9140 if (typeof callback === 'function') { |
| 9141 result = callback(cell, position, tableGrid); |
| 9142 if (result === true) { |
| 9143 return [ cell ]; |
| 9144 } |
| 9145 } |
| 9146 result = traverseTable(dir, { |
| 9147 x: position.x + dir.x, |
| 9148 y: position.y + dir.y |
| 9149 }, tableGrid, callback); |
| 9150 result.unshift(cell); |
| 9151 return result; |
| 9152 }; |
| 9153 table.traverse = function(dir, startPos, tableGrid, callback) { |
| 9154 if (Array.isArray(startPos)) { |
| 9155 callback = tableGrid; |
| 9156 tableGrid = startPos; |
| 9157 startPos = { |
| 9158 x: 0, |
| 9159 y: 0 |
| 9160 }; |
| 9161 } |
| 9162 if (typeof dir === 'string') { |
| 9163 switch (dir) { |
| 9164 case 'left': |
| 9165 dir = { |
| 9166 x: -1, |
| 9167 y: 0 |
| 9168 }; |
| 9169 break; |
| 9170 |
| 9171 case 'up': |
| 9172 dir = { |
| 9173 x: 0, |
| 9174 y: -1 |
| 9175 }; |
| 9176 break; |
| 9177 |
| 9178 case 'right': |
| 9179 dir = { |
| 9180 x: 1, |
| 9181 y: 0 |
| 9182 }; |
| 9183 break; |
| 9184 |
| 9185 case 'down': |
| 9186 dir = { |
| 9187 x: 0, |
| 9188 y: 1 |
| 9189 }; |
| 9190 break; |
| 9191 } |
| 9192 } |
| 9193 return traverseTable(dir, { |
| 9194 x: startPos.x + dir.x, |
| 9195 y: startPos.y + dir.y |
| 9196 }, tableGrid, callback); |
| 9197 }; |
| 9198 })(table); |
| 9199 var defaultButtonValues = { |
| 9200 submit: 'Submit', |
| 9201 reset: 'Reset' |
| 9202 }; |
| 9203 var inputTypes = [ 'text', 'search', 'tel', 'url', 'email', 'date', 'time'
, 'number', 'range', 'color' ]; |
| 9204 var phrasingElements = [ 'A', 'EM', 'STRONG', 'SMALL', 'MARK', 'ABBR', 'DF
N', 'I', 'B', 'S', 'U', 'CODE', 'VAR', 'SAMP', 'KBD', 'SUP', 'SUB', 'Q', 'CITE',
'SPAN', 'BDO', 'BDI', 'BR', 'WBR', 'INS', 'DEL', 'IMG', 'EMBED', 'OBJECT', 'IFR
AME', 'MAP', 'AREA', 'SCRIPT', 'NOSCRIPT', 'RUBY', 'VIDEO', 'AUDIO', 'INPUT', 'T
EXTAREA', 'SELECT', 'BUTTON', 'LABEL', 'OUTPUT', 'DATALIST', 'KEYGEN', 'PROGRESS
', 'COMMAND', 'CANVAS', 'TIME', 'METER' ]; |
| 9205 function findLabel(element) { |
| 9206 var ref = null; |
| 9207 if (element.id) { |
| 9208 ref = document.querySelector('label[for="' + axe.utils.escapeSelector(
element.id) + '"]'); |
| 9209 if (ref) { |
| 9210 return ref; |
| 9211 } |
| 9212 } |
| 9213 ref = dom.findUp(element, 'label'); |
| 9214 return ref; |
| 9215 } |
| 9216 function isButton(element) { |
| 9217 return [ 'button', 'reset', 'submit' ].indexOf(element.type) !== -1; |
| 9218 } |
| 9219 function isInput(element) { |
| 9220 var nodeName = element.nodeName.toUpperCase(); |
| 9221 return nodeName === 'TEXTAREA' || nodeName === 'SELECT' || nodeName ===
'INPUT' && element.type.toLowerCase() !== 'hidden'; |
| 9222 } |
| 9223 function shouldCheckSubtree(element) { |
| 9224 return [ 'BUTTON', 'SUMMARY', 'A' ].indexOf(element.nodeName.toUpperCase
()) !== -1; |
| 9225 } |
| 9226 function shouldNeverCheckSubtree(element) { |
| 9227 return [ 'TABLE', 'FIGURE' ].indexOf(element.nodeName.toUpperCase()) !==
-1; |
| 9228 } |
| 9229 function formValueText(element) { |
| 9230 var nodeName = element.nodeName.toUpperCase(); |
| 9231 if (nodeName === 'INPUT') { |
| 9232 if (!element.hasAttribute('type') || inputTypes.indexOf(element.getAtt
ribute('type').toLowerCase()) !== -1 && element.value) { |
| 9233 return element.value; |
| 9234 } |
| 9235 return ''; |
| 9236 } |
| 9237 if (nodeName === 'SELECT') { |
| 9238 var opts = element.options; |
| 9239 if (opts && opts.length) { |
| 9240 var returnText = ''; |
| 9241 for (var i = 0; i < opts.length; i++) { |
| 9242 if (opts[i].selected) { |
| 9243 returnText += ' ' + opts[i].text; |
| 9244 } |
| 9245 } |
| 9246 return text.sanitize(returnText); |
| 9247 } |
| 9248 return ''; |
| 9249 } |
| 9250 if (nodeName === 'TEXTAREA' && element.value) { |
| 9251 return element.value; |
| 9252 } |
| 9253 return ''; |
| 9254 } |
| 9255 function checkDescendant(element, nodeName) { |
| 9256 var candidate = element.querySelector(nodeName.toLowerCase()); |
| 9257 if (candidate) { |
| 9258 return text.accessibleText(candidate); |
| 9259 } |
| 9260 return ''; |
| 9261 } |
| 9262 function isEmbeddedControl(e) { |
| 9263 if (!e) { |
| 9264 return false; |
| 9265 } |
| 9266 switch (e.nodeName.toUpperCase()) { |
| 9267 case 'SELECT': |
| 9268 case 'TEXTAREA': |
| 9269 return true; |
| 9270 |
| 9271 case 'INPUT': |
| 9272 return !e.hasAttribute('type') || inputTypes.indexOf(e.getAttribute('t
ype').toLowerCase()) !== -1; |
| 9273 |
| 9274 default: |
| 9275 return false; |
| 9276 } |
| 9277 } |
| 9278 function shouldCheckAlt(element) { |
| 9279 var nodeName = element.nodeName.toUpperCase(); |
| 9280 return nodeName === 'INPUT' && element.type.toLowerCase() === 'image' ||
[ 'IMG', 'APPLET', 'AREA' ].indexOf(nodeName) !== -1; |
| 9281 } |
| 9282 function nonEmptyText(t) { |
| 9283 return !!text.sanitize(t); |
| 9284 } |
| 9285 text.accessibleText = function(element, inLabelledByContext) { |
| 9286 var accessibleNameComputation; |
| 9287 var encounteredNodes = []; |
| 9288 function getInnerText(element, inLabelledByContext, inControlContext) { |
| 9289 var nodes = element.childNodes; |
| 9290 var returnText = ''; |
| 9291 var node; |
| 9292 for (var i = 0; i < nodes.length; i++) { |
| 9293 node = nodes[i]; |
| 9294 if (node.nodeType === 3) { |
| 9295 returnText += node.textContent; |
| 9296 } else if (node.nodeType === 1) { |
| 9297 if (phrasingElements.indexOf(node.nodeName.toUpperCase()) === -1)
{ |
| 9298 returnText += ' '; |
| 9299 } |
| 9300 returnText += accessibleNameComputation(nodes[i], inLabelledByCont
ext, inControlContext); |
| 9301 } |
| 9302 } |
| 9303 return returnText; |
| 9304 } |
| 9305 function checkNative(element, inLabelledByContext, inControlContext) { |
| 9306 var returnText = ''; |
| 9307 var nodeName = element.nodeName.toUpperCase(); |
| 9308 if (shouldCheckSubtree(element)) { |
| 9309 returnText = getInnerText(element, false, false) || ''; |
| 9310 if (nonEmptyText(returnText)) { |
| 9311 return returnText; |
| 9312 } |
| 9313 } |
| 9314 if (nodeName === 'FIGURE') { |
| 9315 returnText = checkDescendant(element, 'figcaption'); |
| 9316 if (nonEmptyText(returnText)) { |
| 9317 return returnText; |
| 9318 } |
| 9319 } |
| 9320 if (nodeName === 'TABLE') { |
| 9321 returnText = checkDescendant(element, 'caption'); |
| 9322 if (nonEmptyText(returnText)) { |
| 9323 return returnText; |
| 9324 } |
| 9325 returnText = element.getAttribute('title') || element.getAttribute('
summary') || ''; |
| 9326 if (nonEmptyText(returnText)) { |
| 9327 return returnText; |
| 9328 } |
| 9329 } |
| 9330 if (shouldCheckAlt(element)) { |
| 9331 return element.getAttribute('alt') || ''; |
| 9332 } |
| 9333 if (isInput(element) && !inControlContext) { |
| 9334 if (isButton(element)) { |
| 9335 return element.value || element.title || defaultButtonValues[eleme
nt.type] || ''; |
| 9336 } |
| 9337 var labelElement = findLabel(element); |
| 9338 if (labelElement) { |
| 9339 return accessibleNameComputation(labelElement, inLabelledByContext
, true); |
| 9340 } |
| 9341 } |
| 9342 return ''; |
| 9343 } |
| 9344 function checkARIA(element, inLabelledByContext, inControlContext) { |
| 9345 if (!inLabelledByContext && element.hasAttribute('aria-labelledby')) { |
| 9346 return text.sanitize(dom.idrefs(element, 'aria-labelledby').map(func
tion(l) { |
| 9347 if (element === l) { |
| 9348 encounteredNodes.pop(); |
| 9349 } |
| 9350 return accessibleNameComputation(l, true, element !== l); |
| 9351 }).join(' ')); |
| 9352 } |
| 9353 if (!(inControlContext && isEmbeddedControl(element)) && element.hasAt
tribute('aria-label')) { |
| 9354 return text.sanitize(element.getAttribute('aria-label')); |
| 9355 } |
| 9356 return ''; |
| 9357 } |
| 9358 accessibleNameComputation = function accessibleNameComputation(element,
inLabelledByContext, inControlContext) { |
| 9359 'use strict'; |
| 9360 var returnText; |
| 9361 if (element === null || encounteredNodes.indexOf(element) !== -1) { |
| 9362 return ''; |
| 9363 } else if (!inLabelledByContext && !dom.isVisible(element, true)) { |
| 9364 return ''; |
| 9365 } |
| 9366 encounteredNodes.push(element); |
| 9367 var role = element.getAttribute('role'); |
| 9368 returnText = checkARIA(element, inLabelledByContext, inControlContext)
; |
| 9369 if (nonEmptyText(returnText)) { |
| 9370 return returnText; |
| 9371 } |
| 9372 returnText = checkNative(element, inLabelledByContext, inControlContex
t); |
| 9373 if (nonEmptyText(returnText)) { |
| 9374 return returnText; |
| 9375 } |
| 9376 if (inControlContext) { |
| 9377 returnText = formValueText(element); |
| 9378 if (nonEmptyText(returnText)) { |
| 9379 return returnText; |
| 9380 } |
| 9381 } |
| 9382 if (!shouldNeverCheckSubtree(element) && (!role || aria.getRolesWithNa
meFromContents().indexOf(role) !== -1)) { |
| 9383 returnText = getInnerText(element, inLabelledByContext, inControlCon
text); |
| 9384 if (nonEmptyText(returnText)) { |
| 9385 return returnText; |
| 9386 } |
| 9387 } |
| 9388 if (element.hasAttribute('title')) { |
| 9389 return element.getAttribute('title'); |
| 9390 } |
| 9391 return ''; |
| 9392 }; |
| 9393 return text.sanitize(accessibleNameComputation(element, inLabelledByCont
ext)); |
| 9394 }; |
| 9395 text.label = function(node) { |
| 9396 var ref, candidate, doc; |
| 9397 candidate = aria.label(node); |
| 9398 if (candidate) { |
| 9399 return candidate; |
| 9400 } |
| 9401 if (node.actualNode.id) { |
| 9402 doc = axe.commons.dom.getRootNode(node.actualNode); |
| 9403 ref = doc.querySelector('label[for="' + axe.utils.escapeSelector(node.
actualNode.id) + '"]'); |
| 9404 ref = axe.utils.getNodeFromTree(axe._tree[0], ref); |
| 9405 candidate = ref && text.visible(ref, true); |
| 9406 if (candidate) { |
| 9407 return candidate; |
| 9408 } |
| 9409 } |
| 9410 ref = dom.findUp(node.actualNode, 'label'); |
| 9411 ref = axe.utils.getNodeFromTree(axe._tree[0], ref); |
| 9412 candidate = ref && text.visible(ref, true); |
| 9413 if (candidate) { |
| 9414 return candidate; |
| 9415 } |
| 9416 return null; |
| 9417 }; |
| 9418 text.sanitize = function(str) { |
| 9419 'use strict'; |
| 9420 return str.replace(/\r\n/g, '\n').replace(/\u00A0/g, ' ').replace(/[\s]{
2,}/g, ' ').trim(); |
| 9421 }; |
| 9422 text.visible = function(element, screenReader, noRecursing) { |
| 9423 'use strict'; |
| 9424 var index, child, nodeValue, childNodes = element.children, length = chi
ldNodes.length, result = ''; |
| 9425 for (index = 0; index < length; index++) { |
| 9426 child = childNodes[index]; |
| 9427 if (child.actualNode.nodeType === 3) { |
| 9428 nodeValue = child.actualNode.nodeValue; |
| 9429 if (nodeValue && dom.isVisible(element.actualNode, screenReader)) { |
| 9430 result += nodeValue; |
| 9431 } |
| 9432 } else if (!noRecursing) { |
| 9433 result += text.visible(child, screenReader); |
| 9434 } |
| 9435 } |
| 9436 return text.sanitize(result); |
| 9437 }; |
| 9438 axe.utils.toArray = function(thing) { |
| 9439 'use strict'; |
| 9440 return Array.prototype.slice.call(thing); |
| 9441 }; |
| 9442 axe.utils.tokenList = function(str) { |
| 9443 'use strict'; |
| 9444 return str.trim().replace(/\s{2,}/g, ' ').split(' '); |
| 9445 }; |
| 9446 var langs = [ 'aa', 'ab', 'ae', 'af', 'ak', 'am', 'an', 'ar', 'as', 'av',
'ay', 'az', 'ba', 'be', 'bg', 'bh', 'bi', 'bm', 'bn', 'bo', 'br', 'bs', 'ca', 'c
e', 'ch', 'co', 'cr', 'cs', 'cu', 'cv', 'cy', 'da', 'de', 'dv', 'dz', 'ee', 'el'
, 'en', 'eo', 'es', 'et', 'eu', 'fa', 'ff', 'fi', 'fj', 'fo', 'fr', 'fy', 'ga',
'gd', 'gl', 'gn', 'gu', 'gv', 'ha', 'he', 'hi', 'ho', 'hr', 'ht', 'hu', 'hy', 'h
z', 'ia', 'id', 'ie', 'ig', 'ii', 'ik', 'in', 'io', 'is', 'it', 'iu', 'iw', 'ja'
, 'ji', 'jv', 'jw', 'ka', 'kg', 'ki', 'kj', 'kk', 'kl', 'km', 'kn', 'ko', 'kr',
'ks', 'ku', 'kv', 'kw', 'ky', 'la', 'lb', 'lg', 'li', 'ln', 'lo', 'lt', 'lu', 'l
v', 'mg', 'mh', 'mi', 'mk', 'ml', 'mn', 'mo', 'mr', 'ms', 'mt', 'my', 'na', 'nb'
, 'nd', 'ne', 'ng', 'nl', 'nn', 'no', 'nr', 'nv', 'ny', 'oc', 'oj', 'om', 'or',
'os', 'pa', 'pi', 'pl', 'ps', 'pt', 'qu', 'rm', 'rn', 'ro', 'ru', 'rw', 'sa', 's
c', 'sd', 'se', 'sg', 'sh', 'si', 'sk', 'sl', 'sm', 'sn', 'so', 'sq', 'sr', 'ss'
, 'st', 'su', 'sv', 'sw', 'ta', 'te', 'tg', 'th', 'ti', 'tk', 'tl', 'tn', 'to',
'tr', 'ts', 'tt', 'tw', 'ty', 'ug', 'uk', 'ur', 'uz', 've', 'vi', 'vo', 'wa', 'w
o', 'xh', 'yi', 'yo', 'za', 'zh', 'zu', 'aaa', 'aab', 'aac', 'aad', 'aae', 'aaf'
, 'aag', 'aah', 'aai', 'aak', 'aal', 'aam', 'aan', 'aao', 'aap', 'aaq', 'aas', '
aat', 'aau', 'aav', 'aaw', 'aax', 'aaz', 'aba', 'abb', 'abc', 'abd', 'abe', 'abf
', 'abg', 'abh', 'abi', 'abj', 'abl', 'abm', 'abn', 'abo', 'abp', 'abq', 'abr',
'abs', 'abt', 'abu', 'abv', 'abw', 'abx', 'aby', 'abz', 'aca', 'acb', 'acd', 'ac
e', 'acf', 'ach', 'aci', 'ack', 'acl', 'acm', 'acn', 'acp', 'acq', 'acr', 'acs',
'act', 'acu', 'acv', 'acw', 'acx', 'acy', 'acz', 'ada', 'adb', 'add', 'ade', 'a
df', 'adg', 'adh', 'adi', 'adj', 'adl', 'adn', 'ado', 'adp', 'adq', 'adr', 'ads'
, 'adt', 'adu', 'adw', 'adx', 'ady', 'adz', 'aea', 'aeb', 'aec', 'aed', 'aee', '
aek', 'ael', 'aem', 'aen', 'aeq', 'aer', 'aes', 'aeu', 'aew', 'aey', 'aez', 'afa
', 'afb', 'afd', 'afe', 'afg', 'afh', 'afi', 'afk', 'afn', 'afo', 'afp', 'afs',
'aft', 'afu', 'afz', 'aga', 'agb', 'agc', 'agd', 'age', 'agf', 'agg', 'agh', 'ag
i', 'agj', 'agk', 'agl', 'agm', 'agn', 'ago', 'agp', 'agq', 'agr', 'ags', 'agt',
'agu', 'agv', 'agw', 'agx', 'agy', 'agz', 'aha', 'ahb', 'ahg', 'ahh', 'ahi', 'a
hk', 'ahl', 'ahm', 'ahn', 'aho', 'ahp', 'ahr', 'ahs', 'aht', 'aia', 'aib', 'aic'
, 'aid', 'aie', 'aif', 'aig', 'aih', 'aii', 'aij', 'aik', 'ail', 'aim', 'ain', '
aio', 'aip', 'aiq', 'air', 'ais', 'ait', 'aiw', 'aix', 'aiy', 'aja', 'ajg', 'aji
', 'ajn', 'ajp', 'ajt', 'aju', 'ajw', 'ajz', 'akb', 'akc', 'akd', 'ake', 'akf',
'akg', 'akh', 'aki', 'akj', 'akk', 'akl', 'akm', 'ako', 'akp', 'akq', 'akr', 'ak
s', 'akt', 'aku', 'akv', 'akw', 'akx', 'aky', 'akz', 'ala', 'alc', 'ald', 'ale',
'alf', 'alg', 'alh', 'ali', 'alj', 'alk', 'all', 'alm', 'aln', 'alo', 'alp', 'a
lq', 'alr', 'als', 'alt', 'alu', 'alv', 'alw', 'alx', 'aly', 'alz', 'ama', 'amb'
, 'amc', 'ame', 'amf', 'amg', 'ami', 'amj', 'amk', 'aml', 'amm', 'amn', 'amo', '
amp', 'amq', 'amr', 'ams', 'amt', 'amu', 'amv', 'amw', 'amx', 'amy', 'amz', 'ana
', 'anb', 'anc', 'and', 'ane', 'anf', 'ang', 'anh', 'ani', 'anj', 'ank', 'anl',
'anm', 'ann', 'ano', 'anp', 'anq', 'anr', 'ans', 'ant', 'anu', 'anv', 'anw', 'an
x', 'any', 'anz', 'aoa', 'aob', 'aoc', 'aod', 'aoe', 'aof', 'aog', 'aoh', 'aoi',
'aoj', 'aok', 'aol', 'aom', 'aon', 'aor', 'aos', 'aot', 'aou', 'aox', 'aoz', 'a
pa', 'apb', 'apc', 'apd', 'ape', 'apf', 'apg', 'aph', 'api', 'apj', 'apk', 'apl'
, 'apm', 'apn', 'apo', 'app', 'apq', 'apr', 'aps', 'apt', 'apu', 'apv', 'apw', '
apx', 'apy', 'apz', 'aqa', 'aqc', 'aqd', 'aqg', 'aql', 'aqm', 'aqn', 'aqp', 'aqr
', 'aqt', 'aqz', 'arb', 'arc', 'ard', 'are', 'arh', 'ari', 'arj', 'ark', 'arl',
'arn', 'aro', 'arp', 'arq', 'arr', 'ars', 'art', 'aru', 'arv', 'arw', 'arx', 'ar
y', 'arz', 'asa', 'asb', 'asc', 'asd', 'ase', 'asf', 'asg', 'ash', 'asi', 'asj',
'ask', 'asl', 'asn', 'aso', 'asp', 'asq', 'asr', 'ass', 'ast', 'asu', 'asv', 'a
sw', 'asx', 'asy', 'asz', 'ata', 'atb', 'atc', 'atd', 'ate', 'atg', 'ath', 'ati'
, 'atj', 'atk', 'atl', 'atm', 'atn', 'ato', 'atp', 'atq', 'atr', 'ats', 'att', '
atu', 'atv', 'atw', 'atx', 'aty', 'atz', 'aua', 'aub', 'auc', 'aud', 'aue', 'auf
', 'aug', 'auh', 'aui', 'auj', 'auk', 'aul', 'aum', 'aun', 'auo', 'aup', 'auq',
'aur', 'aus', 'aut', 'auu', 'auw', 'aux', 'auy', 'auz', 'avb', 'avd', 'avi', 'av
k', 'avl', 'avm', 'avn', 'avo', 'avs', 'avt', 'avu', 'avv', 'awa', 'awb', 'awc',
'awd', 'awe', 'awg', 'awh', 'awi', 'awk', 'awm', 'awn', 'awo', 'awr', 'aws', 'a
wt', 'awu', 'awv', 'aww', 'awx', 'awy', 'axb', 'axe', 'axg', 'axk', 'axl', 'axm'
, 'axx', 'aya', 'ayb', 'ayc', 'ayd', 'aye', 'ayg', 'ayh', 'ayi', 'ayk', 'ayl', '
ayn', 'ayo', 'ayp', 'ayq', 'ayr', 'ays', 'ayt', 'ayu', 'ayx', 'ayy', 'ayz', 'aza
', 'azb', 'azc', 'azd', 'azg', 'azj', 'azm', 'azn', 'azo', 'azt', 'azz', 'baa',
'bab', 'bac', 'bad', 'bae', 'baf', 'bag', 'bah', 'bai', 'baj', 'bal', 'ban', 'ba
o', 'bap', 'bar', 'bas', 'bat', 'bau', 'bav', 'baw', 'bax', 'bay', 'baz', 'bba',
'bbb', 'bbc', 'bbd', 'bbe', 'bbf', 'bbg', 'bbh', 'bbi', 'bbj', 'bbk', 'bbl', 'b
bm', 'bbn', 'bbo', 'bbp', 'bbq', 'bbr', 'bbs', 'bbt', 'bbu', 'bbv', 'bbw', 'bbx'
, 'bby', 'bbz', 'bca', 'bcb', 'bcc', 'bcd', 'bce', 'bcf', 'bcg', 'bch', 'bci', '
bcj', 'bck', 'bcl', 'bcm', 'bcn', 'bco', 'bcp', 'bcq', 'bcr', 'bcs', 'bct', 'bcu
', 'bcv', 'bcw', 'bcy', 'bcz', 'bda', 'bdb', 'bdc', 'bdd', 'bde', 'bdf', 'bdg',
'bdh', 'bdi', 'bdj', 'bdk', 'bdl', 'bdm', 'bdn', 'bdo', 'bdp', 'bdq', 'bdr', 'bd
s', 'bdt', 'bdu', 'bdv', 'bdw', 'bdx', 'bdy', 'bdz', 'bea', 'beb', 'bec', 'bed',
'bee', 'bef', 'beg', 'beh', 'bei', 'bej', 'bek', 'bem', 'beo', 'bep', 'beq', 'b
er', 'bes', 'bet', 'beu', 'bev', 'bew', 'bex', 'bey', 'bez', 'bfa', 'bfb', 'bfc'
, 'bfd', 'bfe', 'bff', 'bfg', 'bfh', 'bfi', 'bfj', 'bfk', 'bfl', 'bfm', 'bfn', '
bfo', 'bfp', 'bfq', 'bfr', 'bfs', 'bft', 'bfu', 'bfw', 'bfx', 'bfy', 'bfz', 'bga
', 'bgb', 'bgc', 'bgd', 'bge', 'bgf', 'bgg', 'bgi', 'bgj', 'bgk', 'bgl', 'bgm',
'bgn', 'bgo', 'bgp', 'bgq', 'bgr', 'bgs', 'bgt', 'bgu', 'bgv', 'bgw', 'bgx', 'bg
y', 'bgz', 'bha', 'bhb', 'bhc', 'bhd', 'bhe', 'bhf', 'bhg', 'bhh', 'bhi', 'bhj',
'bhk', 'bhl', 'bhm', 'bhn', 'bho', 'bhp', 'bhq', 'bhr', 'bhs', 'bht', 'bhu', 'b
hv', 'bhw', 'bhx', 'bhy', 'bhz', 'bia', 'bib', 'bic', 'bid', 'bie', 'bif', 'big'
, 'bij', 'bik', 'bil', 'bim', 'bin', 'bio', 'bip', 'biq', 'bir', 'bit', 'biu', '
biv', 'biw', 'bix', 'biy', 'biz', 'bja', 'bjb', 'bjc', 'bjd', 'bje', 'bjf', 'bjg
', 'bjh', 'bji', 'bjj', 'bjk', 'bjl', 'bjm', 'bjn', 'bjo', 'bjp', 'bjq', 'bjr',
'bjs', 'bjt', 'bju', 'bjv', 'bjw', 'bjx', 'bjy', 'bjz', 'bka', 'bkb', 'bkc', 'bk
d', 'bkf', 'bkg', 'bkh', 'bki', 'bkj', 'bkk', 'bkl', 'bkm', 'bkn', 'bko', 'bkp',
'bkq', 'bkr', 'bks', 'bkt', 'bku', 'bkv', 'bkw', 'bkx', 'bky', 'bkz', 'bla', 'b
lb', 'blc', 'bld', 'ble', 'blf', 'blg', 'blh', 'bli', 'blj', 'blk', 'bll', 'blm'
, 'bln', 'blo', 'blp', 'blq', 'blr', 'bls', 'blt', 'blv', 'blw', 'blx', 'bly', '
blz', 'bma', 'bmb', 'bmc', 'bmd', 'bme', 'bmf', 'bmg', 'bmh', 'bmi', 'bmj', 'bmk
', 'bml', 'bmm', 'bmn', 'bmo', 'bmp', 'bmq', 'bmr', 'bms', 'bmt', 'bmu', 'bmv',
'bmw', 'bmx', 'bmy', 'bmz', 'bna', 'bnb', 'bnc', 'bnd', 'bne', 'bnf', 'bng', 'bn
i', 'bnj', 'bnk', 'bnl', 'bnm', 'bnn', 'bno', 'bnp', 'bnq', 'bnr', 'bns', 'bnt',
'bnu', 'bnv', 'bnw', 'bnx', 'bny', 'bnz', 'boa', 'bob', 'boe', 'bof', 'bog', 'b
oh', 'boi', 'boj', 'bok', 'bol', 'bom', 'bon', 'boo', 'bop', 'boq', 'bor', 'bot'
, 'bou', 'bov', 'bow', 'box', 'boy', 'boz', 'bpa', 'bpb', 'bpd', 'bpg', 'bph', '
bpi', 'bpj', 'bpk', 'bpl', 'bpm', 'bpn', 'bpo', 'bpp', 'bpq', 'bpr', 'bps', 'bpt
', 'bpu', 'bpv', 'bpw', 'bpx', 'bpy', 'bpz', 'bqa', 'bqb', 'bqc', 'bqd', 'bqf',
'bqg', 'bqh', 'bqi', 'bqj', 'bqk', 'bql', 'bqm', 'bqn', 'bqo', 'bqp', 'bqq', 'bq
r', 'bqs', 'bqt', 'bqu', 'bqv', 'bqw', 'bqx', 'bqy', 'bqz', 'bra', 'brb', 'brc',
'brd', 'brf', 'brg', 'brh', 'bri', 'brj', 'brk', 'brl', 'brm', 'brn', 'bro', 'b
rp', 'brq', 'brr', 'brs', 'brt', 'bru', 'brv', 'brw', 'brx', 'bry', 'brz', 'bsa'
, 'bsb', 'bsc', 'bse', 'bsf', 'bsg', 'bsh', 'bsi', 'bsj', 'bsk', 'bsl', 'bsm', '
bsn', 'bso', 'bsp', 'bsq', 'bsr', 'bss', 'bst', 'bsu', 'bsv', 'bsw', 'bsx', 'bsy
', 'bta', 'btb', 'btc', 'btd', 'bte', 'btf', 'btg', 'bth', 'bti', 'btj', 'btk',
'btl', 'btm', 'btn', 'bto', 'btp', 'btq', 'btr', 'bts', 'btt', 'btu', 'btv', 'bt
w', 'btx', 'bty', 'btz', 'bua', 'bub', 'buc', 'bud', 'bue', 'buf', 'bug', 'buh',
'bui', 'buj', 'buk', 'bum', 'bun', 'buo', 'bup', 'buq', 'bus', 'but', 'buu', 'b
uv', 'buw', 'bux', 'buy', 'buz', 'bva', 'bvb', 'bvc', 'bvd', 'bve', 'bvf', 'bvg'
, 'bvh', 'bvi', 'bvj', 'bvk', 'bvl', 'bvm', 'bvn', 'bvo', 'bvp', 'bvq', 'bvr', '
bvt', 'bvu', 'bvv', 'bvw', 'bvx', 'bvy', 'bvz', 'bwa', 'bwb', 'bwc', 'bwd', 'bwe
', 'bwf', 'bwg', 'bwh', 'bwi', 'bwj', 'bwk', 'bwl', 'bwm', 'bwn', 'bwo', 'bwp',
'bwq', 'bwr', 'bws', 'bwt', 'bwu', 'bww', 'bwx', 'bwy', 'bwz', 'bxa', 'bxb', 'bx
c', 'bxd', 'bxe', 'bxf', 'bxg', 'bxh', 'bxi', 'bxj', 'bxk', 'bxl', 'bxm', 'bxn',
'bxo', 'bxp', 'bxq', 'bxr', 'bxs', 'bxu', 'bxv', 'bxw', 'bxx', 'bxz', 'bya', 'b
yb', 'byc', 'byd', 'bye', 'byf', 'byg', 'byh', 'byi', 'byj', 'byk', 'byl', 'bym'
, 'byn', 'byo', 'byp', 'byq', 'byr', 'bys', 'byt', 'byv', 'byw', 'byx', 'byy', '
byz', 'bza', 'bzb', 'bzc', 'bzd', 'bze', 'bzf', 'bzg', 'bzh', 'bzi', 'bzj', 'bzk
', 'bzl', 'bzm', 'bzn', 'bzo', 'bzp', 'bzq', 'bzr', 'bzs', 'bzt', 'bzu', 'bzv',
'bzw', 'bzx', 'bzy', 'bzz', 'caa', 'cab', 'cac', 'cad', 'cae', 'caf', 'cag', 'ca
h', 'cai', 'caj', 'cak', 'cal', 'cam', 'can', 'cao', 'cap', 'caq', 'car', 'cas',
'cau', 'cav', 'caw', 'cax', 'cay', 'caz', 'cba', 'cbb', 'cbc', 'cbd', 'cbe', 'c
bg', 'cbh', 'cbi', 'cbj', 'cbk', 'cbl', 'cbn', 'cbo', 'cbq', 'cbr', 'cbs', 'cbt'
, 'cbu', 'cbv', 'cbw', 'cby', 'cca', 'ccc', 'ccd', 'cce', 'ccg', 'cch', 'ccj', '
ccl', 'ccm', 'ccn', 'cco', 'ccp', 'ccq', 'ccr', 'ccs', 'cda', 'cdc', 'cdd', 'cde
', 'cdf', 'cdg', 'cdh', 'cdi', 'cdj', 'cdm', 'cdn', 'cdo', 'cdr', 'cds', 'cdy',
'cdz', 'cea', 'ceb', 'ceg', 'cek', 'cel', 'cen', 'cet', 'cfa', 'cfd', 'cfg', 'cf
m', 'cga', 'cgc', 'cgg', 'cgk', 'chb', 'chc', 'chd', 'chf', 'chg', 'chh', 'chj',
'chk', 'chl', 'chm', 'chn', 'cho', 'chp', 'chq', 'chr', 'cht', 'chw', 'chx', 'c
hy', 'chz', 'cia', 'cib', 'cic', 'cid', 'cie', 'cih', 'cik', 'cim', 'cin', 'cip'
, 'cir', 'ciw', 'ciy', 'cja', 'cje', 'cjh', 'cji', 'cjk', 'cjm', 'cjn', 'cjo', '
cjp', 'cjr', 'cjs', 'cjv', 'cjy', 'cka', 'ckb', 'ckh', 'ckl', 'ckn', 'cko', 'ckq
', 'ckr', 'cks', 'ckt', 'cku', 'ckv', 'ckx', 'cky', 'ckz', 'cla', 'clc', 'cld',
'cle', 'clh', 'cli', 'clj', 'clk', 'cll', 'clm', 'clo', 'clt', 'clu', 'clw', 'cl
y', 'cma', 'cmc', 'cme', 'cmg', 'cmi', 'cmk', 'cml', 'cmm', 'cmn', 'cmo', 'cmr',
'cms', 'cmt', 'cna', 'cnb', 'cnc', 'cng', 'cnh', 'cni', 'cnk', 'cnl', 'cno', 'c
ns', 'cnt', 'cnu', 'cnw', 'cnx', 'coa', 'cob', 'coc', 'cod', 'coe', 'cof', 'cog'
, 'coh', 'coj', 'cok', 'col', 'com', 'con', 'coo', 'cop', 'coq', 'cot', 'cou', '
cov', 'cow', 'cox', 'coy', 'coz', 'cpa', 'cpb', 'cpc', 'cpe', 'cpf', 'cpg', 'cpi
', 'cpn', 'cpo', 'cpp', 'cps', 'cpu', 'cpx', 'cpy', 'cqd', 'cqu', 'cra', 'crb',
'crc', 'crd', 'crf', 'crg', 'crh', 'cri', 'crj', 'crk', 'crl', 'crm', 'crn', 'cr
o', 'crp', 'crq', 'crr', 'crs', 'crt', 'crv', 'crw', 'crx', 'cry', 'crz', 'csa',
'csb', 'csc', 'csd', 'cse', 'csf', 'csg', 'csh', 'csi', 'csj', 'csk', 'csl', 'c
sm', 'csn', 'cso', 'csq', 'csr', 'css', 'cst', 'csu', 'csv', 'csw', 'csy', 'csz'
, 'cta', 'ctc', 'ctd', 'cte', 'ctg', 'cth', 'ctl', 'ctm', 'ctn', 'cto', 'ctp', '
cts', 'ctt', 'ctu', 'ctz', 'cua', 'cub', 'cuc', 'cug', 'cuh', 'cui', 'cuj', 'cuk
', 'cul', 'cum', 'cuo', 'cup', 'cuq', 'cur', 'cus', 'cut', 'cuu', 'cuv', 'cuw',
'cux', 'cvg', 'cvn', 'cwa', 'cwb', 'cwd', 'cwe', 'cwg', 'cwt', 'cya', 'cyb', 'cy
o', 'czh', 'czk', 'czn', 'czo', 'czt', 'daa', 'dac', 'dad', 'dae', 'daf', 'dag',
'dah', 'dai', 'daj', 'dak', 'dal', 'dam', 'dao', 'dap', 'daq', 'dar', 'das', 'd
au', 'dav', 'daw', 'dax', 'day', 'daz', 'dba', 'dbb', 'dbd', 'dbe', 'dbf', 'dbg'
, 'dbi', 'dbj', 'dbl', 'dbm', 'dbn', 'dbo', 'dbp', 'dbq', 'dbr', 'dbt', 'dbu', '
dbv', 'dbw', 'dby', 'dcc', 'dcr', 'dda', 'ddd', 'dde', 'ddg', 'ddi', 'ddj', 'ddn
', 'ddo', 'ddr', 'dds', 'ddw', 'dec', 'ded', 'dee', 'def', 'deg', 'deh', 'dei',
'dek', 'del', 'dem', 'den', 'dep', 'deq', 'der', 'des', 'dev', 'dez', 'dga', 'dg
b', 'dgc', 'dgd', 'dge', 'dgg', 'dgh', 'dgi', 'dgk', 'dgl', 'dgn', 'dgo', 'dgr',
'dgs', 'dgt', 'dgu', 'dgw', 'dgx', 'dgz', 'dha', 'dhd', 'dhg', 'dhi', 'dhl', 'd
hm', 'dhn', 'dho', 'dhr', 'dhs', 'dhu', 'dhv', 'dhw', 'dhx', 'dia', 'dib', 'dic'
, 'did', 'dif', 'dig', 'dih', 'dii', 'dij', 'dik', 'dil', 'dim', 'din', 'dio', '
dip', 'diq', 'dir', 'dis', 'dit', 'diu', 'diw', 'dix', 'diy', 'diz', 'dja', 'djb
', 'djc', 'djd', 'dje', 'djf', 'dji', 'djj', 'djk', 'djl', 'djm', 'djn', 'djo',
'djr', 'dju', 'djw', 'dka', 'dkk', 'dkl', 'dkr', 'dks', 'dkx', 'dlg', 'dlk', 'dl
m', 'dln', 'dma', 'dmb', 'dmc', 'dmd', 'dme', 'dmg', 'dmk', 'dml', 'dmm', 'dmn',
'dmo', 'dmr', 'dms', 'dmu', 'dmv', 'dmw', 'dmx', 'dmy', 'dna', 'dnd', 'dne', 'd
ng', 'dni', 'dnj', 'dnk', 'dnn', 'dnr', 'dnt', 'dnu', 'dnv', 'dnw', 'dny', 'doa'
, 'dob', 'doc', 'doe', 'dof', 'doh', 'doi', 'dok', 'dol', 'don', 'doo', 'dop', '
doq', 'dor', 'dos', 'dot', 'dov', 'dow', 'dox', 'doy', 'doz', 'dpp', 'dra', 'drb
', 'drc', 'drd', 'dre', 'drg', 'drh', 'dri', 'drl', 'drn', 'dro', 'drq', 'drr',
'drs', 'drt', 'dru', 'drw', 'dry', 'dsb', 'dse', 'dsh', 'dsi', 'dsl', 'dsn', 'ds
o', 'dsq', 'dta', 'dtb', 'dtd', 'dth', 'dti', 'dtk', 'dtm', 'dtn', 'dto', 'dtp',
'dtr', 'dts', 'dtt', 'dtu', 'dty', 'dua', 'dub', 'duc', 'dud', 'due', 'duf', 'd
ug', 'duh', 'dui', 'duj', 'duk', 'dul', 'dum', 'dun', 'duo', 'dup', 'duq', 'dur'
, 'dus', 'duu', 'duv', 'duw', 'dux', 'duy', 'duz', 'dva', 'dwa', 'dwl', 'dwr', '
dws', 'dwu', 'dww', 'dwy', 'dya', 'dyb', 'dyd', 'dyg', 'dyi', 'dym', 'dyn', 'dyo
', 'dyu', 'dyy', 'dza', 'dzd', 'dze', 'dzg', 'dzl', 'dzn', 'eaa', 'ebg', 'ebk',
'ebo', 'ebr', 'ebu', 'ecr', 'ecs', 'ecy', 'eee', 'efa', 'efe', 'efi', 'ega', 'eg
l', 'ego', 'egx', 'egy', 'ehu', 'eip', 'eit', 'eiv', 'eja', 'eka', 'ekc', 'eke',
'ekg', 'eki', 'ekk', 'ekl', 'ekm', 'eko', 'ekp', 'ekr', 'eky', 'ele', 'elh', 'e
li', 'elk', 'elm', 'elo', 'elp', 'elu', 'elx', 'ema', 'emb', 'eme', 'emg', 'emi'
, 'emk', 'emm', 'emn', 'emo', 'emp', 'ems', 'emu', 'emw', 'emx', 'emy', 'ena', '
enb', 'enc', 'end', 'enf', 'enh', 'enl', 'enm', 'enn', 'eno', 'enq', 'enr', 'enu
', 'env', 'enw', 'enx', 'eot', 'epi', 'era', 'erg', 'erh', 'eri', 'erk', 'ero',
'err', 'ers', 'ert', 'erw', 'ese', 'esg', 'esh', 'esi', 'esk', 'esl', 'esm', 'es
n', 'eso', 'esq', 'ess', 'esu', 'esx', 'esy', 'etb', 'etc', 'eth', 'etn', 'eto',
'etr', 'ets', 'ett', 'etu', 'etx', 'etz', 'euq', 'eve', 'evh', 'evn', 'ewo', 'e
xt', 'eya', 'eyo', 'eza', 'eze', 'faa', 'fab', 'fad', 'faf', 'fag', 'fah', 'fai'
, 'faj', 'fak', 'fal', 'fam', 'fan', 'fap', 'far', 'fat', 'fau', 'fax', 'fay', '
faz', 'fbl', 'fcs', 'fer', 'ffi', 'ffm', 'fgr', 'fia', 'fie', 'fil', 'fip', 'fir
', 'fit', 'fiu', 'fiw', 'fkk', 'fkv', 'fla', 'flh', 'fli', 'fll', 'fln', 'flr',
'fly', 'fmp', 'fmu', 'fnb', 'fng', 'fni', 'fod', 'foi', 'fom', 'fon', 'for', 'fo
s', 'fox', 'fpe', 'fqs', 'frc', 'frd', 'frk', 'frm', 'fro', 'frp', 'frq', 'frr',
'frs', 'frt', 'fse', 'fsl', 'fss', 'fub', 'fuc', 'fud', 'fue', 'fuf', 'fuh', 'f
ui', 'fuj', 'fum', 'fun', 'fuq', 'fur', 'fut', 'fuu', 'fuv', 'fuy', 'fvr', 'fwa'
, 'fwe', 'gaa', 'gab', 'gac', 'gad', 'gae', 'gaf', 'gag', 'gah', 'gai', 'gaj', '
gak', 'gal', 'gam', 'gan', 'gao', 'gap', 'gaq', 'gar', 'gas', 'gat', 'gau', 'gav
', 'gaw', 'gax', 'gay', 'gaz', 'gba', 'gbb', 'gbc', 'gbd', 'gbe', 'gbf', 'gbg',
'gbh', 'gbi', 'gbj', 'gbk', 'gbl', 'gbm', 'gbn', 'gbo', 'gbp', 'gbq', 'gbr', 'gb
s', 'gbu', 'gbv', 'gbw', 'gbx', 'gby', 'gbz', 'gcc', 'gcd', 'gce', 'gcf', 'gcl',
'gcn', 'gcr', 'gct', 'gda', 'gdb', 'gdc', 'gdd', 'gde', 'gdf', 'gdg', 'gdh', 'g
di', 'gdj', 'gdk', 'gdl', 'gdm', 'gdn', 'gdo', 'gdq', 'gdr', 'gds', 'gdt', 'gdu'
, 'gdx', 'gea', 'geb', 'gec', 'ged', 'geg', 'geh', 'gei', 'gej', 'gek', 'gel', '
gem', 'geq', 'ges', 'gev', 'gew', 'gex', 'gey', 'gez', 'gfk', 'gft', 'gfx', 'gga
', 'ggb', 'ggd', 'gge', 'ggg', 'ggk', 'ggl', 'ggn', 'ggo', 'ggr', 'ggt', 'ggu',
'ggw', 'gha', 'ghc', 'ghe', 'ghh', 'ghk', 'ghl', 'ghn', 'gho', 'ghr', 'ghs', 'gh
t', 'gia', 'gib', 'gic', 'gid', 'gie', 'gig', 'gih', 'gil', 'gim', 'gin', 'gio',
'gip', 'giq', 'gir', 'gis', 'git', 'giu', 'giw', 'gix', 'giy', 'giz', 'gji', 'g
jk', 'gjm', 'gjn', 'gjr', 'gju', 'gka', 'gke', 'gkn', 'gko', 'gkp', 'gku', 'glc'
, 'gld', 'glh', 'gli', 'glj', 'glk', 'gll', 'glo', 'glr', 'glu', 'glw', 'gly', '
gma', 'gmb', 'gmd', 'gme', 'gmg', 'gmh', 'gml', 'gmm', 'gmn', 'gmq', 'gmu', 'gmv
', 'gmw', 'gmx', 'gmy', 'gmz', 'gna', 'gnb', 'gnc', 'gnd', 'gne', 'gng', 'gnh',
'gni', 'gnk', 'gnl', 'gnm', 'gnn', 'gno', 'gnq', 'gnr', 'gnt', 'gnu', 'gnw', 'gn
z', 'goa', 'gob', 'goc', 'god', 'goe', 'gof', 'gog', 'goh', 'goi', 'goj', 'gok',
'gol', 'gom', 'gon', 'goo', 'gop', 'goq', 'gor', 'gos', 'got', 'gou', 'gow', 'g
ox', 'goy', 'goz', 'gpa', 'gpe', 'gpn', 'gqa', 'gqi', 'gqn', 'gqr', 'gqu', 'gra'
, 'grb', 'grc', 'grd', 'grg', 'grh', 'gri', 'grj', 'grk', 'grm', 'gro', 'grq', '
grr', 'grs', 'grt', 'gru', 'grv', 'grw', 'grx', 'gry', 'grz', 'gse', 'gsg', 'gsl
', 'gsm', 'gsn', 'gso', 'gsp', 'gss', 'gsw', 'gta', 'gti', 'gtu', 'gua', 'gub',
'guc', 'gud', 'gue', 'guf', 'gug', 'guh', 'gui', 'guk', 'gul', 'gum', 'gun', 'gu
o', 'gup', 'guq', 'gur', 'gus', 'gut', 'guu', 'guv', 'guw', 'gux', 'guz', 'gva',
'gvc', 'gve', 'gvf', 'gvj', 'gvl', 'gvm', 'gvn', 'gvo', 'gvp', 'gvr', 'gvs', 'g
vy', 'gwa', 'gwb', 'gwc', 'gwd', 'gwe', 'gwf', 'gwg', 'gwi', 'gwj', 'gwm', 'gwn'
, 'gwr', 'gwt', 'gwu', 'gww', 'gwx', 'gxx', 'gya', 'gyb', 'gyd', 'gye', 'gyf', '
gyg', 'gyi', 'gyl', 'gym', 'gyn', 'gyr', 'gyy', 'gza', 'gzi', 'gzn', 'haa', 'hab
', 'hac', 'had', 'hae', 'haf', 'hag', 'hah', 'hai', 'haj', 'hak', 'hal', 'ham',
'han', 'hao', 'hap', 'haq', 'har', 'has', 'hav', 'haw', 'hax', 'hay', 'haz', 'hb
a', 'hbb', 'hbn', 'hbo', 'hbu', 'hca', 'hch', 'hdn', 'hds', 'hdy', 'hea', 'hed',
'heg', 'heh', 'hei', 'hem', 'hgm', 'hgw', 'hhi', 'hhr', 'hhy', 'hia', 'hib', 'h
id', 'hif', 'hig', 'hih', 'hii', 'hij', 'hik', 'hil', 'him', 'hio', 'hir', 'hit'
, 'hiw', 'hix', 'hji', 'hka', 'hke', 'hkk', 'hks', 'hla', 'hlb', 'hld', 'hle', '
hlt', 'hlu', 'hma', 'hmb', 'hmc', 'hmd', 'hme', 'hmf', 'hmg', 'hmh', 'hmi', 'hmj
', 'hmk', 'hml', 'hmm', 'hmn', 'hmp', 'hmq', 'hmr', 'hms', 'hmt', 'hmu', 'hmv',
'hmw', 'hmx', 'hmy', 'hmz', 'hna', 'hnd', 'hne', 'hnh', 'hni', 'hnj', 'hnn', 'hn
o', 'hns', 'hnu', 'hoa', 'hob', 'hoc', 'hod', 'hoe', 'hoh', 'hoi', 'hoj', 'hok',
'hol', 'hom', 'hoo', 'hop', 'hor', 'hos', 'hot', 'hov', 'how', 'hoy', 'hoz', 'h
po', 'hps', 'hra', 'hrc', 'hre', 'hrk', 'hrm', 'hro', 'hrp', 'hrr', 'hrt', 'hru'
, 'hrw', 'hrx', 'hrz', 'hsb', 'hsh', 'hsl', 'hsn', 'hss', 'hti', 'hto', 'hts', '
htu', 'htx', 'hub', 'huc', 'hud', 'hue', 'huf', 'hug', 'huh', 'hui', 'huj', 'huk
', 'hul', 'hum', 'huo', 'hup', 'huq', 'hur', 'hus', 'hut', 'huu', 'huv', 'huw',
'hux', 'huy', 'huz', 'hvc', 'hve', 'hvk', 'hvn', 'hvv', 'hwa', 'hwc', 'hwo', 'hy
a', 'hyx', 'iai', 'ian', 'iap', 'iar', 'iba', 'ibb', 'ibd', 'ibe', 'ibg', 'ibh',
'ibi', 'ibl', 'ibm', 'ibn', 'ibr', 'ibu', 'iby', 'ica', 'ich', 'icl', 'icr', 'i
da', 'idb', 'idc', 'idd', 'ide', 'idi', 'idr', 'ids', 'idt', 'idu', 'ifa', 'ifb'
, 'ife', 'iff', 'ifk', 'ifm', 'ifu', 'ify', 'igb', 'ige', 'igg', 'igl', 'igm', '
ign', 'igo', 'igs', 'igw', 'ihb', 'ihi', 'ihp', 'ihw', 'iin', 'iir', 'ijc', 'ije
', 'ijj', 'ijn', 'ijo', 'ijs', 'ike', 'iki', 'ikk', 'ikl', 'iko', 'ikp', 'ikr',
'iks', 'ikt', 'ikv', 'ikw', 'ikx', 'ikz', 'ila', 'ilb', 'ilg', 'ili', 'ilk', 'il
l', 'ilm', 'ilo', 'ilp', 'ils', 'ilu', 'ilv', 'ilw', 'ima', 'ime', 'imi', 'iml',
'imn', 'imo', 'imr', 'ims', 'imy', 'inb', 'inc', 'ine', 'ing', 'inh', 'inj', 'i
nl', 'inm', 'inn', 'ino', 'inp', 'ins', 'int', 'inz', 'ior', 'iou', 'iow', 'ipi'
, 'ipo', 'iqu', 'iqw', 'ira', 'ire', 'irh', 'iri', 'irk', 'irn', 'iro', 'irr', '
iru', 'irx', 'iry', 'isa', 'isc', 'isd', 'ise', 'isg', 'ish', 'isi', 'isk', 'ism
', 'isn', 'iso', 'isr', 'ist', 'isu', 'itb', 'itc', 'itd', 'ite', 'iti', 'itk',
'itl', 'itm', 'ito', 'itr', 'its', 'itt', 'itv', 'itw', 'itx', 'ity', 'itz', 'iu
m', 'ivb', 'ivv', 'iwk', 'iwm', 'iwo', 'iws', 'ixc', 'ixl', 'iya', 'iyo', 'iyx',
'izh', 'izi', 'izr', 'izz', 'jaa', 'jab', 'jac', 'jad', 'jae', 'jaf', 'jah', 'j
aj', 'jak', 'jal', 'jam', 'jan', 'jao', 'jaq', 'jar', 'jas', 'jat', 'jau', 'jax'
, 'jay', 'jaz', 'jbe', 'jbi', 'jbj', 'jbk', 'jbn', 'jbo', 'jbr', 'jbt', 'jbu', '
jbw', 'jcs', 'jct', 'jda', 'jdg', 'jdt', 'jeb', 'jee', 'jeg', 'jeh', 'jei', 'jek
', 'jel', 'jen', 'jer', 'jet', 'jeu', 'jgb', 'jge', 'jgk', 'jgo', 'jhi', 'jhs',
'jia', 'jib', 'jic', 'jid', 'jie', 'jig', 'jih', 'jii', 'jil', 'jim', 'jio', 'ji
q', 'jit', 'jiu', 'jiv', 'jiy', 'jje', 'jjr', 'jka', 'jkm', 'jko', 'jkp', 'jkr',
'jku', 'jle', 'jls', 'jma', 'jmb', 'jmc', 'jmd', 'jmi', 'jml', 'jmn', 'jmr', 'j
ms', 'jmw', 'jmx', 'jna', 'jnd', 'jng', 'jni', 'jnj', 'jnl', 'jns', 'job', 'jod'
, 'jog', 'jor', 'jos', 'jow', 'jpa', 'jpr', 'jpx', 'jqr', 'jra', 'jrb', 'jrr', '
jrt', 'jru', 'jsl', 'jua', 'jub', 'juc', 'jud', 'juh', 'jui', 'juk', 'jul', 'jum
', 'jun', 'juo', 'jup', 'jur', 'jus', 'jut', 'juu', 'juw', 'juy', 'jvd', 'jvn',
'jwi', 'jya', 'jye', 'jyy', 'kaa', 'kab', 'kac', 'kad', 'kae', 'kaf', 'kag', 'ka
h', 'kai', 'kaj', 'kak', 'kam', 'kao', 'kap', 'kaq', 'kar', 'kav', 'kaw', 'kax',
'kay', 'kba', 'kbb', 'kbc', 'kbd', 'kbe', 'kbf', 'kbg', 'kbh', 'kbi', 'kbj', 'k
bk', 'kbl', 'kbm', 'kbn', 'kbo', 'kbp', 'kbq', 'kbr', 'kbs', 'kbt', 'kbu', 'kbv'
, 'kbw', 'kbx', 'kby', 'kbz', 'kca', 'kcb', 'kcc', 'kcd', 'kce', 'kcf', 'kcg', '
kch', 'kci', 'kcj', 'kck', 'kcl', 'kcm', 'kcn', 'kco', 'kcp', 'kcq', 'kcr', 'kcs
', 'kct', 'kcu', 'kcv', 'kcw', 'kcx', 'kcy', 'kcz', 'kda', 'kdc', 'kdd', 'kde',
'kdf', 'kdg', 'kdh', 'kdi', 'kdj', 'kdk', 'kdl', 'kdm', 'kdn', 'kdo', 'kdp', 'kd
q', 'kdr', 'kdt', 'kdu', 'kdv', 'kdw', 'kdx', 'kdy', 'kdz', 'kea', 'keb', 'kec',
'ked', 'kee', 'kef', 'keg', 'keh', 'kei', 'kej', 'kek', 'kel', 'kem', 'ken', 'k
eo', 'kep', 'keq', 'ker', 'kes', 'ket', 'keu', 'kev', 'kew', 'kex', 'key', 'kez'
, 'kfa', 'kfb', 'kfc', 'kfd', 'kfe', 'kff', 'kfg', 'kfh', 'kfi', 'kfj', 'kfk', '
kfl', 'kfm', 'kfn', 'kfo', 'kfp', 'kfq', 'kfr', 'kfs', 'kft', 'kfu', 'kfv', 'kfw
', 'kfx', 'kfy', 'kfz', 'kga', 'kgb', 'kgc', 'kgd', 'kge', 'kgf', 'kgg', 'kgh',
'kgi', 'kgj', 'kgk', 'kgl', 'kgm', 'kgn', 'kgo', 'kgp', 'kgq', 'kgr', 'kgs', 'kg
t', 'kgu', 'kgv', 'kgw', 'kgx', 'kgy', 'kha', 'khb', 'khc', 'khd', 'khe', 'khf',
'khg', 'khh', 'khi', 'khj', 'khk', 'khl', 'khn', 'kho', 'khp', 'khq', 'khr', 'k
hs', 'kht', 'khu', 'khv', 'khw', 'khx', 'khy', 'khz', 'kia', 'kib', 'kic', 'kid'
, 'kie', 'kif', 'kig', 'kih', 'kii', 'kij', 'kil', 'kim', 'kio', 'kip', 'kiq', '
kis', 'kit', 'kiu', 'kiv', 'kiw', 'kix', 'kiy', 'kiz', 'kja', 'kjb', 'kjc', 'kjd
', 'kje', 'kjf', 'kjg', 'kjh', 'kji', 'kjj', 'kjk', 'kjl', 'kjm', 'kjn', 'kjo',
'kjp', 'kjq', 'kjr', 'kjs', 'kjt', 'kju', 'kjv', 'kjx', 'kjy', 'kjz', 'kka', 'kk
b', 'kkc', 'kkd', 'kke', 'kkf', 'kkg', 'kkh', 'kki', 'kkj', 'kkk', 'kkl', 'kkm',
'kkn', 'kko', 'kkp', 'kkq', 'kkr', 'kks', 'kkt', 'kku', 'kkv', 'kkw', 'kkx', 'k
ky', 'kkz', 'kla', 'klb', 'klc', 'kld', 'kle', 'klf', 'klg', 'klh', 'kli', 'klj'
, 'klk', 'kll', 'klm', 'kln', 'klo', 'klp', 'klq', 'klr', 'kls', 'klt', 'klu', '
klv', 'klw', 'klx', 'kly', 'klz', 'kma', 'kmb', 'kmc', 'kmd', 'kme', 'kmf', 'kmg
', 'kmh', 'kmi', 'kmj', 'kmk', 'kml', 'kmm', 'kmn', 'kmo', 'kmp', 'kmq', 'kmr',
'kms', 'kmt', 'kmu', 'kmv', 'kmw', 'kmx', 'kmy', 'kmz', 'kna', 'knb', 'knc', 'kn
d', 'kne', 'knf', 'kng', 'kni', 'knj', 'knk', 'knl', 'knm', 'knn', 'kno', 'knp',
'knq', 'knr', 'kns', 'knt', 'knu', 'knv', 'knw', 'knx', 'kny', 'knz', 'koa', 'k
oc', 'kod', 'koe', 'kof', 'kog', 'koh', 'koi', 'koj', 'kok', 'kol', 'koo', 'kop'
, 'koq', 'kos', 'kot', 'kou', 'kov', 'kow', 'kox', 'koy', 'koz', 'kpa', 'kpb', '
kpc', 'kpd', 'kpe', 'kpf', 'kpg', 'kph', 'kpi', 'kpj', 'kpk', 'kpl', 'kpm', 'kpn
', 'kpo', 'kpp', 'kpq', 'kpr', 'kps', 'kpt', 'kpu', 'kpv', 'kpw', 'kpx', 'kpy',
'kpz', 'kqa', 'kqb', 'kqc', 'kqd', 'kqe', 'kqf', 'kqg', 'kqh', 'kqi', 'kqj', 'kq
k', 'kql', 'kqm', 'kqn', 'kqo', 'kqp', 'kqq', 'kqr', 'kqs', 'kqt', 'kqu', 'kqv',
'kqw', 'kqx', 'kqy', 'kqz', 'kra', 'krb', 'krc', 'krd', 'kre', 'krf', 'krh', 'k
ri', 'krj', 'krk', 'krl', 'krm', 'krn', 'kro', 'krp', 'krr', 'krs', 'krt', 'kru'
, 'krv', 'krw', 'krx', 'kry', 'krz', 'ksa', 'ksb', 'ksc', 'ksd', 'kse', 'ksf', '
ksg', 'ksh', 'ksi', 'ksj', 'ksk', 'ksl', 'ksm', 'ksn', 'kso', 'ksp', 'ksq', 'ksr
', 'kss', 'kst', 'ksu', 'ksv', 'ksw', 'ksx', 'ksy', 'ksz', 'kta', 'ktb', 'ktc',
'ktd', 'kte', 'ktf', 'ktg', 'kth', 'kti', 'ktj', 'ktk', 'ktl', 'ktm', 'ktn', 'kt
o', 'ktp', 'ktq', 'ktr', 'kts', 'ktt', 'ktu', 'ktv', 'ktw', 'ktx', 'kty', 'ktz',
'kub', 'kuc', 'kud', 'kue', 'kuf', 'kug', 'kuh', 'kui', 'kuj', 'kuk', 'kul', 'k
um', 'kun', 'kuo', 'kup', 'kuq', 'kus', 'kut', 'kuu', 'kuv', 'kuw', 'kux', 'kuy'
, 'kuz', 'kva', 'kvb', 'kvc', 'kvd', 'kve', 'kvf', 'kvg', 'kvh', 'kvi', 'kvj', '
kvk', 'kvl', 'kvm', 'kvn', 'kvo', 'kvp', 'kvq', 'kvr', 'kvs', 'kvt', 'kvu', 'kvv
', 'kvw', 'kvx', 'kvy', 'kvz', 'kwa', 'kwb', 'kwc', 'kwd', 'kwe', 'kwf', 'kwg',
'kwh', 'kwi', 'kwj', 'kwk', 'kwl', 'kwm', 'kwn', 'kwo', 'kwp', 'kwq', 'kwr', 'kw
s', 'kwt', 'kwu', 'kwv', 'kww', 'kwx', 'kwy', 'kwz', 'kxa', 'kxb', 'kxc', 'kxd',
'kxe', 'kxf', 'kxh', 'kxi', 'kxj', 'kxk', 'kxl', 'kxm', 'kxn', 'kxo', 'kxp', 'k
xq', 'kxr', 'kxs', 'kxt', 'kxu', 'kxv', 'kxw', 'kxx', 'kxy', 'kxz', 'kya', 'kyb'
, 'kyc', 'kyd', 'kye', 'kyf', 'kyg', 'kyh', 'kyi', 'kyj', 'kyk', 'kyl', 'kym', '
kyn', 'kyo', 'kyp', 'kyq', 'kyr', 'kys', 'kyt', 'kyu', 'kyv', 'kyw', 'kyx', 'kyy
', 'kyz', 'kza', 'kzb', 'kzc', 'kzd', 'kze', 'kzf', 'kzg', 'kzh', 'kzi', 'kzj',
'kzk', 'kzl', 'kzm', 'kzn', 'kzo', 'kzp', 'kzq', 'kzr', 'kzs', 'kzt', 'kzu', 'kz
v', 'kzw', 'kzx', 'kzy', 'kzz', 'laa', 'lab', 'lac', 'lad', 'lae', 'laf', 'lag',
'lah', 'lai', 'laj', 'lak', 'lal', 'lam', 'lan', 'lap', 'laq', 'lar', 'las', 'l
au', 'law', 'lax', 'lay', 'laz', 'lba', 'lbb', 'lbc', 'lbe', 'lbf', 'lbg', 'lbi'
, 'lbj', 'lbk', 'lbl', 'lbm', 'lbn', 'lbo', 'lbq', 'lbr', 'lbs', 'lbt', 'lbu', '
lbv', 'lbw', 'lbx', 'lby', 'lbz', 'lcc', 'lcd', 'lce', 'lcf', 'lch', 'lcl', 'lcm
', 'lcp', 'lcq', 'lcs', 'lda', 'ldb', 'ldd', 'ldg', 'ldh', 'ldi', 'ldj', 'ldk',
'ldl', 'ldm', 'ldn', 'ldo', 'ldp', 'ldq', 'lea', 'leb', 'lec', 'led', 'lee', 'le
f', 'leg', 'leh', 'lei', 'lej', 'lek', 'lel', 'lem', 'len', 'leo', 'lep', 'leq',
'ler', 'les', 'let', 'leu', 'lev', 'lew', 'lex', 'ley', 'lez', 'lfa', 'lfn', 'l
ga', 'lgb', 'lgg', 'lgh', 'lgi', 'lgk', 'lgl', 'lgm', 'lgn', 'lgq', 'lgr', 'lgt'
, 'lgu', 'lgz', 'lha', 'lhh', 'lhi', 'lhl', 'lhm', 'lhn', 'lhp', 'lhs', 'lht', '
lhu', 'lia', 'lib', 'lic', 'lid', 'lie', 'lif', 'lig', 'lih', 'lii', 'lij', 'lik
', 'lil', 'lio', 'lip', 'liq', 'lir', 'lis', 'liu', 'liv', 'liw', 'lix', 'liy',
'liz', 'lja', 'lje', 'lji', 'ljl', 'ljp', 'ljw', 'ljx', 'lka', 'lkb', 'lkc', 'lk
d', 'lke', 'lkh', 'lki', 'lkj', 'lkl', 'lkm', 'lkn', 'lko', 'lkr', 'lks', 'lkt',
'lku', 'lky', 'lla', 'llb', 'llc', 'lld', 'lle', 'llf', 'llg', 'llh', 'lli', 'l
lj', 'llk', 'lll', 'llm', 'lln', 'llo', 'llp', 'llq', 'lls', 'llu', 'llx', 'lma'
, 'lmb', 'lmc', 'lmd', 'lme', 'lmf', 'lmg', 'lmh', 'lmi', 'lmj', 'lmk', 'lml', '
lmm', 'lmn', 'lmo', 'lmp', 'lmq', 'lmr', 'lmu', 'lmv', 'lmw', 'lmx', 'lmy', 'lmz
', 'lna', 'lnb', 'lnd', 'lng', 'lnh', 'lni', 'lnj', 'lnl', 'lnm', 'lnn', 'lno',
'lns', 'lnu', 'lnw', 'lnz', 'loa', 'lob', 'loc', 'loe', 'lof', 'log', 'loh', 'lo
i', 'loj', 'lok', 'lol', 'lom', 'lon', 'loo', 'lop', 'loq', 'lor', 'los', 'lot',
'lou', 'lov', 'low', 'lox', 'loy', 'loz', 'lpa', 'lpe', 'lpn', 'lpo', 'lpx', 'l
ra', 'lrc', 'lre', 'lrg', 'lri', 'lrk', 'lrl', 'lrm', 'lrn', 'lro', 'lrr', 'lrt'
, 'lrv', 'lrz', 'lsa', 'lsd', 'lse', 'lsg', 'lsh', 'lsi', 'lsl', 'lsm', 'lso', '
lsp', 'lsr', 'lss', 'lst', 'lsy', 'ltc', 'ltg', 'lth', 'lti', 'ltn', 'lto', 'lts
', 'ltu', 'lua', 'luc', 'lud', 'lue', 'luf', 'lui', 'luj', 'luk', 'lul', 'lum',
'lun', 'luo', 'lup', 'luq', 'lur', 'lus', 'lut', 'luu', 'luv', 'luw', 'luy', 'lu
z', 'lva', 'lvk', 'lvs', 'lvu', 'lwa', 'lwe', 'lwg', 'lwh', 'lwl', 'lwm', 'lwo',
'lwt', 'lwu', 'lww', 'lya', 'lyg', 'lyn', 'lzh', 'lzl', 'lzn', 'lzz', 'maa', 'm
ab', 'mad', 'mae', 'maf', 'mag', 'mai', 'maj', 'mak', 'mam', 'man', 'map', 'maq'
, 'mas', 'mat', 'mau', 'mav', 'maw', 'max', 'maz', 'mba', 'mbb', 'mbc', 'mbd', '
mbe', 'mbf', 'mbh', 'mbi', 'mbj', 'mbk', 'mbl', 'mbm', 'mbn', 'mbo', 'mbp', 'mbq
', 'mbr', 'mbs', 'mbt', 'mbu', 'mbv', 'mbw', 'mbx', 'mby', 'mbz', 'mca', 'mcb',
'mcc', 'mcd', 'mce', 'mcf', 'mcg', 'mch', 'mci', 'mcj', 'mck', 'mcl', 'mcm', 'mc
n', 'mco', 'mcp', 'mcq', 'mcr', 'mcs', 'mct', 'mcu', 'mcv', 'mcw', 'mcx', 'mcy',
'mcz', 'mda', 'mdb', 'mdc', 'mdd', 'mde', 'mdf', 'mdg', 'mdh', 'mdi', 'mdj', 'm
dk', 'mdl', 'mdm', 'mdn', 'mdp', 'mdq', 'mdr', 'mds', 'mdt', 'mdu', 'mdv', 'mdw'
, 'mdx', 'mdy', 'mdz', 'mea', 'meb', 'mec', 'med', 'mee', 'mef', 'meg', 'meh', '
mei', 'mej', 'mek', 'mel', 'mem', 'men', 'meo', 'mep', 'meq', 'mer', 'mes', 'met
', 'meu', 'mev', 'mew', 'mey', 'mez', 'mfa', 'mfb', 'mfc', 'mfd', 'mfe', 'mff',
'mfg', 'mfh', 'mfi', 'mfj', 'mfk', 'mfl', 'mfm', 'mfn', 'mfo', 'mfp', 'mfq', 'mf
r', 'mfs', 'mft', 'mfu', 'mfv', 'mfw', 'mfx', 'mfy', 'mfz', 'mga', 'mgb', 'mgc',
'mgd', 'mge', 'mgf', 'mgg', 'mgh', 'mgi', 'mgj', 'mgk', 'mgl', 'mgm', 'mgn', 'm
go', 'mgp', 'mgq', 'mgr', 'mgs', 'mgt', 'mgu', 'mgv', 'mgw', 'mgx', 'mgy', 'mgz'
, 'mha', 'mhb', 'mhc', 'mhd', 'mhe', 'mhf', 'mhg', 'mhh', 'mhi', 'mhj', 'mhk', '
mhl', 'mhm', 'mhn', 'mho', 'mhp', 'mhq', 'mhr', 'mhs', 'mht', 'mhu', 'mhw', 'mhx
', 'mhy', 'mhz', 'mia', 'mib', 'mic', 'mid', 'mie', 'mif', 'mig', 'mih', 'mii',
'mij', 'mik', 'mil', 'mim', 'min', 'mio', 'mip', 'miq', 'mir', 'mis', 'mit', 'mi
u', 'miw', 'mix', 'miy', 'miz', 'mja', 'mjb', 'mjc', 'mjd', 'mje', 'mjg', 'mjh',
'mji', 'mjj', 'mjk', 'mjl', 'mjm', 'mjn', 'mjo', 'mjp', 'mjq', 'mjr', 'mjs', 'm
jt', 'mju', 'mjv', 'mjw', 'mjx', 'mjy', 'mjz', 'mka', 'mkb', 'mkc', 'mke', 'mkf'
, 'mkg', 'mkh', 'mki', 'mkj', 'mkk', 'mkl', 'mkm', 'mkn', 'mko', 'mkp', 'mkq', '
mkr', 'mks', 'mkt', 'mku', 'mkv', 'mkw', 'mkx', 'mky', 'mkz', 'mla', 'mlb', 'mlc
', 'mld', 'mle', 'mlf', 'mlh', 'mli', 'mlj', 'mlk', 'mll', 'mlm', 'mln', 'mlo',
'mlp', 'mlq', 'mlr', 'mls', 'mlu', 'mlv', 'mlw', 'mlx', 'mlz', 'mma', 'mmb', 'mm
c', 'mmd', 'mme', 'mmf', 'mmg', 'mmh', 'mmi', 'mmj', 'mmk', 'mml', 'mmm', 'mmn',
'mmo', 'mmp', 'mmq', 'mmr', 'mmt', 'mmu', 'mmv', 'mmw', 'mmx', 'mmy', 'mmz', 'm
na', 'mnb', 'mnc', 'mnd', 'mne', 'mnf', 'mng', 'mnh', 'mni', 'mnj', 'mnk', 'mnl'
, 'mnm', 'mnn', 'mno', 'mnp', 'mnq', 'mnr', 'mns', 'mnt', 'mnu', 'mnv', 'mnw', '
mnx', 'mny', 'mnz', 'moa', 'moc', 'mod', 'moe', 'mof', 'mog', 'moh', 'moi', 'moj
', 'mok', 'mom', 'moo', 'mop', 'moq', 'mor', 'mos', 'mot', 'mou', 'mov', 'mow',
'mox', 'moy', 'moz', 'mpa', 'mpb', 'mpc', 'mpd', 'mpe', 'mpg', 'mph', 'mpi', 'mp
j', 'mpk', 'mpl', 'mpm', 'mpn', 'mpo', 'mpp', 'mpq', 'mpr', 'mps', 'mpt', 'mpu',
'mpv', 'mpw', 'mpx', 'mpy', 'mpz', 'mqa', 'mqb', 'mqc', 'mqe', 'mqf', 'mqg', 'm
qh', 'mqi', 'mqj', 'mqk', 'mql', 'mqm', 'mqn', 'mqo', 'mqp', 'mqq', 'mqr', 'mqs'
, 'mqt', 'mqu', 'mqv', 'mqw', 'mqx', 'mqy', 'mqz', 'mra', 'mrb', 'mrc', 'mrd', '
mre', 'mrf', 'mrg', 'mrh', 'mrj', 'mrk', 'mrl', 'mrm', 'mrn', 'mro', 'mrp', 'mrq
', 'mrr', 'mrs', 'mrt', 'mru', 'mrv', 'mrw', 'mrx', 'mry', 'mrz', 'msb', 'msc',
'msd', 'mse', 'msf', 'msg', 'msh', 'msi', 'msj', 'msk', 'msl', 'msm', 'msn', 'ms
o', 'msp', 'msq', 'msr', 'mss', 'mst', 'msu', 'msv', 'msw', 'msx', 'msy', 'msz',
'mta', 'mtb', 'mtc', 'mtd', 'mte', 'mtf', 'mtg', 'mth', 'mti', 'mtj', 'mtk', 'm
tl', 'mtm', 'mtn', 'mto', 'mtp', 'mtq', 'mtr', 'mts', 'mtt', 'mtu', 'mtv', 'mtw'
, 'mtx', 'mty', 'mua', 'mub', 'muc', 'mud', 'mue', 'mug', 'muh', 'mui', 'muj', '
muk', 'mul', 'mum', 'mun', 'muo', 'mup', 'muq', 'mur', 'mus', 'mut', 'muu', 'muv
', 'mux', 'muy', 'muz', 'mva', 'mvb', 'mvd', 'mve', 'mvf', 'mvg', 'mvh', 'mvi',
'mvk', 'mvl', 'mvm', 'mvn', 'mvo', 'mvp', 'mvq', 'mvr', 'mvs', 'mvt', 'mvu', 'mv
v', 'mvw', 'mvx', 'mvy', 'mvz', 'mwa', 'mwb', 'mwc', 'mwd', 'mwe', 'mwf', 'mwg',
'mwh', 'mwi', 'mwj', 'mwk', 'mwl', 'mwm', 'mwn', 'mwo', 'mwp', 'mwq', 'mwr', 'm
ws', 'mwt', 'mwu', 'mwv', 'mww', 'mwx', 'mwy', 'mwz', 'mxa', 'mxb', 'mxc', 'mxd'
, 'mxe', 'mxf', 'mxg', 'mxh', 'mxi', 'mxj', 'mxk', 'mxl', 'mxm', 'mxn', 'mxo', '
mxp', 'mxq', 'mxr', 'mxs', 'mxt', 'mxu', 'mxv', 'mxw', 'mxx', 'mxy', 'mxz', 'myb
', 'myc', 'myd', 'mye', 'myf', 'myg', 'myh', 'myi', 'myj', 'myk', 'myl', 'mym',
'myn', 'myo', 'myp', 'myq', 'myr', 'mys', 'myt', 'myu', 'myv', 'myw', 'myx', 'my
y', 'myz', 'mza', 'mzb', 'mzc', 'mzd', 'mze', 'mzg', 'mzh', 'mzi', 'mzj', 'mzk',
'mzl', 'mzm', 'mzn', 'mzo', 'mzp', 'mzq', 'mzr', 'mzs', 'mzt', 'mzu', 'mzv', 'm
zw', 'mzx', 'mzy', 'mzz', 'naa', 'nab', 'nac', 'nad', 'nae', 'naf', 'nag', 'nah'
, 'nai', 'naj', 'nak', 'nal', 'nam', 'nan', 'nao', 'nap', 'naq', 'nar', 'nas', '
nat', 'naw', 'nax', 'nay', 'naz', 'nba', 'nbb', 'nbc', 'nbd', 'nbe', 'nbf', 'nbg
', 'nbh', 'nbi', 'nbj', 'nbk', 'nbm', 'nbn', 'nbo', 'nbp', 'nbq', 'nbr', 'nbs',
'nbt', 'nbu', 'nbv', 'nbw', 'nbx', 'nby', 'nca', 'ncb', 'ncc', 'ncd', 'nce', 'nc
f', 'ncg', 'nch', 'nci', 'ncj', 'nck', 'ncl', 'ncm', 'ncn', 'nco', 'ncp', 'ncq',
'ncr', 'ncs', 'nct', 'ncu', 'ncx', 'ncz', 'nda', 'ndb', 'ndc', 'ndd', 'ndf', 'n
dg', 'ndh', 'ndi', 'ndj', 'ndk', 'ndl', 'ndm', 'ndn', 'ndp', 'ndq', 'ndr', 'nds'
, 'ndt', 'ndu', 'ndv', 'ndw', 'ndx', 'ndy', 'ndz', 'nea', 'neb', 'nec', 'ned', '
nee', 'nef', 'neg', 'neh', 'nei', 'nej', 'nek', 'nem', 'nen', 'neo', 'neq', 'ner
', 'nes', 'net', 'neu', 'nev', 'new', 'nex', 'ney', 'nez', 'nfa', 'nfd', 'nfl',
'nfr', 'nfu', 'nga', 'ngb', 'ngc', 'ngd', 'nge', 'ngf', 'ngg', 'ngh', 'ngi', 'ng
j', 'ngk', 'ngl', 'ngm', 'ngn', 'ngo', 'ngp', 'ngq', 'ngr', 'ngs', 'ngt', 'ngu',
'ngv', 'ngw', 'ngx', 'ngy', 'ngz', 'nha', 'nhb', 'nhc', 'nhd', 'nhe', 'nhf', 'n
hg', 'nhh', 'nhi', 'nhk', 'nhm', 'nhn', 'nho', 'nhp', 'nhq', 'nhr', 'nht', 'nhu'
, 'nhv', 'nhw', 'nhx', 'nhy', 'nhz', 'nia', 'nib', 'nic', 'nid', 'nie', 'nif', '
nig', 'nih', 'nii', 'nij', 'nik', 'nil', 'nim', 'nin', 'nio', 'niq', 'nir', 'nis
', 'nit', 'niu', 'niv', 'niw', 'nix', 'niy', 'niz', 'nja', 'njb', 'njd', 'njh',
'nji', 'njj', 'njl', 'njm', 'njn', 'njo', 'njr', 'njs', 'njt', 'nju', 'njx', 'nj
y', 'njz', 'nka', 'nkb', 'nkc', 'nkd', 'nke', 'nkf', 'nkg', 'nkh', 'nki', 'nkj',
'nkk', 'nkm', 'nkn', 'nko', 'nkp', 'nkq', 'nkr', 'nks', 'nkt', 'nku', 'nkv', 'n
kw', 'nkx', 'nkz', 'nla', 'nlc', 'nle', 'nlg', 'nli', 'nlj', 'nlk', 'nll', 'nln'
, 'nlo', 'nlq', 'nlr', 'nlu', 'nlv', 'nlw', 'nlx', 'nly', 'nlz', 'nma', 'nmb', '
nmc', 'nmd', 'nme', 'nmf', 'nmg', 'nmh', 'nmi', 'nmj', 'nmk', 'nml', 'nmm', 'nmn
', 'nmo', 'nmp', 'nmq', 'nmr', 'nms', 'nmt', 'nmu', 'nmv', 'nmw', 'nmx', 'nmy',
'nmz', 'nna', 'nnb', 'nnc', 'nnd', 'nne', 'nnf', 'nng', 'nnh', 'nni', 'nnj', 'nn
k', 'nnl', 'nnm', 'nnn', 'nnp', 'nnq', 'nnr', 'nns', 'nnt', 'nnu', 'nnv', 'nnw',
'nnx', 'nny', 'nnz', 'noa', 'noc', 'nod', 'noe', 'nof', 'nog', 'noh', 'noi', 'n
oj', 'nok', 'nol', 'nom', 'non', 'noo', 'nop', 'noq', 'nos', 'not', 'nou', 'nov'
, 'now', 'noy', 'noz', 'npa', 'npb', 'npg', 'nph', 'npi', 'npl', 'npn', 'npo', '
nps', 'npu', 'npx', 'npy', 'nqg', 'nqk', 'nql', 'nqm', 'nqn', 'nqo', 'nqq', 'nqy
', 'nra', 'nrb', 'nrc', 'nre', 'nrf', 'nrg', 'nri', 'nrk', 'nrl', 'nrm', 'nrn',
'nrp', 'nrr', 'nrt', 'nru', 'nrx', 'nrz', 'nsa', 'nsc', 'nsd', 'nse', 'nsf', 'ns
g', 'nsh', 'nsi', 'nsk', 'nsl', 'nsm', 'nsn', 'nso', 'nsp', 'nsq', 'nsr', 'nss',
'nst', 'nsu', 'nsv', 'nsw', 'nsx', 'nsy', 'nsz', 'ntd', 'nte', 'ntg', 'nti', 'n
tj', 'ntk', 'ntm', 'nto', 'ntp', 'ntr', 'nts', 'ntu', 'ntw', 'ntx', 'nty', 'ntz'
, 'nua', 'nub', 'nuc', 'nud', 'nue', 'nuf', 'nug', 'nuh', 'nui', 'nuj', 'nuk', '
nul', 'num', 'nun', 'nuo', 'nup', 'nuq', 'nur', 'nus', 'nut', 'nuu', 'nuv', 'nuw
', 'nux', 'nuy', 'nuz', 'nvh', 'nvm', 'nvo', 'nwa', 'nwb', 'nwc', 'nwe', 'nwg',
'nwi', 'nwm', 'nwo', 'nwr', 'nwx', 'nwy', 'nxa', 'nxd', 'nxe', 'nxg', 'nxi', 'nx
k', 'nxl', 'nxm', 'nxn', 'nxo', 'nxq', 'nxr', 'nxu', 'nxx', 'nyb', 'nyc', 'nyd',
'nye', 'nyf', 'nyg', 'nyh', 'nyi', 'nyj', 'nyk', 'nyl', 'nym', 'nyn', 'nyo', 'n
yp', 'nyq', 'nyr', 'nys', 'nyt', 'nyu', 'nyv', 'nyw', 'nyx', 'nyy', 'nza', 'nzb'
, 'nzi', 'nzk', 'nzm', 'nzs', 'nzu', 'nzy', 'nzz', 'oaa', 'oac', 'oar', 'oav', '
obi', 'obk', 'obl', 'obm', 'obo', 'obr', 'obt', 'obu', 'oca', 'och', 'oco', 'ocu
', 'oda', 'odk', 'odt', 'odu', 'ofo', 'ofs', 'ofu', 'ogb', 'ogc', 'oge', 'ogg',
'ogo', 'ogu', 'oht', 'ohu', 'oia', 'oin', 'ojb', 'ojc', 'ojg', 'ojp', 'ojs', 'oj
v', 'ojw', 'oka', 'okb', 'okd', 'oke', 'okg', 'okh', 'oki', 'okj', 'okk', 'okl',
'okm', 'okn', 'oko', 'okr', 'oks', 'oku', 'okv', 'okx', 'ola', 'old', 'ole', 'o
lk', 'olm', 'olo', 'olr', 'olt', 'olu', 'oma', 'omb', 'omc', 'ome', 'omg', 'omi'
, 'omk', 'oml', 'omn', 'omo', 'omp', 'omq', 'omr', 'omt', 'omu', 'omv', 'omw', '
omx', 'ona', 'onb', 'one', 'ong', 'oni', 'onj', 'onk', 'onn', 'ono', 'onp', 'onr
', 'ons', 'ont', 'onu', 'onw', 'onx', 'ood', 'oog', 'oon', 'oor', 'oos', 'opa',
'opk', 'opm', 'opo', 'opt', 'opy', 'ora', 'orc', 'ore', 'org', 'orh', 'orn', 'or
o', 'orr', 'ors', 'ort', 'oru', 'orv', 'orw', 'orx', 'ory', 'orz', 'osa', 'osc',
'osi', 'oso', 'osp', 'ost', 'osu', 'osx', 'ota', 'otb', 'otd', 'ote', 'oti', 'o
tk', 'otl', 'otm', 'otn', 'oto', 'otq', 'otr', 'ots', 'ott', 'otu', 'otw', 'otx'
, 'oty', 'otz', 'oua', 'oub', 'oue', 'oui', 'oum', 'oun', 'ovd', 'owi', 'owl', '
oyb', 'oyd', 'oym', 'oyy', 'ozm', 'paa', 'pab', 'pac', 'pad', 'pae', 'paf', 'pag
', 'pah', 'pai', 'pak', 'pal', 'pam', 'pao', 'pap', 'paq', 'par', 'pas', 'pat',
'pau', 'pav', 'paw', 'pax', 'pay', 'paz', 'pbb', 'pbc', 'pbe', 'pbf', 'pbg', 'pb
h', 'pbi', 'pbl', 'pbn', 'pbo', 'pbp', 'pbr', 'pbs', 'pbt', 'pbu', 'pbv', 'pby',
'pbz', 'pca', 'pcb', 'pcc', 'pcd', 'pce', 'pcf', 'pcg', 'pch', 'pci', 'pcj', 'p
ck', 'pcl', 'pcm', 'pcn', 'pcp', 'pcr', 'pcw', 'pda', 'pdc', 'pdi', 'pdn', 'pdo'
, 'pdt', 'pdu', 'pea', 'peb', 'ped', 'pee', 'pef', 'peg', 'peh', 'pei', 'pej', '
pek', 'pel', 'pem', 'peo', 'pep', 'peq', 'pes', 'pev', 'pex', 'pey', 'pez', 'pfa
', 'pfe', 'pfl', 'pga', 'pgd', 'pgg', 'pgi', 'pgk', 'pgl', 'pgn', 'pgs', 'pgu',
'pgy', 'pgz', 'pha', 'phd', 'phg', 'phh', 'phi', 'phk', 'phl', 'phm', 'phn', 'ph
o', 'phq', 'phr', 'pht', 'phu', 'phv', 'phw', 'pia', 'pib', 'pic', 'pid', 'pie',
'pif', 'pig', 'pih', 'pii', 'pij', 'pil', 'pim', 'pin', 'pio', 'pip', 'pir', 'p
is', 'pit', 'piu', 'piv', 'piw', 'pix', 'piy', 'piz', 'pjt', 'pka', 'pkb', 'pkc'
, 'pkg', 'pkh', 'pkn', 'pko', 'pkp', 'pkr', 'pks', 'pkt', 'pku', 'pla', 'plb', '
plc', 'pld', 'ple', 'plf', 'plg', 'plh', 'plj', 'plk', 'pll', 'pln', 'plo', 'plp
', 'plq', 'plr', 'pls', 'plt', 'plu', 'plv', 'plw', 'ply', 'plz', 'pma', 'pmb',
'pmc', 'pmd', 'pme', 'pmf', 'pmh', 'pmi', 'pmj', 'pmk', 'pml', 'pmm', 'pmn', 'pm
o', 'pmq', 'pmr', 'pms', 'pmt', 'pmu', 'pmw', 'pmx', 'pmy', 'pmz', 'pna', 'pnb',
'pnc', 'pne', 'png', 'pnh', 'pni', 'pnj', 'pnk', 'pnl', 'pnm', 'pnn', 'pno', 'p
np', 'pnq', 'pnr', 'pns', 'pnt', 'pnu', 'pnv', 'pnw', 'pnx', 'pny', 'pnz', 'poc'
, 'pod', 'poe', 'pof', 'pog', 'poh', 'poi', 'pok', 'pom', 'pon', 'poo', 'pop', '
poq', 'pos', 'pot', 'pov', 'pow', 'pox', 'poy', 'poz', 'ppa', 'ppe', 'ppi', 'ppk
', 'ppl', 'ppm', 'ppn', 'ppo', 'ppp', 'ppq', 'ppr', 'pps', 'ppt', 'ppu', 'pqa',
'pqe', 'pqm', 'pqw', 'pra', 'prb', 'prc', 'prd', 'pre', 'prf', 'prg', 'prh', 'pr
i', 'prk', 'prl', 'prm', 'prn', 'pro', 'prp', 'prq', 'prr', 'prs', 'prt', 'pru',
'prw', 'prx', 'pry', 'prz', 'psa', 'psc', 'psd', 'pse', 'psg', 'psh', 'psi', 'p
sl', 'psm', 'psn', 'pso', 'psp', 'psq', 'psr', 'pss', 'pst', 'psu', 'psw', 'psy'
, 'pta', 'pth', 'pti', 'ptn', 'pto', 'ptp', 'ptq', 'ptr', 'ptt', 'ptu', 'ptv', '
ptw', 'pty', 'pua', 'pub', 'puc', 'pud', 'pue', 'puf', 'pug', 'pui', 'puj', 'puk
', 'pum', 'puo', 'pup', 'puq', 'pur', 'put', 'puu', 'puw', 'pux', 'puy', 'puz',
'pwa', 'pwb', 'pwg', 'pwi', 'pwm', 'pwn', 'pwo', 'pwr', 'pww', 'pxm', 'pye', 'py
m', 'pyn', 'pys', 'pyu', 'pyx', 'pyy', 'pzn', 'qaa..qtz', 'qua', 'qub', 'quc', '
qud', 'quf', 'qug', 'quh', 'qui', 'quk', 'qul', 'qum', 'qun', 'qup', 'quq', 'qur
', 'qus', 'quv', 'quw', 'qux', 'quy', 'quz', 'qva', 'qvc', 'qve', 'qvh', 'qvi',
'qvj', 'qvl', 'qvm', 'qvn', 'qvo', 'qvp', 'qvs', 'qvw', 'qvy', 'qvz', 'qwa', 'qw
c', 'qwe', 'qwh', 'qwm', 'qws', 'qwt', 'qxa', 'qxc', 'qxh', 'qxl', 'qxn', 'qxo',
'qxp', 'qxq', 'qxr', 'qxs', 'qxt', 'qxu', 'qxw', 'qya', 'qyp', 'raa', 'rab', 'r
ac', 'rad', 'raf', 'rag', 'rah', 'rai', 'raj', 'rak', 'ral', 'ram', 'ran', 'rao'
, 'rap', 'raq', 'rar', 'ras', 'rat', 'rau', 'rav', 'raw', 'rax', 'ray', 'raz', '
rbb', 'rbk', 'rbl', 'rbp', 'rcf', 'rdb', 'rea', 'reb', 'ree', 'reg', 'rei', 'rej
', 'rel', 'rem', 'ren', 'rer', 'res', 'ret', 'rey', 'rga', 'rge', 'rgk', 'rgn',
'rgr', 'rgs', 'rgu', 'rhg', 'rhp', 'ria', 'rie', 'rif', 'ril', 'rim', 'rin', 'ri
r', 'rit', 'riu', 'rjg', 'rji', 'rjs', 'rka', 'rkb', 'rkh', 'rki', 'rkm', 'rkt',
'rkw', 'rma', 'rmb', 'rmc', 'rmd', 'rme', 'rmf', 'rmg', 'rmh', 'rmi', 'rmk', 'r
ml', 'rmm', 'rmn', 'rmo', 'rmp', 'rmq', 'rmr', 'rms', 'rmt', 'rmu', 'rmv', 'rmw'
, 'rmx', 'rmy', 'rmz', 'rna', 'rnd', 'rng', 'rnl', 'rnn', 'rnp', 'rnr', 'rnw', '
roa', 'rob', 'roc', 'rod', 'roe', 'rof', 'rog', 'rol', 'rom', 'roo', 'rop', 'ror
', 'rou', 'row', 'rpn', 'rpt', 'rri', 'rro', 'rrt', 'rsb', 'rsi', 'rsl', 'rsm',
'rtc', 'rth', 'rtm', 'rts', 'rtw', 'rub', 'ruc', 'rue', 'ruf', 'rug', 'ruh', 'ru
i', 'ruk', 'ruo', 'rup', 'ruq', 'rut', 'ruu', 'ruy', 'ruz', 'rwa', 'rwk', 'rwm',
'rwo', 'rwr', 'rxd', 'rxw', 'ryn', 'rys', 'ryu', 'rzh', 'saa', 'sab', 'sac', 's
ad', 'sae', 'saf', 'sah', 'sai', 'saj', 'sak', 'sal', 'sam', 'sao', 'sap', 'saq'
, 'sar', 'sas', 'sat', 'sau', 'sav', 'saw', 'sax', 'say', 'saz', 'sba', 'sbb', '
sbc', 'sbd', 'sbe', 'sbf', 'sbg', 'sbh', 'sbi', 'sbj', 'sbk', 'sbl', 'sbm', 'sbn
', 'sbo', 'sbp', 'sbq', 'sbr', 'sbs', 'sbt', 'sbu', 'sbv', 'sbw', 'sbx', 'sby',
'sbz', 'sca', 'scb', 'sce', 'scf', 'scg', 'sch', 'sci', 'sck', 'scl', 'scn', 'sc
o', 'scp', 'scq', 'scs', 'sct', 'scu', 'scv', 'scw', 'scx', 'sda', 'sdb', 'sdc',
'sde', 'sdf', 'sdg', 'sdh', 'sdj', 'sdk', 'sdl', 'sdm', 'sdn', 'sdo', 'sdp', 's
dr', 'sds', 'sdt', 'sdu', 'sdv', 'sdx', 'sdz', 'sea', 'seb', 'sec', 'sed', 'see'
, 'sef', 'seg', 'seh', 'sei', 'sej', 'sek', 'sel', 'sem', 'sen', 'seo', 'sep', '
seq', 'ser', 'ses', 'set', 'seu', 'sev', 'sew', 'sey', 'sez', 'sfb', 'sfe', 'sfm
', 'sfs', 'sfw', 'sga', 'sgb', 'sgc', 'sgd', 'sge', 'sgg', 'sgh', 'sgi', 'sgj',
'sgk', 'sgl', 'sgm', 'sgn', 'sgo', 'sgp', 'sgr', 'sgs', 'sgt', 'sgu', 'sgw', 'sg
x', 'sgy', 'sgz', 'sha', 'shb', 'shc', 'shd', 'she', 'shg', 'shh', 'shi', 'shj',
'shk', 'shl', 'shm', 'shn', 'sho', 'shp', 'shq', 'shr', 'shs', 'sht', 'shu', 's
hv', 'shw', 'shx', 'shy', 'shz', 'sia', 'sib', 'sid', 'sie', 'sif', 'sig', 'sih'
, 'sii', 'sij', 'sik', 'sil', 'sim', 'sio', 'sip', 'siq', 'sir', 'sis', 'sit', '
siu', 'siv', 'siw', 'six', 'siy', 'siz', 'sja', 'sjb', 'sjd', 'sje', 'sjg', 'sjk
', 'sjl', 'sjm', 'sjn', 'sjo', 'sjp', 'sjr', 'sjs', 'sjt', 'sju', 'sjw', 'ska',
'skb', 'skc', 'skd', 'ske', 'skf', 'skg', 'skh', 'ski', 'skj', 'skk', 'skm', 'sk
n', 'sko', 'skp', 'skq', 'skr', 'sks', 'skt', 'sku', 'skv', 'skw', 'skx', 'sky',
'skz', 'sla', 'slc', 'sld', 'sle', 'slf', 'slg', 'slh', 'sli', 'slj', 'sll', 's
lm', 'sln', 'slp', 'slq', 'slr', 'sls', 'slt', 'slu', 'slw', 'slx', 'sly', 'slz'
, 'sma', 'smb', 'smc', 'smd', 'smf', 'smg', 'smh', 'smi', 'smj', 'smk', 'sml', '
smm', 'smn', 'smp', 'smq', 'smr', 'sms', 'smt', 'smu', 'smv', 'smw', 'smx', 'smy
', 'smz', 'snb', 'snc', 'sne', 'snf', 'sng', 'snh', 'sni', 'snj', 'snk', 'snl',
'snm', 'snn', 'sno', 'snp', 'snq', 'snr', 'sns', 'snu', 'snv', 'snw', 'snx', 'sn
y', 'snz', 'soa', 'sob', 'soc', 'sod', 'soe', 'sog', 'soh', 'soi', 'soj', 'sok',
'sol', 'son', 'soo', 'sop', 'soq', 'sor', 'sos', 'sou', 'sov', 'sow', 'sox', 's
oy', 'soz', 'spb', 'spc', 'spd', 'spe', 'spg', 'spi', 'spk', 'spl', 'spm', 'spn'
, 'spo', 'spp', 'spq', 'spr', 'sps', 'spt', 'spu', 'spv', 'spx', 'spy', 'sqa', '
sqh', 'sqj', 'sqk', 'sqm', 'sqn', 'sqo', 'sqq', 'sqr', 'sqs', 'sqt', 'squ', 'sra
', 'srb', 'src', 'sre', 'srf', 'srg', 'srh', 'sri', 'srk', 'srl', 'srm', 'srn',
'sro', 'srq', 'srr', 'srs', 'srt', 'sru', 'srv', 'srw', 'srx', 'sry', 'srz', 'ss
a', 'ssb', 'ssc', 'ssd', 'sse', 'ssf', 'ssg', 'ssh', 'ssi', 'ssj', 'ssk', 'ssl',
'ssm', 'ssn', 'sso', 'ssp', 'ssq', 'ssr', 'sss', 'sst', 'ssu', 'ssv', 'ssx', 's
sy', 'ssz', 'sta', 'stb', 'std', 'ste', 'stf', 'stg', 'sth', 'sti', 'stj', 'stk'
, 'stl', 'stm', 'stn', 'sto', 'stp', 'stq', 'str', 'sts', 'stt', 'stu', 'stv', '
stw', 'sty', 'sua', 'sub', 'suc', 'sue', 'sug', 'sui', 'suj', 'suk', 'sul', 'sum
', 'suq', 'sur', 'sus', 'sut', 'suv', 'suw', 'sux', 'suy', 'suz', 'sva', 'svb',
'svc', 'sve', 'svk', 'svm', 'svr', 'svs', 'svx', 'swb', 'swc', 'swf', 'swg', 'sw
h', 'swi', 'swj', 'swk', 'swl', 'swm', 'swn', 'swo', 'swp', 'swq', 'swr', 'sws',
'swt', 'swu', 'swv', 'sww', 'swx', 'swy', 'sxb', 'sxc', 'sxe', 'sxg', 'sxk', 's
xl', 'sxm', 'sxn', 'sxo', 'sxr', 'sxs', 'sxu', 'sxw', 'sya', 'syb', 'syc', 'syd'
, 'syi', 'syk', 'syl', 'sym', 'syn', 'syo', 'syr', 'sys', 'syw', 'syx', 'syy', '
sza', 'szb', 'szc', 'szd', 'sze', 'szg', 'szl', 'szn', 'szp', 'szs', 'szv', 'szw
', 'taa', 'tab', 'tac', 'tad', 'tae', 'taf', 'tag', 'tai', 'taj', 'tak', 'tal',
'tan', 'tao', 'tap', 'taq', 'tar', 'tas', 'tau', 'tav', 'taw', 'tax', 'tay', 'ta
z', 'tba', 'tbb', 'tbc', 'tbd', 'tbe', 'tbf', 'tbg', 'tbh', 'tbi', 'tbj', 'tbk',
'tbl', 'tbm', 'tbn', 'tbo', 'tbp', 'tbq', 'tbr', 'tbs', 'tbt', 'tbu', 'tbv', 't
bw', 'tbx', 'tby', 'tbz', 'tca', 'tcb', 'tcc', 'tcd', 'tce', 'tcf', 'tcg', 'tch'
, 'tci', 'tck', 'tcl', 'tcm', 'tcn', 'tco', 'tcp', 'tcq', 'tcs', 'tct', 'tcu', '
tcw', 'tcx', 'tcy', 'tcz', 'tda', 'tdb', 'tdc', 'tdd', 'tde', 'tdf', 'tdg', 'tdh
', 'tdi', 'tdj', 'tdk', 'tdl', 'tdm', 'tdn', 'tdo', 'tdq', 'tdr', 'tds', 'tdt',
'tdu', 'tdv', 'tdx', 'tdy', 'tea', 'teb', 'tec', 'ted', 'tee', 'tef', 'teg', 'te
h', 'tei', 'tek', 'tem', 'ten', 'teo', 'tep', 'teq', 'ter', 'tes', 'tet', 'teu',
'tev', 'tew', 'tex', 'tey', 'tfi', 'tfn', 'tfo', 'tfr', 'tft', 'tga', 'tgb', 't
gc', 'tgd', 'tge', 'tgf', 'tgg', 'tgh', 'tgi', 'tgj', 'tgn', 'tgo', 'tgp', 'tgq'
, 'tgr', 'tgs', 'tgt', 'tgu', 'tgv', 'tgw', 'tgx', 'tgy', 'tgz', 'thc', 'thd', '
the', 'thf', 'thh', 'thi', 'thk', 'thl', 'thm', 'thn', 'thp', 'thq', 'thr', 'ths
', 'tht', 'thu', 'thv', 'thw', 'thx', 'thy', 'thz', 'tia', 'tic', 'tid', 'tie',
'tif', 'tig', 'tih', 'tii', 'tij', 'tik', 'til', 'tim', 'tin', 'tio', 'tip', 'ti
q', 'tis', 'tit', 'tiu', 'tiv', 'tiw', 'tix', 'tiy', 'tiz', 'tja', 'tjg', 'tji',
'tjl', 'tjm', 'tjn', 'tjo', 'tjs', 'tju', 'tjw', 'tka', 'tkb', 'tkd', 'tke', 't
kf', 'tkg', 'tkk', 'tkl', 'tkm', 'tkn', 'tkp', 'tkq', 'tkr', 'tks', 'tkt', 'tku'
, 'tkv', 'tkw', 'tkx', 'tkz', 'tla', 'tlb', 'tlc', 'tld', 'tlf', 'tlg', 'tlh', '
tli', 'tlj', 'tlk', 'tll', 'tlm', 'tln', 'tlo', 'tlp', 'tlq', 'tlr', 'tls', 'tlt
', 'tlu', 'tlv', 'tlw', 'tlx', 'tly', 'tma', 'tmb', 'tmc', 'tmd', 'tme', 'tmf',
'tmg', 'tmh', 'tmi', 'tmj', 'tmk', 'tml', 'tmm', 'tmn', 'tmo', 'tmp', 'tmq', 'tm
r', 'tms', 'tmt', 'tmu', 'tmv', 'tmw', 'tmy', 'tmz', 'tna', 'tnb', 'tnc', 'tnd',
'tne', 'tnf', 'tng', 'tnh', 'tni', 'tnk', 'tnl', 'tnm', 'tnn', 'tno', 'tnp', 't
nq', 'tnr', 'tns', 'tnt', 'tnu', 'tnv', 'tnw', 'tnx', 'tny', 'tnz', 'tob', 'toc'
, 'tod', 'toe', 'tof', 'tog', 'toh', 'toi', 'toj', 'tol', 'tom', 'too', 'top', '
toq', 'tor', 'tos', 'tou', 'tov', 'tow', 'tox', 'toy', 'toz', 'tpa', 'tpc', 'tpe
', 'tpf', 'tpg', 'tpi', 'tpj', 'tpk', 'tpl', 'tpm', 'tpn', 'tpo', 'tpp', 'tpq',
'tpr', 'tpt', 'tpu', 'tpv', 'tpw', 'tpx', 'tpy', 'tpz', 'tqb', 'tql', 'tqm', 'tq
n', 'tqo', 'tqp', 'tqq', 'tqr', 'tqt', 'tqu', 'tqw', 'tra', 'trb', 'trc', 'trd',
'tre', 'trf', 'trg', 'trh', 'tri', 'trj', 'trk', 'trl', 'trm', 'trn', 'tro', 't
rp', 'trq', 'trr', 'trs', 'trt', 'tru', 'trv', 'trw', 'trx', 'try', 'trz', 'tsa'
, 'tsb', 'tsc', 'tsd', 'tse', 'tsf', 'tsg', 'tsh', 'tsi', 'tsj', 'tsk', 'tsl', '
tsm', 'tsp', 'tsq', 'tsr', 'tss', 'tst', 'tsu', 'tsv', 'tsw', 'tsx', 'tsy', 'tsz
', 'tta', 'ttb', 'ttc', 'ttd', 'tte', 'ttf', 'ttg', 'tth', 'tti', 'ttj', 'ttk',
'ttl', 'ttm', 'ttn', 'tto', 'ttp', 'ttq', 'ttr', 'tts', 'ttt', 'ttu', 'ttv', 'tt
w', 'tty', 'ttz', 'tua', 'tub', 'tuc', 'tud', 'tue', 'tuf', 'tug', 'tuh', 'tui',
'tuj', 'tul', 'tum', 'tun', 'tuo', 'tup', 'tuq', 'tus', 'tut', 'tuu', 'tuv', 't
uw', 'tux', 'tuy', 'tuz', 'tva', 'tvd', 'tve', 'tvk', 'tvl', 'tvm', 'tvn', 'tvo'
, 'tvs', 'tvt', 'tvu', 'tvw', 'tvy', 'twa', 'twb', 'twc', 'twd', 'twe', 'twf', '
twg', 'twh', 'twl', 'twm', 'twn', 'two', 'twp', 'twq', 'twr', 'twt', 'twu', 'tww
', 'twx', 'twy', 'txa', 'txb', 'txc', 'txe', 'txg', 'txh', 'txi', 'txj', 'txm',
'txn', 'txo', 'txq', 'txr', 'txs', 'txt', 'txu', 'txx', 'txy', 'tya', 'tye', 'ty
h', 'tyi', 'tyj', 'tyl', 'tyn', 'typ', 'tyr', 'tys', 'tyt', 'tyu', 'tyv', 'tyx',
'tyz', 'tza', 'tzh', 'tzj', 'tzl', 'tzm', 'tzn', 'tzo', 'tzx', 'uam', 'uan', 'u
ar', 'uba', 'ubi', 'ubl', 'ubr', 'ubu', 'uby', 'uda', 'ude', 'udg', 'udi', 'udj'
, 'udl', 'udm', 'udu', 'ues', 'ufi', 'uga', 'ugb', 'uge', 'ugn', 'ugo', 'ugy', '
uha', 'uhn', 'uis', 'uiv', 'uji', 'uka', 'ukg', 'ukh', 'ukk', 'ukl', 'ukp', 'ukq
', 'uks', 'uku', 'ukw', 'uky', 'ula', 'ulb', 'ulc', 'ule', 'ulf', 'uli', 'ulk',
'ull', 'ulm', 'uln', 'ulu', 'ulw', 'uma', 'umb', 'umc', 'umd', 'umg', 'umi', 'um
m', 'umn', 'umo', 'ump', 'umr', 'ums', 'umu', 'una', 'und', 'une', 'ung', 'unk',
'unm', 'unn', 'unp', 'unr', 'unu', 'unx', 'unz', 'uok', 'upi', 'upv', 'ura', 'u
rb', 'urc', 'ure', 'urf', 'urg', 'urh', 'uri', 'urj', 'urk', 'url', 'urm', 'urn'
, 'uro', 'urp', 'urr', 'urt', 'uru', 'urv', 'urw', 'urx', 'ury', 'urz', 'usa', '
ush', 'usi', 'usk', 'usp', 'usu', 'uta', 'ute', 'utp', 'utr', 'utu', 'uum', 'uun
', 'uur', 'uuu', 'uve', 'uvh', 'uvl', 'uwa', 'uya', 'uzn', 'uzs', 'vaa', 'vae',
'vaf', 'vag', 'vah', 'vai', 'vaj', 'val', 'vam', 'van', 'vao', 'vap', 'var', 'va
s', 'vau', 'vav', 'vay', 'vbb', 'vbk', 'vec', 'ved', 'vel', 'vem', 'veo', 'vep',
'ver', 'vgr', 'vgt', 'vic', 'vid', 'vif', 'vig', 'vil', 'vin', 'vis', 'vit', 'v
iv', 'vka', 'vki', 'vkj', 'vkk', 'vkl', 'vkm', 'vko', 'vkp', 'vkt', 'vku', 'vlp'
, 'vls', 'vma', 'vmb', 'vmc', 'vmd', 'vme', 'vmf', 'vmg', 'vmh', 'vmi', 'vmj', '
vmk', 'vml', 'vmm', 'vmp', 'vmq', 'vmr', 'vms', 'vmu', 'vmv', 'vmw', 'vmx', 'vmy
', 'vmz', 'vnk', 'vnm', 'vnp', 'vor', 'vot', 'vra', 'vro', 'vrs', 'vrt', 'vsi',
'vsl', 'vsv', 'vto', 'vum', 'vun', 'vut', 'vwa', 'waa', 'wab', 'wac', 'wad', 'wa
e', 'waf', 'wag', 'wah', 'wai', 'waj', 'wak', 'wal', 'wam', 'wan', 'wao', 'wap',
'waq', 'war', 'was', 'wat', 'wau', 'wav', 'waw', 'wax', 'way', 'waz', 'wba', 'w
bb', 'wbe', 'wbf', 'wbh', 'wbi', 'wbj', 'wbk', 'wbl', 'wbm', 'wbp', 'wbq', 'wbr'
, 'wbs', 'wbt', 'wbv', 'wbw', 'wca', 'wci', 'wdd', 'wdg', 'wdj', 'wdk', 'wdu', '
wdy', 'wea', 'wec', 'wed', 'weg', 'weh', 'wei', 'wem', 'wen', 'weo', 'wep', 'wer
', 'wes', 'wet', 'weu', 'wew', 'wfg', 'wga', 'wgb', 'wgg', 'wgi', 'wgo', 'wgu',
'wgw', 'wgy', 'wha', 'whg', 'whk', 'whu', 'wib', 'wic', 'wie', 'wif', 'wig', 'wi
h', 'wii', 'wij', 'wik', 'wil', 'wim', 'win', 'wir', 'wit', 'wiu', 'wiv', 'wiw',
'wiy', 'wja', 'wji', 'wka', 'wkb', 'wkd', 'wkl', 'wku', 'wkw', 'wky', 'wla', 'w
lc', 'wle', 'wlg', 'wli', 'wlk', 'wll', 'wlm', 'wlo', 'wlr', 'wls', 'wlu', 'wlv'
, 'wlw', 'wlx', 'wly', 'wma', 'wmb', 'wmc', 'wmd', 'wme', 'wmh', 'wmi', 'wmm', '
wmn', 'wmo', 'wms', 'wmt', 'wmw', 'wmx', 'wnb', 'wnc', 'wnd', 'wne', 'wng', 'wni
', 'wnk', 'wnm', 'wnn', 'wno', 'wnp', 'wnu', 'wnw', 'wny', 'woa', 'wob', 'woc',
'wod', 'woe', 'wof', 'wog', 'woi', 'wok', 'wom', 'won', 'woo', 'wor', 'wos', 'wo
w', 'woy', 'wpc', 'wra', 'wrb', 'wrd', 'wrg', 'wrh', 'wri', 'wrk', 'wrl', 'wrm',
'wrn', 'wro', 'wrp', 'wrr', 'wrs', 'wru', 'wrv', 'wrw', 'wrx', 'wry', 'wrz', 'w
sa', 'wsg', 'wsi', 'wsk', 'wsr', 'wss', 'wsu', 'wsv', 'wtf', 'wth', 'wti', 'wtk'
, 'wtm', 'wtw', 'wua', 'wub', 'wud', 'wuh', 'wul', 'wum', 'wun', 'wur', 'wut', '
wuu', 'wuv', 'wux', 'wuy', 'wwa', 'wwb', 'wwo', 'wwr', 'www', 'wxa', 'wxw', 'wya
', 'wyb', 'wyi', 'wym', 'wyr', 'wyy', 'xaa', 'xab', 'xac', 'xad', 'xae', 'xag',
'xai', 'xaj', 'xak', 'xal', 'xam', 'xan', 'xao', 'xap', 'xaq', 'xar', 'xas', 'xa
t', 'xau', 'xav', 'xaw', 'xay', 'xba', 'xbb', 'xbc', 'xbd', 'xbe', 'xbg', 'xbi',
'xbj', 'xbm', 'xbn', 'xbo', 'xbp', 'xbr', 'xbw', 'xbx', 'xby', 'xcb', 'xcc', 'x
ce', 'xcg', 'xch', 'xcl', 'xcm', 'xcn', 'xco', 'xcr', 'xct', 'xcu', 'xcv', 'xcw'
, 'xcy', 'xda', 'xdc', 'xdk', 'xdm', 'xdo', 'xdy', 'xeb', 'xed', 'xeg', 'xel', '
xem', 'xep', 'xer', 'xes', 'xet', 'xeu', 'xfa', 'xga', 'xgb', 'xgd', 'xgf', 'xgg
', 'xgi', 'xgl', 'xgm', 'xgn', 'xgr', 'xgu', 'xgw', 'xha', 'xhc', 'xhd', 'xhe',
'xhr', 'xht', 'xhu', 'xhv', 'xia', 'xib', 'xii', 'xil', 'xin', 'xip', 'xir', 'xi
s', 'xiv', 'xiy', 'xjb', 'xjt', 'xka', 'xkb', 'xkc', 'xkd', 'xke', 'xkf', 'xkg',
'xkh', 'xki', 'xkj', 'xkk', 'xkl', 'xkn', 'xko', 'xkp', 'xkq', 'xkr', 'xks', 'x
kt', 'xku', 'xkv', 'xkw', 'xkx', 'xky', 'xkz', 'xla', 'xlb', 'xlc', 'xld', 'xle'
, 'xlg', 'xli', 'xln', 'xlo', 'xlp', 'xls', 'xlu', 'xly', 'xma', 'xmb', 'xmc', '
xmd', 'xme', 'xmf', 'xmg', 'xmh', 'xmj', 'xmk', 'xml', 'xmm', 'xmn', 'xmo', 'xmp
', 'xmq', 'xmr', 'xms', 'xmt', 'xmu', 'xmv', 'xmw', 'xmx', 'xmy', 'xmz', 'xna',
'xnb', 'xnd', 'xng', 'xnh', 'xni', 'xnk', 'xnn', 'xno', 'xnr', 'xns', 'xnt', 'xn
u', 'xny', 'xnz', 'xoc', 'xod', 'xog', 'xoi', 'xok', 'xom', 'xon', 'xoo', 'xop',
'xor', 'xow', 'xpa', 'xpc', 'xpe', 'xpg', 'xpi', 'xpj', 'xpk', 'xpm', 'xpn', 'x
po', 'xpp', 'xpq', 'xpr', 'xps', 'xpt', 'xpu', 'xpy', 'xqa', 'xqt', 'xra', 'xrb'
, 'xrd', 'xre', 'xrg', 'xri', 'xrm', 'xrn', 'xrq', 'xrr', 'xrt', 'xru', 'xrw', '
xsa', 'xsb', 'xsc', 'xsd', 'xse', 'xsh', 'xsi', 'xsj', 'xsl', 'xsm', 'xsn', 'xso
', 'xsp', 'xsq', 'xsr', 'xss', 'xsu', 'xsv', 'xsy', 'xta', 'xtb', 'xtc', 'xtd',
'xte', 'xtg', 'xth', 'xti', 'xtj', 'xtl', 'xtm', 'xtn', 'xto', 'xtp', 'xtq', 'xt
r', 'xts', 'xtt', 'xtu', 'xtv', 'xtw', 'xty', 'xtz', 'xua', 'xub', 'xud', 'xug',
'xuj', 'xul', 'xum', 'xun', 'xuo', 'xup', 'xur', 'xut', 'xuu', 'xve', 'xvi', 'x
vn', 'xvo', 'xvs', 'xwa', 'xwc', 'xwd', 'xwe', 'xwg', 'xwj', 'xwk', 'xwl', 'xwo'
, 'xwr', 'xwt', 'xww', 'xxb', 'xxk', 'xxm', 'xxr', 'xxt', 'xya', 'xyb', 'xyj', '
xyk', 'xyl', 'xyt', 'xyy', 'xzh', 'xzm', 'xzp', 'yaa', 'yab', 'yac', 'yad', 'yae
', 'yaf', 'yag', 'yah', 'yai', 'yaj', 'yak', 'yal', 'yam', 'yan', 'yao', 'yap',
'yaq', 'yar', 'yas', 'yat', 'yau', 'yav', 'yaw', 'yax', 'yay', 'yaz', 'yba', 'yb
b', 'ybd', 'ybe', 'ybh', 'ybi', 'ybj', 'ybk', 'ybl', 'ybm', 'ybn', 'ybo', 'ybx',
'yby', 'ych', 'ycl', 'ycn', 'ycp', 'yda', 'ydd', 'yde', 'ydg', 'ydk', 'yds', 'y
ea', 'yec', 'yee', 'yei', 'yej', 'yel', 'yen', 'yer', 'yes', 'yet', 'yeu', 'yev'
, 'yey', 'yga', 'ygi', 'ygl', 'ygm', 'ygp', 'ygr', 'ygs', 'ygu', 'ygw', 'yha', '
yhd', 'yhl', 'yhs', 'yia', 'yif', 'yig', 'yih', 'yii', 'yij', 'yik', 'yil', 'yim
', 'yin', 'yip', 'yiq', 'yir', 'yis', 'yit', 'yiu', 'yiv', 'yix', 'yiy', 'yiz',
'yka', 'ykg', 'yki', 'ykk', 'ykl', 'ykm', 'ykn', 'yko', 'ykr', 'ykt', 'yku', 'yk
y', 'yla', 'ylb', 'yle', 'ylg', 'yli', 'yll', 'ylm', 'yln', 'ylo', 'ylr', 'ylu',
'yly', 'yma', 'ymb', 'ymc', 'ymd', 'yme', 'ymg', 'ymh', 'ymi', 'ymk', 'yml', 'y
mm', 'ymn', 'ymo', 'ymp', 'ymq', 'ymr', 'yms', 'ymt', 'ymx', 'ymz', 'yna', 'ynd'
, 'yne', 'yng', 'ynh', 'ynk', 'ynl', 'ynn', 'yno', 'ynq', 'yns', 'ynu', 'yob', '
yog', 'yoi', 'yok', 'yol', 'yom', 'yon', 'yos', 'yot', 'yox', 'yoy', 'ypa', 'ypb
', 'ypg', 'yph', 'ypk', 'ypm', 'ypn', 'ypo', 'ypp', 'ypz', 'yra', 'yrb', 'yre',
'yri', 'yrk', 'yrl', 'yrm', 'yrn', 'yro', 'yrs', 'yrw', 'yry', 'ysc', 'ysd', 'ys
g', 'ysl', 'ysn', 'yso', 'ysp', 'ysr', 'yss', 'ysy', 'yta', 'ytl', 'ytp', 'ytw',
'yty', 'yua', 'yub', 'yuc', 'yud', 'yue', 'yuf', 'yug', 'yui', 'yuj', 'yuk', 'y
ul', 'yum', 'yun', 'yup', 'yuq', 'yur', 'yut', 'yuu', 'yuw', 'yux', 'yuy', 'yuz'
, 'yva', 'yvt', 'ywa', 'ywg', 'ywl', 'ywn', 'ywq', 'ywr', 'ywt', 'ywu', 'yww', '
yxa', 'yxg', 'yxl', 'yxm', 'yxu', 'yxy', 'yyr', 'yyu', 'yyz', 'yzg', 'yzk', 'zaa
', 'zab', 'zac', 'zad', 'zae', 'zaf', 'zag', 'zah', 'zai', 'zaj', 'zak', 'zal',
'zam', 'zao', 'zap', 'zaq', 'zar', 'zas', 'zat', 'zau', 'zav', 'zaw', 'zax', 'za
y', 'zaz', 'zbc', 'zbe', 'zbl', 'zbt', 'zbw', 'zca', 'zch', 'zdj', 'zea', 'zeg',
'zeh', 'zen', 'zga', 'zgb', 'zgh', 'zgm', 'zgn', 'zgr', 'zhb', 'zhd', 'zhi', 'z
hn', 'zhw', 'zhx', 'zia', 'zib', 'zik', 'zil', 'zim', 'zin', 'zir', 'ziw', 'ziz'
, 'zka', 'zkb', 'zkd', 'zkg', 'zkh', 'zkk', 'zkn', 'zko', 'zkp', 'zkr', 'zkt', '
zku', 'zkv', 'zkz', 'zle', 'zlj', 'zlm', 'zln', 'zlq', 'zls', 'zlw', 'zma', 'zmb
', 'zmc', 'zmd', 'zme', 'zmf', 'zmg', 'zmh', 'zmi', 'zmj', 'zmk', 'zml', 'zmm',
'zmn', 'zmo', 'zmp', 'zmq', 'zmr', 'zms', 'zmt', 'zmu', 'zmv', 'zmw', 'zmx', 'zm
y', 'zmz', 'zna', 'znd', 'zne', 'zng', 'znk', 'zns', 'zoc', 'zoh', 'zom', 'zoo',
'zoq', 'zor', 'zos', 'zpa', 'zpb', 'zpc', 'zpd', 'zpe', 'zpf', 'zpg', 'zph', 'z
pi', 'zpj', 'zpk', 'zpl', 'zpm', 'zpn', 'zpo', 'zpp', 'zpq', 'zpr', 'zps', 'zpt'
, 'zpu', 'zpv', 'zpw', 'zpx', 'zpy', 'zpz', 'zqe', 'zra', 'zrg', 'zrn', 'zro', '
zrp', 'zrs', 'zsa', 'zsk', 'zsl', 'zsm', 'zsr', 'zsu', 'zte', 'ztg', 'ztl', 'ztm
', 'ztn', 'ztp', 'ztq', 'zts', 'ztt', 'ztu', 'ztx', 'zty', 'zua', 'zuh', 'zum',
'zun', 'zuy', 'zwa', 'zxx', 'zyb', 'zyg', 'zyj', 'zyn', 'zyp', 'zza', 'zzj' ]; |
| 9447 axe.utils.validLangs = function() { |
| 9448 'use strict'; |
| 9449 return langs; |
| 9450 }; |
| 9451 return commons; |
| 9452 }() |
| 9453 }); |
| 9454 })(typeof window === 'object' ? window : this); |
OLD | NEW |