Repository navigation
feat(nextjs,tanstack): v8-only StudioBridge and DecoDocument, Cypress-safe "." shortcut - #806
Merged
Merged
Conversation
…-safe "." shortcut @decocms/nextjs's StudioBridge and @decocms/tanstack's DecoDocument / DecoPreview no longer render v7's framed handler (scrollToComponent, editor::rerender), whose inline script compares window.self with window.top. Cypress's modifyObstructiveCode rewrites that comparison in the proxied HTML, including inside the RSC payload that carries the script, so a Next.js page's Flight stream comes out one byte off and every page throws "Connection closed.". Both now render the v8 Studio channel (exact studioOrigins()) plus v7's "." edit shortcut as a script of its own (studioShortcut.ts, the same file in both bindings) that matches none of Cypress's rewrite regexes and keeps the shadow-root field check. Props are unchanged. @decocms/blocks/preview is untouched. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
🎉 This PR is included in version 8.15.0 🎉 The release is available on:
Your semantic-release bot 📦🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Not merged — waiting for review.
Summary
@decocms/nextjs'sStudioBridgeand@decocms/tanstack'sDecoDocument/DecoPreviewbecome v8 only:scrollToComponent,editor::rerender, the coreSTUDIO_BRIDGE_SCRIPTbranch guarded bywindow.self!==window.top) is no longer rendered. Studio's v8 editor reaches the page through the Studio channel only.StudioChannelfrom@decocms/blocks/previewwith the exactstudioOrigins()(option, elseDECO_STUDIO_ORIGIN, elsestudio.decocms.com+studio-stg.decocms.com), as before./choose-editor), as a separate inline script,studioShortcut.ts. It is off in a frame. It reads the frame state asvar w=window,p=w.parent; if(p!==w)return, which none of Cypress's frame-busting regexes match. It keeps the samedata-deco-studio-bridge/data-site/data-shortcut/data-path-template/data-page-idattributes and theStudioPagemarker lookup.Why: Cypress's
modifyObstructiveCoderewriteswindow.self!==window.topeverywhere in proxied HTML. That includes the RSC payload, where a Server Component's inline script travels as a length-prefixed text row. The row comes out one byte longer than its prefix, React's Flight client misreads the stream, and every page throws an uncaughtConnection closed.. This broke the osklen Cypress suite on deco-sites/osklenbr-faststore#1388, which is why that site renderedStudioChannelby hand.Decisions taken
StudioBridgeProps(nextjs) keepssite,editShortcut,page,nonceandstudioOrigins, and all of them still do something, so nothing needed a@deprecatedno-op.DecoDocumentProps/DecoPreviewPropsare unchanged.StudioBridgePropsis now its own interface with the same fields, no longerOmit<core StudioBridgeProps, "trustedOrigins">.@decocms/blocks/previewis untouched. ItsStudioBridge(v7 handler) stays exported for anyone who renders it directly. The shortcut script lives in each binding (packages/nextjs/src/studioShortcut.tsandpackages/tanstack/src/studioShortcut.ts), following the existing per-bindingstudio.tscopies.tests/studio-shortcut.test.tsasserts the two files are byte-identical.e.composedPath()[0], the shadow-root fix of fix(blocks): keep the "." shortcut out of fields inside a shadow root #784, so the binding path gets it whether or not fix(blocks): keep the "." shortcut out of fields inside a shadow root #784 lands first. fix(blocks): keep the "." shortcut out of fields inside a shadow root #784 still matters for the coreStudioBridge.__decoStudioShortcut).feat:(minor).How to spike it
On a Next.js site: render
<StudioBridge site="…" />and curl a page. It should containdata-deco-studio-channelanddata-shortcut, and noscrollToComponentand nowindow.self!==window.top. Load the page through Cypress (or the regex rewrite) and confirm there is no "Connection closed.". Pressing "." outside a frame goes tostudio.decocms.com/choose-editor?.... In Studio's frame the editor still getsdeco:readyand loads its modules.Evidence
tests/studio-shortcut.test.ts(16 tests) applies Cypress's own regexes frompackages/rewriter/lib/regex-rewriter.ts, in both modes (first-party, andmodifyObstructiveThirdPartyCode's expanded ones), to the nextjsStudioBridgemarkup and to the tanstack shortcut + channel markup. The output is byte-identical. As a control, the same rewrite does change the core v7STUDIO_BRIDGE_SCRIPT.choose-editorwith site/domain/path/pathTemplate/pageId; a plain "." and Ctrl+Shift+E are handled; the shortcut is inactive in a frame;editShortcut={false}turns it off; typing in an input, and in an input inside an open shadow root, is left alone; and aStudioPagemarker wins at keypress time.react.test.tsxchecks thatDecoDocument's Studio scripts are exactly the shortcut and the channel.components.test.tsxchecks the same forStudioBridge, with nodata-originsand no v7 handler.bun run typecheck,bun run lint,bun run lint:unused,skills:check,skills:readme:check,bun run buildand thenextjs-binding-smokebuild + smoke all pass. 233 tests pass acrosspackages/nextjs,packages/tanstack/src/react,packages/blocks/src/v8/previewandtests/studio-shortcut.test.ts.feat/studio-bridge-bumpwas built withnext build+next starton packed 8.15.0 tarballs of this branch. Home,/about-usand a PLP served markup that all 9 Cypress rewriter regexes leave alone. The Cypress-rewrite Playwright harness showed no page errors (no "Connection closed."). A fake Studio parent at studio.decocms.com gotdeco:ready+deco:loadedx2, and the wireframe selected and outlined each section and ran html-swap. "." unframed went tochoose-editor?site=osklenbr-faststore-studio&…. "." in a field typed a ".". In a frame, "." did nothing.Known limitations
scrollToComponent/editor::rerenderto a v8 site gets no answer. v8 Studio doesn't send them: it loads its wireframe and html-swap modules through the channel.🤖 Generated with Claude Code
Summary by cubic
Makes
@decocms/nextjs'sStudioBridgeand@decocms/tanstack'sDecoDocument/DecoPreviewv8-only: v7's framed handler is gone, and the "." edit shortcut is now a script of its own that never compares the window withtoporparent. Cypress'smodifyObstructiveCoderewrites such comparisons in proxied HTML; when the RSC payload carries the script, the rewrite changes its length and every page fails with an uncaught "Connection closed.".Details
@decocms/blocks/previewis untouched and still exports its v7StudioBridge.scrollToComponentoreditor::rerendergets no answer; v8 Studio reaches the page through the channel only.Written for commit c5716dd. Summary will update on new commits.