Skip to content

Render Gemini streaming responses without replacing source DOM - #1

Merged
kangjoseph90 merged 5 commits into
mainfrom
feat/non-destructive-streaming
Oct 12, 2026
Merged

kangjoseph90 merged 5 commits into
mainfrom
feat/non-destructive-streaming

Conversation

@kangjoseph90

@kangjoseph90 kangjoseph90 commented Oct 12, 2026 •

Copy link
Copy Markdown
Owner

Streaming currently skips parser fixes because replacing a Gemini paragraph's innerHTML removes the Text nodes its renderer owns. Removing that guard can leave stale output or append cumulative text next to the parsed prefix. Initial-disabled sessions also miss later toggle messages.

Render each supported text block in an extension-owned shadow tree while keeping its light-DOM children intact. A clipped original slot preserves native text readers; disabling switches to a plain slot, cancels queued work and restores native display. Re-enabling reads the current source, including updates made while disabled. Streaming and completed responses now share one renderer.

  • Coalesce ordinary token updates in a fixed 40 ms window. Process new hosts/structural finalization before the next paint, recognize Gemini path/index metadata and inert native formula expressions, and reconcile the preview to retain unchanged text/formula nodes. Finished tokens keep the same streaming fonts/styles. Inline code includes a visible themed background, spacing, and font inside the shadow tree; native code box styles survive disabling code repair. Rediscover replaced chat containers.
  • Use markdown-it's balanced inline tokens and KaTeX's DOM renderer with MathML; keep unfinished/invalid math literal and code/math opaque to other formatting. Repair punctuation-ended emphasis before Korean suffixes, preserve literal entity spellings, normalize code whitespace/backslashes, pair nested underline tags, support bracket LaTeX delimiters, and avoid matching adjacent dollar prices as formulas. Metadata-only spans can split one token.
  • Preserve native visibility, opacity, and explicit inline styles. Refresh copied styles when an ancestor inside the chat changes class/style.
  • Share the engine between the Chrome adapter and generated userscript, retain listeners while disabled, and propagate storage changes across tabs. Add a persistent userscript menu toggle.
  • Bundle KaTeX fonts and register their font faces at document scope. Share projection stylesheets, and hide disclaimers with removable CSS instead of deleting content.
  • Keep interactive/mixed-content blocks and bare td/th text native. Paragraphs/headings inside table cells remain eligible. Shadow roots cannot be detached; disabled supported hosts retain only a plain slot.

Validation: all 58 browser tests pass, including retained source identity, 500 cumulative updates, sustained streaming, 30 rapid toggles, feature/color reset, response/SPA replacement, native button handlers, layout, selection/accessibility, font loading and Trusted Types. Completion regressions verify first-frame mounting, retained inline/formula identity, and identical streaming/final fonts. Audit regressions cover Korean quoted emphasis, code backslashes/whitespace, literal entities, bracket math, nested underline with opaque content, prices, metadata-split tokens, hidden native text/math, and nested ancestor themes. An actual installed MV3 extension also passes popup/storage and initially-disabled cross-tab tests on an intercepted gemini.google.com fixture. Public-registry npm ci, generated-userscript consistency and git diff checks pass. CI runs the same suite.

Live Gemini DOM and the installed inline-code presentation were inspected. Native response-copy, virtualization, and auto-scroll remain only partially verified; automated tests do not submit prompts to live Gemini.

@kangjoseph90
kangjoseph90 marked this pull request as ready for review October 12, 2026 08:19
@kangjoseph90
kangjoseph90 merged commit ec38a69 into main Oct 12, 2026
2 checks passed
kangjoseph90 added a commit that referenced this pull request Oct 12, 2026
Render Gemini streaming responses without replacing source DOM
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.

2 participants