Skip to content

fix(dom): honor PowerCSS :expr() in image/link selector arguments - #6

Open
platonai wants to merge 5 commits into
mainfrom
fix/issue-5-img-expr-selector
Open

platonai wants to merge 5 commits into
mainfrom
fix/issue-5-img-expr-selector

Conversation

@platonai

@platonai platonai commented Sep 6, 2026

Copy link
Copy Markdown
Owner

Summary

Fixes #5: DOM_FIRST_IMG / DOM_NTH_IMG / DOM_ALL_IMGS (and the link helpers) with a PowerCSS :expr(...) selector silently matched nothing.

Root cause

appendSelectorIfMissing() in pulsar-dom (used by the image/link scanning helpers in DomSelectFunctions and DomQueries) decided whether the query already targets img/a by splitting the query on raw whitespace. Spaces inside a pseudo-class argument such as img:expr(width > 200) were mistaken for selector separators, so the query was rewritten into img:expr(width > 200) img — an image element that contains a descendant image, which never matches. Result: empty column, exit 0, silent data loss.

Fix

appendSelectorIfMissing() now splits only on top-level whitespace, ignoring spaces inside parentheses, brackets and quoted strings:

  • img:expr(width > 200) → unchanged (was img:expr(width > 200) img) ✅
  • a:contains(Some Text) → unchanged (same bug for links) ✅
  • img[src*="a b"] → unchanged ✅
  • :root / div.gallery / div:expr(width > 100) → still get img appended, as before ✅

Tests

  • TestImageQueries (pulsar-dom-tests, 5 tests): appendSelectorIfMissing behavior + end-to-end PowerSelector / selectImages with img:expr(width > 200) against a FeaturedDocument with vi geometry.
  • DomImageFunctionExprTests (pulsar-ql-tests, 3 tests): DOM_FIRST_IMG / DOM_NTH_IMG / DOM_ALL_IMGS with img:expr(width > 200) return the wide-image srcs.

Both suites failed before the fix and pass after. Full pulsar-dom-tests module: 376 tests, 0 failures.

github-actions Bot and others added 5 commits September 4, 2026 03:40
Post-release version bump to the next patch snapshot.

Co-Authored-By: Claude <noreply@anthropic.com>
The release bump-version job updated 28 pom.xml files in the workspace,
but 'git add VERSION **/pom.xml' only staged one-directory-deep POMs
(bash without globstar treats '**' as '*'). The root parent POM and all
nested module POMs stayed on 4.11.12-SNAPSHOT, breaking parent POM
resolution in CI.

- Bump the remaining 22 POMs (root + nested modules) to 4.11.13-SNAPSHOT
- Stage the root pom.xml explicitly in release.yml and quote the glob so
  git's own pathspec expands '**' to any depth

Co-Authored-By: Claude <noreply@anthropic.com>
…renderer predicates

Both renderers treated ref-addressability (backendNodeId/locator) as an interactivity
signal: the 'ref != null' / 'ref > 0' early returns qualified virtually every DOM
node (CDP assigns backend node ids broadly), turning AriaSnapshotOptions(interactive
= true) into a no-op filter that leaked headings, paragraphs, listitems and generic
containers into interactive-only output.

- Add AriaSnapshotFiltering as the single shared predicate: a role widget
  (INTERACTIVE_ROLES) or an isInteractable signal qualifies; refs never qualify.
- AriaSnapshotRenderer and NanoAriaSnapshotRenderer now call the shared predicate,
  so viewport/nano and whole-page/full renderers agree on the same DOM.
- While interactive mode is active, skip --compact collapsing so kept interactive
  nodes (e.g. nameless cursor:pointer divs) are not dropped.
- Unit tests for both renderers (structural roles excluded even with refs, plain
  div with backendNodeId does not survive, descendants promoted, input type
  matrix, identical output across renderers) plus an E2E strict-mode test.

Closes #3

Co-Authored-By: Claude <noreply@anthropic.com>
Post-release version bump to the next patch snapshot.

Co-Authored-By: Claude <noreply@anthropic.com>
DOM_*_IMG / DOM_*_HREF helpers auto-append the target tag (img/a) to the
css query when it is missing. appendSelectorIfMissing split the query on
raw whitespace, so spaces inside a pseudo-class argument such as
img:expr(width > 200) broke the detection and the query was rewritten to
"img:expr(width > 200) img", which silently matches nothing (an image
cannot contain an image): empty column, exit 0.

Split only on top-level whitespace, ignoring spaces inside parentheses,
brackets and quoted strings, so img:expr(width > 200), a:contains(Some Text)
and img[src*="a b"] are left intact while ":root" / "div.gallery" still get
"img" appended.

Closes #5

Co-Authored-By: Claude <noreply@anthropic.com>
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.

DOM_FIRST_IMG with PowerCSS :expr() selector silently matches nothing (empty column, exit 0)

2 participants