-
Notifications
You must be signed in to change notification settings - Fork 8
feat(playground): support hash sync when embedded in iframe #298
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(playground): support hash sync when embedded in iframe #298
Conversation
- Post playground-hash-change to parent when URL hash changes in iframe - Listen for playground-parent-url from host to deserialize hash and sync state - Sync TinyRobot version from import-map when loading from hash - Restrict postMessage to allowed origins (localhost, playground.opentiny.design) - Drop __TINY_ROBOT_VERSION__; use "latest" and derive version from hash/import-map - getVersions returns lastVersion; header shows "latest (x.y.z)" when applicable
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. WalkthroughRemove build-time version injection; add runtime sync of TinyRobot version from the playground import-map, iframe host messaging with origin validation and URL/hash persistence, and surface the latest TinyRobot release alongside available versions. Changes
Sequence DiagramsequenceDiagram
participant Host
participant App as App.vue
participant Store as Store (files / import-map.json)
participant VersionAPI as Version API
participant Header as Header.vue
Host->>App: postMessage(hash, origin)
App->>App: onHostMessage() / isAllowedMessageOrigin(origin)
App->>App: Deserialize hash → update Store
App->>Store: Read `import-map.json` (`@opentiny/tiny-robot` URL)
App->>App: syncTinyRobotVersionFromImportMap()
App->>VersionAPI: getVersions(pkg)
VersionAPI-->>App: { versions[], lastVersion }
App->>App: set tinyRobotLatestVersion, update state
App->>App: triggerFullRecompile()
App->>Host: postMessage(newHash, targetOrigin)
App->>Header: pass tiny-robot-version, tiny-robot-versions, tiny-robot-latest-version
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@packages/playground/src/App.vue`:
- Around line 60-67: The outgoing postMessage call in the watchEffect block
leaks state by using '*' as the target origin; update the code to validate
window.parent.origin (or derive a safe origin from document.referrer) against
the ALLOWED_ORIGINS via the isAllowedMessageOrigin function and only call
window.parent.postMessage({ type: 'playground-hash-change', ... }, parentOrigin)
when the parentOrigin is allowed; if the origin is not allowed, skip posting.
Move the ALLOWED_ORIGINS and isAllowedMessageOrigin definitions above the
watchEffect so they can be reused.
📦 Package Previewpnpm add https://pkg.pr.new/opentiny/tiny-robot/@opentiny/tiny-robot@15af55c pnpm add https://pkg.pr.new/opentiny/tiny-robot/@opentiny/tiny-robot-kit@15af55c pnpm add https://pkg.pr.new/opentiny/tiny-robot/@opentiny/tiny-robot-svgs@15af55c commit: 15af55c |
- Implement getParentOrigin to derive the parent page's origin using document.referrer - Update postMessage to use the derived target origin for improved security - Consolidate origin validation logic for better maintainability
- Eliminate onHostMessage function and associated event listeners to streamline code - Retain essential lifecycle hooks and imports for component functionality
- Introduce IconShare component for sharing URLs - Implement getShareUrl function to generate shareable links based on iframe context - Add handleShareClick method to copy share URL to clipboard with user notification - Create Notification component for displaying messages with auto-hide functionality - Develop notify utility function to programmatically show notifications
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@packages/playground/src/components/Notification.vue`:
- Around line 21-33: The mounted hook schedules a requestAnimationFrame and two
setTimeouts (in onMounted) but never clears them, so add cleanup in an
onUnmounted handler: store the requestAnimationFrame id and both timeout ids
(the show rAF, the auto-hide timeout, and the inner emit timeout) as local
refs/vars, call cancelAnimationFrame for the rAF id and clearTimeout for both
timeouts inside onUnmounted, and guard the emit('close') callback if needed to
avoid emitting after unmount; update the handlers that use visible and emit (the
requestAnimationFrame callback, the outer setTimeout using props.duration, and
the inner setTimeout that calls emit('close')) to use those stored ids so they
can be cleared on unmount.
In `@packages/playground/src/Header.vue`:
- Around line 48-62: The catch block in handleShareClick currently does nothing,
so when navigator.clipboard.writeText fails users get no feedback; update
handleShareClick to implement the promised fallback: after catching the error,
present the URL to the user (e.g., via window.prompt or a visible modal) so they
can manually copy it and call notify to inform them of the fallback action; use
getShareUrl() to fetch the URL, include the error message in console.error for
debugging, and ensure notify('链接已复制到剪贴板') is replaced or supplemented with a
different message like notify('请手动复制链接') when using the fallback.
🧹 Nitpick comments (1)
packages/playground/src/Header.vue (1)
23-45: Hardcoded pathname may require future maintenance.The pathname
/tiny-robot.htmlis hardcoded at line 35. If the parent page URL structure changes, this will need to be updated. Consider extracting this to a constant or making it configurable if flexibility is needed.
- Update getShareUrl function to handle iframe and non-iframe contexts more clearly - Simplify error handling in getShareUrl - Enhance Notification component to manage animation frames and timers for better performance - Ensure cleanup of timers on component unmount to prevent memory leaks
🧹 Preview Cleaned UpThe preview deployment has been removed. |

PR:Playground iframe 下的 hash 同步能力
Related to opentiny/playground#21
功能概述
当 Playground 以 iframe 方式嵌入时,支持将自身的 URL hash 变化同步给父页面,保证地址栏状态与 iframe 内的示例状态尽量保持一致(便于分享与还原)。
通信方式
postMessagewindow.self !== window.top(运行在 iframe 中)时开启通信document.referrer推导父页面origin,并通过白名单校验,仅在受信任来源下发送消息事件约定
playground-hash-change(iframe → 父页面)type:'playground-hash-change'url: iframe 当前完整 URLhash: 序列化后的 hash(如#code/...)history.replaceState或路由更新,将父页面地址栏同步为最新的 Playground 状态;安全策略
发送
playground-hash-change事件前,会基于以下策略决定是否发送以及发送目标origin:document.referrer推导父页面 URL,并取其originorigin满足以下任一条件时才发送:https://playground.opentiny.designlocalhost(任意端口)127.0.0.1(任意端口)Summary by CodeRabbit
New Features
Improvements