Skip to content

Fix inline HTML preview theming#1042

Merged
SuuBro merged 26 commits into
masterfrom
goal/fix-inline-htm-a58ba482
Jul 23, 2026
Merged

Fix inline HTML preview theming#1042
SuuBro merged 26 commits into
masterfrom
goal/fix-inline-htm-a58ba482

Conversation

@SuuBro

@SuuBro SuuBro commented Jul 22, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • inject the shared live theme bridge into completed and streaming inline HTML previews without the side-panel swipe bridge
  • preserve authored HTML semantics with parser-backed early injection, idempotent fail-open behavior, and host-token preview chrome
  • cover write/edit, streaming transitions, light/dark palette changes, real Vite development loading, and clean packaged runtime loading
  • document inline, embedded-panel, and standalone snapshot theme contracts

Verification

  • build, type-check, unit, browser, E2E, regression, quality, security, and QA workflow checks passed
  • focused source-Vite and packed-tarball browser smokes passed

🤖 Generated with Bobbit

SuuBro and others added 23 commits July 22, 2026 21:25
Co-authored-by: bobbit-ai <bobbit@bobbit.ai>
Co-authored-by: bobbit-ai <bobbit@bobbit.ai>
Co-authored-by: bobbit-ai <bobbit@bobbit.ai>
Co-authored-by: bobbit-ai <bobbit@bobbit.ai>
Co-authored-by: bobbit-ai <bobbit@bobbit.ai>
Co-authored-by: bobbit-ai <bobbit@bobbit.ai>
Co-authored-by: bobbit-ai <bobbit@bobbit.ai>
Co-authored-by: bobbit-ai <bobbit@bobbit.ai>
Co-authored-by: bobbit-ai <bobbit@bobbit.ai>
Co-authored-by: bobbit-ai <bobbit@bobbit.ai>
Co-authored-by: bobbit-ai <bobbit@bobbit.ai>
Co-authored-by: bobbit-ai <bobbit@bobbit.ai>
Co-authored-by: bobbit-ai <bobbit@bobbit.ai>
@greptile-apps

greptile-apps Bot commented Jul 22, 2026

Copy link
Copy Markdown

Greptile Summary

This PR wires the shared PREVIEW_THEME_BRIDGE script into inline HTML previews (both the completed srcdoc declarative binding and the streaming document.write path) via a new prepareInlineHtml utility, and replaces hardcoded dark-theme chrome colors with CSS custom properties.

  • prepare-inline-html.ts uses DOMParser for safe, tag-shape-agnostic injection of the canonical bridge as the first <head> element; idempotency is verified by content-matching the marked script so authored collisions don't block re-injection; all parser/serializer failures are fail-open.
  • preview-bridge-scripts.ts gains install-state tracking in window[installKey] (disconnects stale observers across document.open() rewrites) and wraps sync() in a try/catch for transient cross-origin access failures.
  • Six new test files land in tests2/ covering VM runtime semantics, DOM lifecycle, and real-browser (source Vite + packaged tarball) E2E smoke paths.

Confidence Score: 5/5

Safe to merge — the change adds a well-guarded preparation layer and observer lifecycle management with no regressions on existing paths.

The new prepareInlineHtml utility is fully fail-open and the test suite covers duplicate installation, hostile authored syntax, streaming transitions, document.open() observer cleanup, and both source-Vite and packaged tarball runtimes.

No files require special attention.

Important Files Changed

Filename Overview
src/ui/tools/renderers/prepare-inline-html.ts New module using DOMParser to inject PREVIEW_THEME_BRIDGE as the first head element, with content-verified idempotency detection and fail-open semantics.
src/shared/preview-bridge-scripts.ts Bridge now tracks install state in window[installKey], disconnects stale observers on document.open() rewrites, and wraps sync() in a try/catch for transient cross-origin failures.
src/ui/tools/renderers/HtmlRenderer.ts Threads prepared HTML through both the completed srcdoc binding and the streaming document.write path; replaces hardcoded chrome colors with CSS custom properties and color-mix().
tests2/core/preview-theme-bridge-runtime.test.ts VM-based unit tests cover observer deduplication, token/palette/font mirroring, live host mutations, and all fail-open seams.
tests2/dom/inline-html-renderer-lifecycle.test.ts Comprehensive DOM lifecycle coverage: hostile authored syntax, preparation idempotency, streaming debounce and completion, chrome theming, and WriteRenderer/EditRenderer delegation.
tests2/browser/fixtures/inline-html-theme-source.spec.ts Playwright fixture spec validating parse-time and live token resolution, streaming transitions, EditRenderer delegation, and absence of swipe forwarding.
tests2/browser/e2e/packaged-inline-html-theme.spec.ts E2E tarball-consumer smoke verifying theme bridge presence and live token resolution in the packaged UI bundle.
tests2/browser/e2e/source-vite-inline-html-theme.spec.ts E2E spec validating parse-time theme capture and live token sync against a Vite dev-server path with an isolated mock gateway.

Reviews (3): Last reviewed commit: "Merge remote-tracking branch 'origin/mas..." | Re-trigger Greptile

Comment thread src/ui/tools/renderers/prepare-inline-html.ts Outdated
import { PREVIEW_THEME_BRIDGE } from "../../src/shared/preview-bridge-scripts.js";

function bridgeProgram(): string {
const match = PREVIEW_THEME_BRIDGE.match(/^<script(?:\s[^>]*)?>([\s\S]*)<\/script>$/i);
return swipeMessages.slice();
}

window.addEventListener("message", (event) => {
const headers = { Authorization: `Bearer ${token}`, "Content-Type": "application/json" };
const projectResponse = await fetch(`${baseUrl}/api/projects`, {
method: "POST",
headers,
if (!project.id) throw new Error("packed project creation returned no id");
const sessionResponse = await fetch(`${baseUrl}/api/sessions`, {
method: "POST",
headers,
ws.close();
reject(new Error(`packaged session prompt timed out; messages=${JSON.stringify(messages.slice(-12))}`));
}, 30_000);
ws.on("open", () => ws.send(JSON.stringify({ type: "auth", token })));
const token = await readToken(join(tempRoot, "secrets"));
const preferenceResponse = await fetch(`${gatewayBaseUrl}/api/preferences`, {
method: "PUT",
headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
@SuuBro

SuuBro commented Jul 23, 2026

Copy link
Copy Markdown
Collaborator Author

Addressed the Greptile P2 in commit 0fb13d4.

  • Added module-scoped bounded LRU memoization shared across inline cards (rather than a single-value instance cache, since HtmlRenderer is shared).
  • Reuses a lazily parsed, realm-neutral canonical bridge descriptor.
  • Bounds entry count and retained input/output size; oversized and fail-open results are not cached.
  • Added deterministic parser-count, changed-input, eviction, size-limit, oversized, and fail-open recovery coverage.

Focused DOM/reproducer/type-check tests and the full implementation workflow pass.

@SuuBro

SuuBro commented Jul 23, 2026

Copy link
Copy Markdown
Collaborator Author

@greptileai

@SuuBro
SuuBro merged commit b3d406a into master Jul 23, 2026
6 checks passed
@SuuBro
SuuBro deleted the goal/fix-inline-htm-a58ba482 branch July 23, 2026 08:18
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