Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
B
bit-pm
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
燕伟桐
bit-pm
Commits
e488df24
Unverified
提交
e488df24
authored
5月 02, 2025
作者:
Will Chen
提交者:
GitHub
5月 02, 2025
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Hook into vite error overlay and show fixable in dyad (#71)
上级
c069599d
隐藏空白字符变更
内嵌
并排
正在显示
2 个修改的文件
包含
121 行增加
和
2 行删除
+121
-2
dyad-shim.js
scaffold/dyad-shim.js
+82
-0
PreviewIframe.tsx
src/components/preview_panel/PreviewIframe.tsx
+39
-2
没有找到文件。
scaffold/dyad-shim.js
浏览文件 @
e488df24
...
@@ -182,4 +182,86 @@
...
@@ -182,4 +182,86 @@
}
}
sendSourcemappedErrorToParent
(
error
,
"unhandled-rejection"
);
sendSourcemappedErrorToParent
(
error
,
"unhandled-rejection"
);
});
});
(
function
watchForViteErrorOverlay
()
{
// --- Configuration for the observer ---
// We only care about direct children being added or removed.
const
config
=
{
childList
:
true
,
// Observe additions/removals of child nodes
subtree
:
false
,
// IMPORTANT: Do *not* observe descendants, only direct children
};
// --- Callback function executed when mutations are observed ---
const
observerCallback
=
function
(
mutationsList
)
{
// Iterate through all mutations that just occurred
for
(
const
mutation
of
mutationsList
)
{
// We are only interested in nodes that were added
if
(
mutation
.
type
===
"childList"
&&
mutation
.
addedNodes
.
length
>
0
)
{
// Check each added node
for
(
const
node
of
mutation
.
addedNodes
)
{
// Check if it's an ELEMENT_NODE (type 1) and has the correct ID
if
(
node
.
nodeType
===
Node
.
ELEMENT_NODE
&&
node
.
tagName
===
"vite-error-overlay"
.
toUpperCase
()
)
{
reportViteErrorOverlay
(
node
);
}
}
}
}
};
function
reportViteErrorOverlay
(
node
)
{
console
.
log
(
`Detected vite error overlay:
${
node
}
`
);
try
{
window
.
parent
.
postMessage
(
{
type
:
"build-error-report"
,
payload
:
{
message
:
node
.
shadowRoot
.
querySelector
(
".message"
).
textContent
,
file
:
node
.
shadowRoot
.
querySelector
(
".file"
).
textContent
,
frame
:
node
.
shadowRoot
.
querySelector
(
".frame"
).
textContent
,
},
},
PARENT_TARGET_ORIGIN
);
}
catch
(
error
)
{
console
.
error
(
"Could not report vite error overlay"
,
error
);
}
}
// --- Wait for DOM ready logic ---
if
(
document
.
readyState
===
"loading"
)
{
// The document is still loading, wait for DOMContentLoaded
document
.
addEventListener
(
"DOMContentLoaded"
,
()
=>
{
if
(
!
document
.
body
)
{
console
.
error
(
"document.body does not exist - something very weird happened"
);
return
;
}
const
node
=
document
.
body
.
querySelector
(
"vite-error-overlay"
);
if
(
node
)
{
reportViteErrorOverlay
(
node
);
}
const
observer
=
new
MutationObserver
(
observerCallback
);
observer
.
observe
(
document
.
body
,
config
);
});
console
.
log
(
"Document loading, waiting for DOMContentLoaded to set up observer."
);
}
else
{
if
(
!
document
.
body
)
{
console
.
error
(
"document.body does not exist - something very weird happened"
);
return
;
}
// The DOM is already interactive or complete
console
.
log
(
"DOM already ready, setting up observer immediately."
);
const
observer
=
new
MutationObserver
(
observerCallback
);
observer
.
observe
(
document
.
body
,
config
);
}
})();
})();
})();
src/components/preview_panel/PreviewIframe.tsx
浏览文件 @
e488df24
...
@@ -16,6 +16,7 @@ import {
...
@@ -16,6 +16,7 @@ import {
Sparkles
,
Sparkles
,
ChevronDown
,
ChevronDown
,
Lightbulb
,
Lightbulb
,
ChevronRight
,
}
from
"lucide-react"
;
}
from
"lucide-react"
;
import
{
selectedChatIdAtom
}
from
"@/atoms/chatAtoms"
;
import
{
selectedChatIdAtom
}
from
"@/atoms/chatAtoms"
;
import
{
IpcClient
}
from
"@/ipc/ipc_client"
;
import
{
IpcClient
}
from
"@/ipc/ipc_client"
;
...
@@ -38,8 +39,19 @@ interface ErrorBannerProps {
...
@@ -38,8 +39,19 @@ interface ErrorBannerProps {
}
}
const
ErrorBanner
=
({
error
,
onDismiss
,
onAIFix
}:
ErrorBannerProps
)
=>
{
const
ErrorBanner
=
({
error
,
onDismiss
,
onAIFix
}:
ErrorBannerProps
)
=>
{
const
[
isCollapsed
,
setIsCollapsed
]
=
useState
(
true
);
if
(
!
error
)
return
null
;
if
(
!
error
)
return
null
;
const
getTruncatedError
=
()
=>
{
const
firstLine
=
error
.
split
(
"
\
n"
)[
0
];
const
snippetLength
=
200
;
const
snippet
=
error
.
substring
(
0
,
snippetLength
);
return
firstLine
.
length
<
snippet
.
length
?
firstLine
:
snippet
+
(
snippet
.
length
===
snippetLength
?
"..."
:
""
);
};
return
(
return
(
<
div
className=
"absolute top-2 left-2 right-2 z-10 bg-red-50 dark:bg-red-950 border border-red-200 dark:border-red-800 rounded-md shadow-sm p-2"
>
<
div
className=
"absolute top-2 left-2 right-2 z-10 bg-red-50 dark:bg-red-950 border border-red-200 dark:border-red-800 rounded-md shadow-sm p-2"
>
{
/* Close button in top left */
}
{
/* Close button in top left */
}
...
@@ -52,8 +64,17 @@ const ErrorBanner = ({ error, onDismiss, onAIFix }: ErrorBannerProps) => {
...
@@ -52,8 +64,17 @@ const ErrorBanner = ({ error, onDismiss, onAIFix }: ErrorBannerProps) => {
{
/* Error message in the middle */
}
{
/* Error message in the middle */
}
<
div
className=
"px-6 py-1 text-sm"
>
<
div
className=
"px-6 py-1 text-sm"
>
<
div
className=
"text-red-700 dark:text-red-300 text-wrap font-mono whitespace-pre-wrap break-words text-xs"
>
<
div
{
error
}
className=
"text-red-700 dark:text-red-300 text-wrap font-mono whitespace-pre-wrap break-words text-xs cursor-pointer flex gap-1 items-start"
onClick=
{
()
=>
setIsCollapsed
(
!
isCollapsed
)
}
>
<
ChevronRight
size=
{
14
}
className=
{
`mt-0.5 transform transition-transform ${
isCollapsed ? "" : "rotate-90"
}`
}
/>
{
isCollapsed
?
getTruncatedError
()
:
error
}
</
div
>
</
div
>
</
div
>
</
div
>
...
@@ -162,6 +183,7 @@ export const PreviewIframe = ({ loading }: { loading: boolean }) => {
...
@@ -162,6 +183,7 @@ export const PreviewIframe = ({ loading }: { loading: boolean }) => {
|
"window-error"
|
"window-error"
|
"unhandled-rejection"
|
"unhandled-rejection"
|
"iframe-sourcemapped-error"
|
"iframe-sourcemapped-error"
|
"build-error-report"
|
"pushState"
|
"pushState"
|
"replaceState"
;
|
"replaceState"
;
payload
?:
{
payload
?:
{
...
@@ -169,6 +191,8 @@ export const PreviewIframe = ({ loading }: { loading: boolean }) => {
...
@@ -169,6 +191,8 @@ export const PreviewIframe = ({ loading }: { loading: boolean }) => {
stack
?:
string
;
stack
?:
string
;
reason
?:
string
;
reason
?:
string
;
newUrl
?:
string
;
newUrl
?:
string
;
file
?:
string
;
frame
?:
string
;
};
};
};
};
...
@@ -195,6 +219,19 @@ export const PreviewIframe = ({ loading }: { loading: boolean }) => {
...
@@ -195,6 +219,19 @@ export const PreviewIframe = ({ loading }: { loading: boolean }) => {
timestamp
:
Date
.
now
(),
timestamp
:
Date
.
now
(),
},
},
]);
]);
}
else
if
(
type
===
"build-error-report"
)
{
console
.
debug
(
`Build error report:
${
payload
}
`
);
const
errorMessage
=
`
${
payload
?.
message
}
from
file
$
{
payload
?.
file
}.
\
n
\
nSource
code
:
\
n$
{
payload
?.
frame
}
`;
setErrorMessage(errorMessage);
setAppOutput((prev) => [
...prev,
{
message: `
Build
error
report
:
$
{
JSON
.
stringify
(
payload
)}
`,
type: "client-error",
appId: selectedAppId!,
timestamp: Date.now(),
},
]);
} else if (type === "pushState" || type === "replaceState") {
} else if (type === "pushState" || type === "replaceState") {
console.debug(`
Navigation
event
:
$
{
type
}
`
,
payload
);
console.debug(`
Navigation
event
:
$
{
type
}
`
,
payload
);
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论