Skip to content

fix: keep element text in simplifyHtmlElement - #5691

Open
DavertMik wants to merge 1 commit into
4.xfrom
fix/simplify-html-keep-text
Open

fix: keep element text in simplifyHtmlElement#5691
DavertMik wants to merge 1 commit into
4.xfrom
fix/simplify-html-keep-text

Conversation

@DavertMik

Copy link
Copy Markdown
Contributor

What was wrong

simplifyHtmlElement() calls removeNonInteractiveElements(), which strips non-interactive descendants. When an interactive element's visible label lives in nested <span>s (icon + badge + text button markup), everything inside is removed and the element serializes as an empty shell.

import { simplifyHtmlElement } from './lib/html.js'
const html = `<button type="button"><span class="content inline-flex items-center gap-3 w-full"><span class="badge badge-type manual"><svg class="md-icon md-icon-file-document-outline"></svg></span><span>New test</span></span></button>`
console.log(simplifyHtmlElement(html))

Before:

<button type="button"><span class="content inline-flex items-center w-full"></span></button>

After:

<button type="button"><span class="content inline-flex items-center w-full"><span>New test</span></span></button>

Why it matters

WebElement.toSimplifiedHTML() is the only caller, and it feeds MultipleElementsFound, whose job is to describe candidate elements so a human or an agent can tell them apart. With the labels stripped, two different menu items — New test and New tests from requirement — rendered byte-identically, making the error message useless and any automated choice between them a guess.

The change

removeNonInteractiveElements() gets an opt-in keepText option, false by default. When enabled, a non-interactive subtree is dropped only if it contains no visible text. simplifyHtmlElement() passes keepText: true, since it describes a single element and that element's own text is exactly what the caller needs.

removeNonInteractiveElements()'s existing behavior is unchanged: with keepText false the new condition short-circuits, and output on the full-page fixtures (test/data/github.html, test/data/testomat.html) is byte-identical to before. maxLength truncation still applies after simplification, as before.

Tests

New #simplifyHtmlElement block in test/unit/html_test.js covers the nested label, distinguishability of two similar labels, dropping of text-free nested markup, maxLength truncation, and that removeNonInteractiveElements() still strips the nested label by default.

npx mocha test/unit --recursive --timeout 10000 — 786 passing, 11 pending, 0 failing.

removeNonInteractiveElements dropped non-interactive descendants, so an
interactive element whose label lives in nested spans was serialized as an
empty shell. Add an opt-in keepText option, off by default, and use it from
simplifyHtmlElement which describes a single element.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JbhzmY1M51pyRysUx32MdP
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant