From 2adea2fb32314dc2b9489b9908bcc9849f1589e7 Mon Sep 17 00:00:00 2001 From: j-mendez Date: Thu, 4 May 2023 10:04:23 -0400 Subject: [PATCH] perf(htmlcs): improve heading order detection --- README.md | 2 +- a11y-js/lib/runner.ts | 8 +- a11y-js/package.json | 2 +- fast_htmlcs/HTMLCS.Util.ts | 2 +- .../Sniffs/Principle1/Guideline1_2/1_2_4.ts | 2 +- .../Sniffs/Principle1/Guideline1_3/1_3_1.ts | 188 ++++++++---------- .../Guideline1_3/{1_3_2.js => 1_3_2.ts} | 6 +- .../Guideline1_3/{1_3_3.js => 1_3_3.ts} | 6 +- .../Guideline1_3/{1_3_4.js => 1_3_4.ts} | 6 +- .../Guideline1_3/{1_3_5.js => 1_3_5.ts} | 52 +++-- .../Guideline1_3/{1_3_6.js => 1_3_6.ts} | 6 +- .../Guideline1_4/{1_4_1.js => 1_4_1.ts} | 6 +- .../Guideline1_4/{1_4_2.js => 1_4_2.ts} | 6 +- fast_htmlcs/globals.d.ts | 9 + fast_htmlcs/package.json | 2 +- .../@axe-core_playwright.json | 2 +- .../@axe-core_playwright_stats.json | 2 +- .../axe-core.json | 66 +++--- .../axe-core_stats.json | 2 +- .../pa11y_htmlcs_stats.json | 2 +- .../htmlcs.json | 26 +-- .../htmlcs_stats.json | 2 +- 22 files changed, 193 insertions(+), 212 deletions(-) rename fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_3/{1_3_2.js => 1_3_2.ts} (93%) rename fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_3/{1_3_3.js => 1_3_3.ts} (93%) rename fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_3/{1_3_4.js => 1_3_4.ts} (93%) rename fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_3/{1_3_5.js => 1_3_5.ts} (92%) rename fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_3/{1_3_6.js => 1_3_6.ts} (93%) rename fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_4/{1_4_1.js => 1_4_1.ts} (93%) rename fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_4/{1_4_2.js => 1_4_2.ts} (90%) diff --git a/README.md b/README.md index bd8bf266..db2807f6 100644 --- a/README.md +++ b/README.md @@ -188,7 +188,7 @@ complete. The performance increases we made to the project were not only done at make the ability of auditing at the MS level for almost any website. Right now, the project is moving forward based on performance and accuracy for ensuring minimal to no false positives. -## Next Level +## Teleportation like Speeds As we set the foundation to mark test cases that can pass and increase our target on automating accessibility we have a couple of layers that can make a major difference to the project. The following will save drastic time and money if done. diff --git a/a11y-js/lib/runner.ts b/a11y-js/lib/runner.ts index a9a342a5..6688b530 100644 --- a/a11y-js/lib/runner.ts +++ b/a11y-js/lib/runner.ts @@ -43,7 +43,7 @@ }; // Truncate the html. - const getElementContext = (element) => { + const getElementContext = (element: Element) => { let outerHTML = element.outerHTML; if (!outerHTML) { @@ -53,19 +53,19 @@ if (element.innerHTML.length > 31) { outerHTML = outerHTML.replace( element.innerHTML, - `${element.innerHTML.substring(0, 31)}...` + `${element.innerHTML.substring(0, 32)}...` ); } if (outerHTML.length > 251) { - outerHTML = `${outerHTML.substring(0, 250)}...`; + outerHTML = `${outerHTML.substring(0, 251)}...`; } return outerHTML; }; // valid element node - const isElementNode = (element) => + const isElementNode = (element: Element) => element.nodeType === window.Node.ELEMENT_NODE; // get css selelector diff --git a/a11y-js/package.json b/a11y-js/package.json index 459f0a84..758d4a8e 100644 --- a/a11y-js/package.json +++ b/a11y-js/package.json @@ -1,6 +1,6 @@ { "name": "a11y-js", - "version": "0.3.44", + "version": "0.3.45", "description": "Extremely fast accessibility evaluation for nodejs", "main": "./build/index.js", "keywords": [ diff --git a/fast_htmlcs/HTMLCS.Util.ts b/fast_htmlcs/HTMLCS.Util.ts index 11272a1f..4c60a8e0 100644 --- a/fast_htmlcs/HTMLCS.Util.ts +++ b/fast_htmlcs/HTMLCS.Util.ts @@ -476,7 +476,7 @@ _global.HTMLCS.util = { | { red: number; blue: number; green: number; alpha?: number } = color.toLowerCase(); - if (colour.substring(0, 3) === "rgb") { + if (colour.substr(0, 3) === "rgb") { // rgb[a](0, 0, 0[, 0]) format. const matches = /^rgba?\s*\((\d+),\s*(\d+),\s*(\d+)([^)]*)\)$/.exec( colour diff --git a/fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_2/1_2_4.ts b/fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_2/1_2_4.ts index f031c7b7..88209fc9 100644 --- a/fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_2/1_2_4.ts +++ b/fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_2/1_2_4.ts @@ -30,7 +30,7 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_2_1_2_4 = { * @param {DOMNode} element The element registered. * @param {DOMNode} top The top element of the tested code. */ - process: function (element, top) { + process: function (element, _) { HTMLCS.addMessage( HTMLCS.NOTICE, element, diff --git a/fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_3/1_3_1.ts b/fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_3/1_3_1.ts index ea4de202..88502097 100755 --- a/fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_3/1_3_1.ts +++ b/fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_3/1_3_1.ts @@ -42,55 +42,55 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_1 = { * @param {DOMNode} top The top element of the tested code. */ process: function (element, top) { - var nodeName = element.nodeName.toLowerCase(); + const nodeName = element.nodeName; if (element === top) { this.testPresentationMarkup(top); this.testEmptyDupeLabelForAttrs(top); } else { switch (nodeName) { - case "input": - case "textarea": - case "button": + case "INPUT": + case "TEXTAREA": + case "BUTTON": this.testLabelsOnInputs(element, top); break; - case "form": + case "FORM": this.testRequiredFieldsets(element); break; - case "select": + case "SELECT": this.testLabelsOnInputs(element, top); this.testOptgroup(element); break; - case "p": - case "div": + case "P": + case "DIV": this.testNonSemanticHeading(element); this.testListsWithBreaks(element); this.testUnstructuredNavLinks(element); break; - case "table": + case "TABLE": this.testGeneralTable(element); this.testTableHeaders(element); this.testTableCaptionSummary(element); break; - case "fieldset": + case "FIELDSET": this.testFieldsetLegend(element); break; - case "h1": - case "h2": - case "h3": - case "h4": - case "h5": - case "h6": + case "H1": + case "H2": + case "H3": + case "H4": + case "H5": + case "H6": this.testEmptyHeading(element); break; } - } + } }, /** @@ -110,13 +110,13 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_1 = { element.nodeName === "I" ) ) { - var childElements = element.querySelectorAll( + const childElements = element.querySelectorAll( "*:not(" + ["div", "span", "b", "i"].join("):not(") + ")" ); - var children = new Array(childElements.length); - var childIterator = 0; + const children = new Array(childElements.length); + let childIterator = 0; - for (var child of childElements) { + for (const child of childElements) { if (!child.hasAttribute("role")) { children[childIterator] = child; childIterator++; @@ -143,8 +143,8 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_1 = { */ testEmptyDupeLabelForAttrs: function (top) { this._labelNames = {}; - var labels = top.getElementsByTagName("label"); var refNode = null; + var labels = top.getElementsByTagName("label"); for (var i = 0; i < labels.length; i++) { var labelFor = labels[i].getAttribute("for"); @@ -234,6 +234,7 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_1 = { testLabelsOnInputs: function (element, _, muteErrors) { var nodeName = element.nodeName.toLowerCase(); var inputType = nodeName; + if (inputType === "input") { if (element.hasAttribute("type") === true) { inputType = element.getAttribute("type"); @@ -246,8 +247,8 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_1 = { var addToLabelList = function (found) { if (!hasLabel) { - hasLabel = {} - }; + hasLabel = {}; + } hasLabel[found] = true; }; @@ -365,7 +366,7 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_1 = { _global.HTMLCS.getTranslation("1_3_1_F68"), "F68" ); - } + } } return hasLabel; @@ -390,58 +391,51 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_1 = { var doctype = HTMLCS.util.getDocumentType(_doc); if (doctype && (doctype === "html5" || doctype === "xhtml5")) { - var tags = HTMLCS.util.getAllElements( + for (const tag of HTMLCS.util.getAllElements( top, "strike, tt, big, center, font" - ); - for (var i = 0; i < tags.length; i++) { - var msgCode = - "H49." + - tags[i].nodeName.substr(0, 1).toUpperCase() + - tags[i].nodeName.substr(1).toLowerCase(); + )) { HTMLCS.addMessage( HTMLCS.ERROR, - tags[i], + tag, _global.HTMLCS.getTranslation("1_3_1_H49."), - msgCode + "H49." + + tag.nodeName.substr(0, 1).toUpperCase() + + tag.nodeName.substr(1).toLowerCase() ); } // Align attributes, too. - var tags = HTMLCS.util.getAllElements(top, "*[align]"); - - for (var i = 0; i < tags.length; i++) { - var msgCode = "H49.AlignAttr"; - HTMLCS.addMessage(HTMLCS.ERROR, tags[i], "Align attributes .", msgCode); + for (const tag of HTMLCS.util.getAllElements(top, "*[align]")) { + HTMLCS.addMessage( + HTMLCS.ERROR, + tag, + "Align attributes .", + "H49.AlignAttr" + ); } } else { - var tags = HTMLCS.util.getAllElements( + for (const tag of HTMLCS.util.getAllElements( top, "b, i, u, s, strike, tt, big, small, center, font" - ); - for (var i = 0; i < tags.length; i++) { - var msgCode = - "H49." + - tags[i].nodeName.substr(0, 1).toUpperCase() + - tags[i].nodeName.substr(1).toLowerCase(); + )) { HTMLCS.addMessage( HTMLCS.WARNING, - tags[i], + tag, _global.HTMLCS.getTranslation("1_3_1_H49.Semantic"), - msgCode + "H49." + + tag.nodeName.substr(0, 1).toUpperCase() + + tag.nodeName.substr(1).toLowerCase() ); } // Align attributes, too. - var tags = HTMLCS.util.getAllElements(top, "*[align]"); - - for (var i = 0; i < tags.length; i++) { - var msgCode = "H49.AlignAttr"; + for (const tag of HTMLCS.util.getAllElements(top, "*[align]")) { HTMLCS.addMessage( HTMLCS.WARNING, - tags[i], + tag, _global.HTMLCS.getTranslation("1_3_1_H49.AlignAttr.Semantic"), - msgCode + "H49.AlignAttr" ); } } @@ -464,9 +458,7 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_1 = { if (tag === "p" || tag === "div") { var children = element.childNodes; if (children.length === 1 && children[0].nodeType === 1) { - var childTag = children[0].nodeName.toLowerCase(); - - if (/^(strong|em|b|i|u)$/.test(childTag) === true) { + if (/^(STRONG|EM|B|I|U)$/.test(children[0].nodeName) === true) { HTMLCS.addMessage( HTMLCS.WARNING, element, @@ -504,10 +496,10 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_1 = { var scopeAttr = this._testTableScopeAttrs(table); // Invalid scope attribute - emit always if scope tested. - for (var i = 0; i < scopeAttr.invalid.length; i++) { + for (const invalid of scopeAttr.invalid) { HTMLCS.addMessage( HTMLCS.ERROR, - scopeAttr.invalid[i], + invalid, _global.HTMLCS.getTranslation("1_3_1_H63.3"), "H63.3" ); @@ -541,7 +533,7 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_1 = { ); scopeAttr = null; } - } + } if (headersAttr.isMultiLevelHeadersTable) { HTMLCS.addMessage( @@ -594,8 +586,8 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_1 = { "H43.MissingHeadersAttrs" ); } - } - } + } + } // Errors where either is permitted, but neither are done properly (missing // certain elements). @@ -699,8 +691,8 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_1 = { for (var tagType in elements) { for (var i = 0; i < elements[tagType].length; i++) { var element = elements[tagType][i]; - var scope = ""; + if (element.hasAttribute("scope") === true) { retval.used = true; if (element.getAttribute("scope")) { @@ -729,8 +721,8 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_1 = { retval.correct = false; retval.invalid.push(element); } - } - } + } + } } } @@ -789,8 +781,8 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_1 = { "H73.3.NoSummary" ); } - } - } + } + } if (caption !== "") { if (HTMLCS.util.isLayoutTable(table) === true) { @@ -817,7 +809,7 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_1 = { "H39.3.NoCaption" ); } - } + } }, /** @@ -826,7 +818,7 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_1 = { * @param {DOMNode} fieldset Fieldset element to test upon. */ testFieldsetLegend: function (fieldset) { - var legend = fieldset.querySelector("legend"); + const legend = fieldset.querySelector("legend"); if (legend === null || legend.parentNode !== fieldset) { HTMLCS.addMessage( @@ -846,9 +838,7 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_1 = { * @param {DOMNode} select Select element to test upon. */ testOptgroup: function (select) { - var optgroup = select.querySelector("optgroup"); - - if (optgroup === null) { + if (select.querySelector("optgroup") === null) { // Optgroup isn't being used. HTMLCS.addMessage( HTMLCS.WARNING, @@ -896,7 +886,7 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_1 = { // Record that this name is used, but there is no fieldset. fieldset = null; } - } + } if (usedNames[optionName] === undefined) { usedNames[optionName] = fieldset; @@ -911,7 +901,7 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_1 = { "H71.SameName" ); break; - } + } } }, @@ -982,26 +972,25 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_1 = { break; } } - } + } }, - testHeadingOrder: function (top, level) { - var lastHeading = 0; - var headings = HTMLCS.util.getAllElements(top, "h1, h2, h3, h4, h5, h6"); + let lastHeading = 0; + + for (const heading of HTMLCS.util.getAllElements(top, "h1, h2, h3, h4, h5, h6")) { + const headingNum = parseInt(heading.nodeName.substring(1, 2)); + const headingNumStr = headingNum + "" - for (var i = 0; i < headings.length; i++) { - var headingNum = parseInt(headings[i].nodeName.substr(1, 1)); if (headingNum - lastHeading > 1) { if (lastHeading === 0) { // If last heading is empty, we are at document top and we are // expecting a H1, generally speaking. HTMLCS.addMessage( level, - headings[i], + heading, _global.HTMLCS.getTranslation("1_3_1_G141_a").replace( /\{\{headingNum\}\}/g, - // @ts-ignore - headingNum + headingNumStr ), "G141" ); @@ -1009,12 +998,10 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_1 = { HTMLCS.addMessage( level, - headings[i], + heading, _global.HTMLCS.getTranslation("1_3_1_G141_b") - // @ts-ignore - .replace(/\{\{headingNum\}\}/g, headingNum) - // @ts-ignore - .replace(/\{\{properHeadingNum\}\}/g, lastHeading + 1), + .replace(/\{\{headingNum\}\}/g, headingNumStr) + .replace(/\{\{properHeadingNum\}\}/g, (lastHeading + 1) + ""), "G141" ); } @@ -1031,9 +1018,9 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_1 = { * @returns void */ testEmptyHeading: function (element) { - var text = HTMLCS.util.getElementTextContent(element, true); - - if (/^\s*$/.test(text) === true) { + if ( + /^\s*$/.test(HTMLCS.util.getElementTextContent(element, true)) === true + ) { HTMLCS.addMessage( HTMLCS.ERROR, element, @@ -1051,13 +1038,12 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_1 = { * @returns void */ testUnstructuredNavLinks: function (element) { - var linksLength = 0; + let linksLength = 0; - var childNodes = element.childNodes; - for (var i = 0; i < childNodes.length; i++) { + for (const childNodes of element.childNodes) { if ( - childNodes[i].nodeType === 1 && - childNodes[i].nodeName.toLowerCase() === "a" + childNodes.nodeType === 1 && + childNodes.nodeName === "A" ) { linksLength++; if (linksLength > 1) { @@ -1070,11 +1056,11 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_1 = { // Going to throw a warning here, mainly because we cannot easily tell // whether it is just a paragraph with multiple links, or a navigation // structure. - var parent = element.parentNode; + let parent = element.parentNode; while ( parent !== null && - parent.nodeName.toLowerCase() !== "ul" && - parent.nodeName.toLowerCase() !== "ol" + parent.nodeName !== "UL" && + parent.nodeName !== "OL" ) { parent = parent.parentNode; } @@ -1087,7 +1073,7 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_1 = { "H48" ); } - } + } }, /** @@ -1115,4 +1101,4 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_1 = { ); } }, -}; \ No newline at end of file +}; diff --git a/fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_3/1_3_2.js b/fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_3/1_3_2.ts similarity index 93% rename from fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_3/1_3_2.js rename to fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_3/1_3_2.ts index 8e258fb3..5b664032 100644 --- a/fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_3/1_3_2.js +++ b/fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_3/1_3_2.ts @@ -20,9 +20,7 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_2 = { * * @returns {Array} The list of elements. */ - register: function () { - return ["_top"]; - }, + register: () => ["_top"], /** * Process the registered element. @@ -30,7 +28,7 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_2 = { * @param {DOMNode} element The element registered. * @param {DOMNode} top The top element of the tested code. */ - process: function (element, top) { + process: (_, top) => { HTMLCS.addMessage( HTMLCS.NOTICE, top, diff --git a/fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_3/1_3_3.js b/fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_3/1_3_3.ts similarity index 93% rename from fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_3/1_3_3.js rename to fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_3/1_3_3.ts index e49e5599..4f5c5875 100644 --- a/fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_3/1_3_3.js +++ b/fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_3/1_3_3.ts @@ -20,9 +20,7 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_3 = { * * @returns {Array} The list of elements. */ - register: function () { - return ["_top"]; - }, + register: () => ["_top"], /** * Process the registered element. @@ -30,7 +28,7 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_3 = { * @param {DOMNode} element The element registered. * @param {DOMNode} top The top element of the tested code. */ - process: function (element, top) { + process: (_, top) => { HTMLCS.addMessage( HTMLCS.NOTICE, top, diff --git a/fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_3/1_3_4.js b/fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_3/1_3_4.ts similarity index 93% rename from fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_3/1_3_4.js rename to fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_3/1_3_4.ts index f1ea2df7..08c63bc3 100644 --- a/fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_3/1_3_4.js +++ b/fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_3/1_3_4.ts @@ -20,9 +20,7 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_4 = { * * @returns {Array} The list of elements. */ - register: function () { - return ["_top"]; - }, + register: () => ["_top"], /** * Process the registered element. @@ -30,7 +28,7 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_4 = { * @param {DOMNode} element The element registered. * @param {DOMNode} top The top element of the tested code. */ - process: function (element, top) { + process: function (_, top) { HTMLCS.addMessage( HTMLCS.NOTICE, top, diff --git a/fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_3/1_3_5.js b/fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_3/1_3_5.ts similarity index 92% rename from fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_3/1_3_5.js rename to fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_3/1_3_5.ts index 24b49450..23670452 100644 --- a/fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_3/1_3_5.js +++ b/fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_3/1_3_5.ts @@ -20,9 +20,7 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_5 = { * * @returns {Array} The list of elements. */ - register: function () { - return ["_top", "input", "select", "textarea"]; - }, + register: () => ["_top", "input", "select", "textarea"], /** * Checks that the values of the autocomplete attribute are values listed in the HTML 5.2 spec. @@ -30,7 +28,7 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_5 = { * @param {DOMNode} element The element registered. */ checkValidAttributes: function (element) { - var valid_attributes = [ + const valid_attributes = [ "additional-name", "address-level1", "address-level2", @@ -96,9 +94,11 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_5 = { ]; var valuesStr = element.getAttribute("autocomplete"); + if (typeof valuesStr !== "string") { return; } + var values = valuesStr.split(" "); var hasFaultyValue = false; @@ -133,7 +133,7 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_5 = { * @param {DOMNode} element The element registered. */ checkControlGroups: function (element) { - var textFields = [ + const textFields = [ "name", "honorific-prefix", "given-name", @@ -172,7 +172,7 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_5 = { "tel-local-suffix", "tel-extension", ]; - var isText = + const isText = (element.tagName === "INPUT" && element.getAttribute("type") === "hidden") || (element.tagName === "INPUT" && @@ -182,15 +182,15 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_5 = { element.tagName === "TEXTAREA" || element.tagName === "SELECT"; - var multilineFields = ["street-address"]; - var isMultiline = + const multilineFields = ["street-address"]; + const isMultiline = (element.tagName === "INPUT" && element.getAttribute("type") === "hidden") || element.tagName === "TEXTAREA" || element.tagName === "SELECT"; - var passwordFields = ["new-password", "current-password"]; - var isPassword = + const passwordFields = ["new-password", "current-password"]; + const isPassword = (element.tagName === "INPUT" && element.getAttribute("type") === "hidden") || (element.tagName === "INPUT" && @@ -202,8 +202,8 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_5 = { element.tagName === "TEXTAREA" || element.tagName === "SELECT"; - var urlFields = ["url", "photo", "impp"]; - var isUrl = + const urlFields = ["url", "photo", "impp"]; + const isUrl = (element.tagName === "INPUT" && element.getAttribute("type") === "hidden") || (element.tagName === "INPUT" && @@ -215,8 +215,8 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_5 = { element.tagName === "TEXTAREA" || element.tagName === "SELECT"; - var telFields = ["tel"]; - var isTel = + const telFields = ["tel"]; + const isTel = (element.tagName === "INPUT" && element.getAttribute("type") === "hidden") || (element.tagName === "INPUT" && @@ -227,7 +227,7 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_5 = { element.tagName === "TEXTAREA" || element.tagName === "SELECT"; - var numericFields = [ + const numericFields = [ "cc-exp-month", "cc-exp-year", "transaction-amount", @@ -235,7 +235,7 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_5 = { "bday-month", "bday-year", ]; - var isNumeric = + const isNumeric = (element.tagName === "INPUT" && element.getAttribute("type") === "hidden") || (element.tagName === "INPUT" && @@ -247,8 +247,8 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_5 = { element.tagName === "TEXTAREA" || element.tagName === "SELECT"; - var monthFields = ["cc-exp"]; - var isMonth = + const monthFields = ["cc-exp"]; + const isMonth = (element.tagName === "INPUT" && element.getAttribute("type") === "hidden") || (element.tagName === "INPUT" && @@ -260,8 +260,8 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_5 = { element.tagName === "TEXTAREA" || element.tagName === "SELECT"; - var dateFields = ["bday"]; - var isDate = + const dateFields = ["bday"]; + const isDate = (element.tagName === "INPUT" && element.getAttribute("type") === "hidden") || (element.tagName === "INPUT" && @@ -273,7 +273,7 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_5 = { element.tagName === "TEXTAREA" || element.tagName === "SELECT"; - var values = element.getAttribute("autocomplete").split(" "); + const values = element.getAttribute("autocomplete").split(" "); for (var i = 0; i < values.length; i++) { values[i] = values[i].trim(); @@ -369,11 +369,9 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_5 = { */ process: function (element, top) { if (element === top) { - var els = HTMLCS.util.getAllElements(element, "*[autocomplete]"); - for (var i = 0; i < els.length; i++) { - var x = els[i]; - this.checkValidAttributes(x); - this.checkControlGroups(x); + for (const ele of HTMLCS.util.getAllElements(element, "*[autocomplete]")) { + this.checkValidAttributes(ele); + this.checkControlGroups(ele); } } else { HTMLCS.addMessage( @@ -383,7 +381,7 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_5 = { "H98" ); // See table in https://www.w3.org/TR/html52/sec-forms.html#the-input-element - var types_to_skip = [ + const types_to_skip = [ "hidden", "checkbox", "radio", diff --git a/fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_3/1_3_6.js b/fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_3/1_3_6.ts similarity index 93% rename from fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_3/1_3_6.js rename to fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_3/1_3_6.ts index 610199df..a41fef7e 100644 --- a/fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_3/1_3_6.js +++ b/fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_3/1_3_6.ts @@ -20,9 +20,7 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_6 = { * * @returns {Array} The list of elements. */ - register: function () { - return ["_top"]; - }, + register: () => ["_top"], /** * Process the registered element. @@ -30,7 +28,7 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_6 = { * @param {DOMNode} element The element registered. * @param {DOMNode} top The top element of the tested code. */ - process: function (element, top) { + process: function (_, top) { HTMLCS.addMessage( HTMLCS.NOTICE, top, diff --git a/fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_4/1_4_1.js b/fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_4/1_4_1.ts similarity index 93% rename from fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_4/1_4_1.js rename to fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_4/1_4_1.ts index 3ee12f6f..c18bcb1c 100644 --- a/fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_4/1_4_1.js +++ b/fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_4/1_4_1.ts @@ -20,9 +20,7 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_4_1_4_1 = { * * @returns {Array} The list of elements. */ - register: function () { - return ["_top"]; - }, + register: () => ["_top"], /** * Process the registered element. @@ -30,7 +28,7 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_4_1_4_1 = { * @param {DOMNode} element The element registered. * @param {DOMNode} top The top element of the tested code. */ - process: function (element, top) { + process: function (_, top) { HTMLCS.addMessage( HTMLCS.NOTICE, top, diff --git a/fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_4/1_4_2.js b/fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_4/1_4_2.ts similarity index 90% rename from fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_4/1_4_2.js rename to fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_4/1_4_2.ts index 1881c734..f12da13f 100644 --- a/fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_4/1_4_2.js +++ b/fast_htmlcs/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_4/1_4_2.ts @@ -20,9 +20,7 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_4_1_4_2 = { * * @returns {Array} The list of elements. */ - register: function () { - return ["object", "embed", "applet", "bgsound", "audio", "video"]; - }, + register: () => ["object", "embed", "applet", "bgsound", "audio", "video"], /** * Process the registered element. @@ -30,7 +28,7 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_4_1_4_2 = { * @param {DOMNode} element The element registered. * @param {DOMNode} top The top element of the tested code. */ - process: function (element, top) { + process: function (_, top) { HTMLCS.addMessage( HTMLCS.NOTICE, top, diff --git a/fast_htmlcs/globals.d.ts b/fast_htmlcs/globals.d.ts index 9058e7ea..39bb727f 100644 --- a/fast_htmlcs/globals.d.ts +++ b/fast_htmlcs/globals.d.ts @@ -104,6 +104,8 @@ type GuideLine = { _labelNames?: string[]; register(): string[]; process(element: Element, top?: Element): void; + checkValidAttributes?(element: Element): void; + checkControlGroups?(element: Element): void; testSemanticPresentationRole?(element: Element): void; testEmptyDupeLabelForAttrs?( top: Element & { getElementById?(id: string): HTMLElement } @@ -147,6 +149,13 @@ declare global { HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_1_A: GuideLine; HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_1_AAA: GuideLine; HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_1: GuideLine; + HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_2: GuideLine; + HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_3: GuideLine; + HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_4: GuideLine; + HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_5: GuideLine; + HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_3_1_3_6: GuideLine; + HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_4_1_4_1: GuideLine; + HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_4_1_4_2: GuideLine; HTMLCS_WCAG2A: RuleSet; HTMLCS_WCAG2AAA: RuleSet; HTMLCS_WCAG2AA: RuleSet; diff --git a/fast_htmlcs/package.json b/fast_htmlcs/package.json index 82af33ab..1f1d46e4 100644 --- a/fast_htmlcs/package.json +++ b/fast_htmlcs/package.json @@ -1,6 +1,6 @@ { "name": "fast_htmlcs", - "version": "0.0.21", + "version": "0.0.22", "description": "HTML_CodeSniffer is a client-side JavaScript that checks a HTML document or source code, and detects violations of a defined coding standard.", "license": "BSD-3-Clause", "main": "index.js", diff --git a/test-results/a11y-js-tests-axecore-playwright--axe-core-playwright-audit-drakeMock/@axe-core_playwright.json b/test-results/a11y-js-tests-axecore-playwright--axe-core-playwright-audit-drakeMock/@axe-core_playwright.json index ef092cbe..f2ff9f44 100644 --- a/test-results/a11y-js-tests-axecore-playwright--axe-core-playwright-audit-drakeMock/@axe-core_playwright.json +++ b/test-results/a11y-js-tests-axecore-playwright--axe-core-playwright-audit-drakeMock/@axe-core_playwright.json @@ -13,7 +13,7 @@ "orientationAngle": 90, "orientationType": "landscape-primary" }, - "timestamp": "2023-05-03T23:50:05.175Z", + "timestamp": "2023-05-04T14:13:20.298Z", "url": "about:blank", "toolOptions": { "reporter": "v1" diff --git a/test-results/a11y-js-tests-axecore-playwright--axe-core-playwright-audit-drakeMock/@axe-core_playwright_stats.json b/test-results/a11y-js-tests-axecore-playwright--axe-core-playwright-audit-drakeMock/@axe-core_playwright_stats.json index 11178aaf..1a954e21 100644 --- a/test-results/a11y-js-tests-axecore-playwright--axe-core-playwright-audit-drakeMock/@axe-core_playwright_stats.json +++ b/test-results/a11y-js-tests-axecore-playwright--axe-core-playwright-audit-drakeMock/@axe-core_playwright_stats.json @@ -1,7 +1,7 @@ { "mock": "[drakeMock]", "htmlSize": 71784, - "duration": 1079.1019999980927, + "duration": 827.5457080006599, "errors": 8, "warnings": 56, "runner": [ diff --git a/test-results/a11y-js-tests-basic-axe-playwright-fast-axecore-audit-drakeMock/axe-core.json b/test-results/a11y-js-tests-basic-axe-playwright-fast-axecore-audit-drakeMock/axe-core.json index ad320344..163c974b 100644 --- a/test-results/a11y-js-tests-basic-axe-playwright-fast-axecore-audit-drakeMock/axe-core.json +++ b/test-results/a11y-js-tests-basic-axe-playwright-fast-axecore-audit-drakeMock/axe-core.json @@ -93,7 +93,7 @@ "recurrence": 0 }, { - "context": "", + "context": "", "selector": "#hs-cta-wrapper-991abde1-792b-4f15-b338-a79c214c3e94", "code": "duplicate-id", "type": "error", @@ -138,7 +138,7 @@ "recurrence": 0 }, { - "context": "", + "context": "", "selector": "#hs-cta-991abde1-792b-4f15-b338-a79c214c3e94", "code": "duplicate-id", "type": "error", @@ -153,7 +153,7 @@ "recurrence": 0 }, { - "context": "
\n
", + "context": "
\n
", "selector": "html > body > div:nth-child(3) > div > div:nth-child(3) > div > div > div:nth-child(3) > div > div > div:nth-child(3) > div > h5", "code": "heading-order", "type": "error", @@ -183,7 +183,7 @@ "recurrence": 0 }, { - "context": "