Skip to content

fix(xiaohongshu): scan composer media from document.body so native text-to-image works - #2297

Open
liuxinyea wants to merge 1 commit into
jackwener:mainfrom
liuxinyea:main
Open

fix(xiaohongshu): scan composer media from document.body so native text-to-image works#2297
liuxinyea wants to merge 1 commit into
jackwener:mainfrom
liuxinyea:main

Conversation

@liuxinyea

@liuxinyea liuxinyea commented Aug 18, 2026

Copy link
Copy Markdown

Description

Problem

opencli xiaohongshu publish --card-text (小红书原生的「文字生成图片」/ text-to-image card flow) always aborts with:

expected at least N visible media item(s), got 0

Root cause

currentComposerMediaCount() located the composer's DOM root by walking up from the title element:

const root = titleEl?.closest('form, [class*="publish"], [class*="editor"], [class*="note"]') || document.body;

Xiaohongshu's current React renderer mounts the image / card editor in a different subtree than the title. So closest(...) resolves to a container that never contains the generated card media — the scan always returns 0, and the publisher refuses to submit even though the cards were generated correctly.

Fix

  • Scan from document.body instead of the narrow closest(...) match, so generated cards are always found regardless of where XHS mounts the editor.
  • Extend the media selector with image, svg (alongside img, video, canvas) for completeness.
       const titleEl = Array.from(document.querySelectorAll('input, textarea, [contenteditable="true"]'))
         .map((sel) => Array.from(document.querySelectorAll(sel)))
         .flat()
         .find((el) => visibleBox(el));
-      const root = titleEl?.closest('form, [class*="publish"], [class*="editor"], [class*="note"]') || document.body;
+      const root = document.body;
       const seen = new Set();
       let count = 0;
-      for (const el of Array.from(root.querySelectorAll('img, video, canvas, [style*="background-image"]'))) {
+      for (const el of Array.from(root.querySelectorAll('img, image, svg, video, canvas, [style*="background-image"]'))) {
         if (!visibleMedia(el)) continue;

Verification

  • Manual: opencli xiaohongshu publish --card-text "..." --card-style 简约 --draft now generates the cards and passes the media-count gate (previously got 0).
  • Confirmed on two independent browser profiles / accounts.

Trade-offs

  • document.body is broader than the old root, but safe: the function already filters each candidate via visibleMedia(el) + getBoundingClientRect(), so unrelated images elsewhere on the page are excluded.
  • If XHS later wraps the editor in a reliably-located, specific container, we can narrow root back down.

Related issue: (none — discovered via a real automation run; link one here if it exists)

Type of Change

  • 🐛 Bug fix
  • ✨ New feature
  • 🌐 New site adapter
  • 📝 Documentation
  • ♻️ Refactor
  • 🔧 CI / build / tooling

Checklist

  • I ran the checks relevant to this PR — built the project (dist/ compiled) and verified the --card-text flow manually end-to-end.
  • I updated tests or docs if needed — N/A: no unit/e2e test currently covers currentComposerMediaCount; DOM detection needs a live XHS session. (Happy to add a regression test if a headless harness is available.)
  • I included output or screenshots when useful — error message + manual verification captured above.

Documentation (if adding/modifying an adapter)

  • Not applicable — this is a bug fix in an existing adapter. No new command, no discoverability change, no new doc page, so the adapter-doc checklist items are intentionally left unchecked.

Screenshots / Output

Before

expected at least 1 visible media item(s), got 0

After (draft publish with --card-text)

  • Cards generated by XHS native text-to-image
  • Publisher proceeds past the media-count gate and creates the draft successfully

opencli's currentComposerMediaCount() picked the composer root via
titleEl.closest('form, [class*=publish], ...'), but Xiaohongshu's new
React DOM renders the image/card editor in a different subtree, so the
matched root never contained the generated media and the count was
always 0. That broke the native '--card-text' (文字生成图片) flow with
'expected at least N visible media item(s), got 0'.

- Use document.body as the scan root so generated cards are found.
- Add 'image, svg' to the media selector for completeness.

This is the maintained fork of @jackwener/opencli (liuxinyea/OpenCLI).
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