* Get element text content (from selectorUtils.ts lines 65-99)
(element)
| 173 | * Get element text content (from selectorUtils.ts lines 65-99) |
| 174 | */ |
| 175 | function elementText(element) { |
| 176 | if (!element) return { full: '', normalized: '', immediate: [] }; |
| 177 | |
| 178 | const tagName = element.nodeName; |
| 179 | if (['SCRIPT', 'NOSCRIPT', 'STYLE'].includes(tagName)) |
| 180 | return { full: '', normalized: '', immediate: [] }; |
| 181 | |
| 182 | // Special case for input buttons |
| 183 | if (tagName === 'INPUT' && ['submit', 'button'].includes((element.type || '').toLowerCase())) { |
| 184 | const value = element.value || ''; |
| 185 | return { full: value, normalized: normalizeWhiteSpace(value), immediate: [value] }; |
| 186 | } |
| 187 | |
| 188 | let full = ''; |
| 189 | const immediate = []; |
| 190 | let currentImmediate = ''; |
| 191 | |
| 192 | for (let child = element.firstChild; child; child = child.nextSibling) { |
| 193 | if (child.nodeType === Node.TEXT_NODE) { |
| 194 | full += child.nodeValue || ''; |
| 195 | currentImmediate += child.nodeValue || ''; |
| 196 | } else if (child.nodeType === Node.ELEMENT_NODE) { |
| 197 | if (currentImmediate) { |
| 198 | immediate.push(currentImmediate); |
| 199 | currentImmediate = ''; |
| 200 | } |
| 201 | full += elementText(child).full; |
| 202 | } |
| 203 | } |
| 204 | if (currentImmediate) immediate.push(currentImmediate); |
| 205 | |
| 206 | // Include shadow DOM text |
| 207 | if (element.shadowRoot) { |
| 208 | full += elementText(element.shadowRoot).full; |
| 209 | } |
| 210 | |
| 211 | return { |
| 212 | full, |
| 213 | normalized: normalizeWhiteSpace(full), |
| 214 | immediate |
| 215 | }; |
| 216 | } |
| 217 | |
| 218 | /** |
| 219 | * Get element labels (from selectorUtils.ts lines 115-131) |
no test coverage detected