@afixt/test-utils 1.1.7 → 1.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +2 -1
- package/.github/dependabot.yml +36 -0
- package/.github/workflows/ci.yml +71 -0
- package/.github/workflows/security.yml +142 -0
- package/.husky/pre-commit +1 -0
- package/.jscpd.json +27 -0
- package/.markdownlint.json +9 -0
- package/.prettierignore +13 -0
- package/.prettierrc +10 -0
- package/docs/arrayUtils.js.html +2 -2
- package/docs/domUtils.js.html +2 -2
- package/docs/getAccessibleName.js.html +2 -2
- package/docs/getAccessibleText.js.html +2 -2
- package/docs/getAriaAttributesByElement.js.html +2 -2
- package/docs/getCSSGeneratedContent.js.html +2 -2
- package/docs/getComputedRole.js.html +2 -2
- package/docs/getFocusableElements.js.html +2 -2
- package/docs/getGeneratedContent.js.html +2 -2
- package/docs/getImageText.js.html +2 -2
- package/docs/getStyleObject.js.html +2 -2
- package/docs/global.html +2 -2
- package/docs/hasAccessibleName.js.html +2 -2
- package/docs/hasAttribute.js.html +2 -2
- package/docs/hasCSSGeneratedContent.js.html +2 -2
- package/docs/hasHiddenParent.js.html +2 -2
- package/docs/hasParent.js.html +2 -2
- package/docs/hasValidAriaAttributes.js.html +2 -2
- package/docs/hasValidAriaRole.js.html +2 -2
- package/docs/index.html +2 -2
- package/docs/index.js.html +2 -2
- package/docs/isAriaAttributesValid.js.html +2 -2
- package/docs/isComplexTable.js.html +2 -2
- package/docs/isDataTable.js.html +2 -2
- package/docs/isFocusable.js.html +2 -2
- package/docs/isHidden.js.html +2 -2
- package/docs/isOffScreen.js.html +2 -2
- package/docs/isValidUrl.js.html +2 -2
- package/docs/isVisible.js.html +2 -2
- package/docs/module-afixt-test-utils.html +2 -2
- package/docs/scripts/core.js +726 -726
- package/docs/scripts/core.min.js +22 -22
- package/docs/scripts/resize.js +90 -90
- package/docs/scripts/search.js +265 -265
- package/docs/scripts/third-party/Apache-License-2.0.txt +202 -202
- package/docs/scripts/third-party/fuse.js +8 -8
- package/docs/scripts/third-party/hljs-line-num-original.js +369 -369
- package/docs/scripts/third-party/hljs-original.js +5171 -5171
- package/docs/scripts/third-party/popper.js +5 -5
- package/docs/scripts/third-party/tippy.js +1 -1
- package/docs/scripts/third-party/tocbot.js +671 -671
- package/docs/styles/clean-jsdoc-theme-base.css +1159 -1159
- package/docs/styles/clean-jsdoc-theme-dark.css +412 -412
- package/docs/styles/clean-jsdoc-theme-light.css +482 -482
- package/docs/styles/clean-jsdoc-theme-scrollbar.css +29 -29
- package/docs/testContrast.js.html +2 -2
- package/docs/testLang.js.html +2 -2
- package/docs/testOrder.js.html +2 -2
- package/eslint.config.mjs +84 -0
- package/package.json +68 -41
- package/scratchpads/issue-6-standardize-repo.md +109 -0
- package/src/getAccessibleName.js +156 -112
- package/src/getAccessibleText.js +71 -42
- package/test/getAccessibleName.test.js +379 -315
- package/test/getAccessibleText.test.js +375 -308
- package/.eslintrc +0 -78
- package/.github/workflows/test.yml +0 -26
package/src/getAccessibleText.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
const { isEmpty } = require(
|
|
1
|
+
const { isEmpty } = require('./stringUtils.js');
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Get all accessible text for an element, including aria-labels and content from children.
|
|
5
|
+
* Traverses the DOM subtree collecting text from text nodes, img alt attributes,
|
|
6
|
+
* and input[type="image"] alt attributes.
|
|
5
7
|
* @param {Element} el - The DOM element.
|
|
6
8
|
* @returns {string} The accessible text.
|
|
7
9
|
*/
|
|
@@ -13,55 +15,82 @@ function getAccessibleText(el) {
|
|
|
13
15
|
if (!el.isConnected) {
|
|
14
16
|
return '';
|
|
15
17
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
if (el.textContent) {
|
|
21
|
-
textContent = el.textContent.trim();
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// Check for aria-label
|
|
25
|
-
if (el.hasAttribute("aria-label")) {
|
|
26
|
-
const ariaLabel = el.getAttribute("aria-label").trim();
|
|
18
|
+
|
|
19
|
+
// Check for aria-label first (highest priority)
|
|
20
|
+
if (el.hasAttribute('aria-label')) {
|
|
21
|
+
const ariaLabel = el.getAttribute('aria-label').trim();
|
|
27
22
|
if (ariaLabel) {
|
|
28
|
-
// Prioritize aria-label if present
|
|
29
23
|
return ariaLabel;
|
|
30
24
|
}
|
|
31
25
|
}
|
|
32
|
-
|
|
33
|
-
// Check for img alt text
|
|
34
|
-
if (el.tagName.toLowerCase() ===
|
|
35
|
-
return el.getAttribute(
|
|
26
|
+
|
|
27
|
+
// Check for img alt text when the element itself is an img
|
|
28
|
+
if (el.tagName.toLowerCase() === 'img' && el.hasAttribute('alt')) {
|
|
29
|
+
return el.getAttribute('alt').trim();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Check for input[type="image"] alt text when the element itself is one
|
|
33
|
+
if (
|
|
34
|
+
el.tagName.toLowerCase() === 'input' &&
|
|
35
|
+
el.getAttribute('type') === 'image' &&
|
|
36
|
+
el.hasAttribute('alt')
|
|
37
|
+
) {
|
|
38
|
+
return el.getAttribute('alt').trim();
|
|
36
39
|
}
|
|
37
|
-
|
|
38
|
-
//
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
40
|
+
|
|
41
|
+
// Collect accessible text from the subtree, including text nodes
|
|
42
|
+
// and alt text from embedded images
|
|
43
|
+
const parts = collectSubtreeText(el);
|
|
44
|
+
return parts.join(' ').replace(/\s+/g, ' ').trim();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Recursively collect accessible text parts from an element's subtree.
|
|
49
|
+
* Handles text nodes, img alt text, and input[type="image"] alt text.
|
|
50
|
+
* @param {Node} node - The DOM node to traverse.
|
|
51
|
+
* @returns {string[]} Array of text parts found in the subtree.
|
|
52
|
+
*/
|
|
53
|
+
function collectSubtreeText(node) {
|
|
54
|
+
const parts = [];
|
|
55
|
+
|
|
56
|
+
for (let child = node.firstChild; child; child = child.nextSibling) {
|
|
57
|
+
if (child.nodeType === Node.TEXT_NODE) {
|
|
58
|
+
const text = child.nodeValue.trim();
|
|
59
|
+
if (!isEmpty(text)) {
|
|
60
|
+
parts.push(text);
|
|
61
|
+
}
|
|
62
|
+
} else if (child.nodeType === Node.ELEMENT_NODE) {
|
|
63
|
+
const tag = child.tagName.toLowerCase();
|
|
64
|
+
|
|
65
|
+
// img with non-empty alt contributes its alt text
|
|
66
|
+
if (tag === 'img' && child.hasAttribute('alt')) {
|
|
67
|
+
const alt = child.getAttribute('alt').trim();
|
|
68
|
+
if (alt) {
|
|
69
|
+
parts.push(alt);
|
|
70
|
+
}
|
|
71
|
+
continue;
|
|
50
72
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
73
|
+
|
|
74
|
+
// input[type="image"] with non-empty alt contributes its alt text
|
|
75
|
+
if (
|
|
76
|
+
tag === 'input' &&
|
|
77
|
+
child.getAttribute('type') === 'image' &&
|
|
78
|
+
child.hasAttribute('alt')
|
|
79
|
+
) {
|
|
80
|
+
const alt = child.getAttribute('alt').trim();
|
|
81
|
+
if (alt) {
|
|
82
|
+
parts.push(alt);
|
|
83
|
+
}
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Recurse into other element children
|
|
88
|
+
parts.push(...collectSubtreeText(child));
|
|
58
89
|
}
|
|
59
|
-
|
|
60
|
-
textContent = textNodes.join(" ").trim();
|
|
61
90
|
}
|
|
62
|
-
|
|
63
|
-
return
|
|
91
|
+
|
|
92
|
+
return parts;
|
|
64
93
|
}
|
|
65
94
|
|
|
66
95
|
// Export for CommonJS module usage
|
|
67
|
-
module.exports = { getAccessibleText };
|
|
96
|
+
module.exports = { getAccessibleText };
|