diff --git a/webview-ui/src/components/common/MermaidBlock.tsx b/webview-ui/src/components/common/MermaidBlock.tsx index 59132e4239..b3b34f7fea 100644 --- a/webview-ui/src/components/common/MermaidBlock.tsx +++ b/webview-ui/src/components/common/MermaidBlock.tsx @@ -3,6 +3,9 @@ import mermaid from "mermaid" import { useDebounceEffect } from "@src/utils/useDebounceEffect" import styled from "styled-components" import { vscode } from "@src/utils/vscode" +import { useAppTranslation } from "@src/i18n/TranslationContext" +import { useCopyToClipboard } from "@src/utils/clipboard" +import CodeBlock from "./CodeBlock" const MERMAID_THEME = { background: "#1e1e1e", // VS Code dark theme background @@ -81,10 +84,15 @@ interface MermaidBlockProps { export default function MermaidBlock({ code }: MermaidBlockProps) { const containerRef = useRef(null) const [isLoading, setIsLoading] = useState(false) + const [error, setError] = useState(null) + const [isErrorExpanded, setIsErrorExpanded] = useState(false) + const { showCopyFeedback, copyWithFeedback } = useCopyToClipboard() + const { t } = useAppTranslation() // 1) Whenever `code` changes, mark that we need to re-render a new chart useEffect(() => { setIsLoading(true) + setError(null) }, [code]) // 2) Debounce the actual parse/render @@ -93,12 +101,10 @@ export default function MermaidBlock({ code }: MermaidBlockProps) { if (containerRef.current) { containerRef.current.innerHTML = "" } + mermaid - .parse(code, { suppressErrors: true }) - .then((isValid) => { - if (!isValid) { - throw new Error("Invalid or incomplete Mermaid code") - } + .parse(code) + .then(() => { const id = `mermaid-${Math.random().toString(36).substring(2)}` return mermaid.render(id, code) }) @@ -109,7 +115,7 @@ export default function MermaidBlock({ code }: MermaidBlockProps) { }) .catch((err) => { console.warn("Mermaid parse/render failed:", err) - containerRef.current!.innerHTML = code.replace(//g, ">") + setError(err.message || "Failed to render Mermaid diagram") }) .finally(() => { setIsLoading(false) @@ -139,12 +145,71 @@ export default function MermaidBlock({ code }: MermaidBlockProps) { } } + // Copy functionality handled directly through the copyWithFeedback utility + return ( - {isLoading && Generating mermaid diagram...} + {isLoading && {t("common:mermaid.loading")}} - {/* The container for the final or raw code. */} - + {error ? ( +
+
setIsErrorExpanded(!isErrorExpanded)}> +
+ + {t("common:mermaid.render_error")} +
+
+ { + e.stopPropagation() + copyWithFeedback(code, e) + }}> + + + +
+
+ {isErrorExpanded && ( +
+
+ {error} +
+ +
+ )} +
+ ) : ( + + )}
) } @@ -212,6 +277,23 @@ const LoadingMessage = styled.div` font-size: 0.9em; ` +const CopyButton = styled.button` + padding: 3px; + height: 24px; + margin-right: 4px; + color: var(--vscode-editor-foreground); + display: flex; + align-items: center; + justify-content: center; + background: transparent; + border: none; + cursor: pointer; + + &:hover { + opacity: 0.8; + } +` + interface SvgContainerProps { $isLoading: boolean } diff --git a/webview-ui/src/i18n/locales/ca/common.json b/webview-ui/src/i18n/locales/ca/common.json index c6a797f7c6..8e95450cc4 100644 --- a/webview-ui/src/i18n/locales/ca/common.json +++ b/webview-ui/src/i18n/locales/ca/common.json @@ -6,5 +6,9 @@ }, "ui": { "search_placeholder": "Cerca..." + }, + "mermaid": { + "loading": "Generant diagrama mermaid...", + "render_error": "No es pot renderitzar el diagrama" } } diff --git a/webview-ui/src/i18n/locales/de/common.json b/webview-ui/src/i18n/locales/de/common.json index 62056d8d53..c5b7172efe 100644 --- a/webview-ui/src/i18n/locales/de/common.json +++ b/webview-ui/src/i18n/locales/de/common.json @@ -6,5 +6,9 @@ }, "ui": { "search_placeholder": "Suchen..." + }, + "mermaid": { + "loading": "Mermaid-Diagramm wird generiert...", + "render_error": "Diagramm kann nicht gerendert werden" } } diff --git a/webview-ui/src/i18n/locales/en/common.json b/webview-ui/src/i18n/locales/en/common.json index 757867bb2c..70a3c4a2d7 100644 --- a/webview-ui/src/i18n/locales/en/common.json +++ b/webview-ui/src/i18n/locales/en/common.json @@ -6,5 +6,9 @@ }, "ui": { "search_placeholder": "Search..." + }, + "mermaid": { + "loading": "Generating mermaid diagram...", + "render_error": "Unable to Render Diagram" } } diff --git a/webview-ui/src/i18n/locales/es/common.json b/webview-ui/src/i18n/locales/es/common.json index 0412376957..6d649eb926 100644 --- a/webview-ui/src/i18n/locales/es/common.json +++ b/webview-ui/src/i18n/locales/es/common.json @@ -6,5 +6,9 @@ }, "ui": { "search_placeholder": "Buscar..." + }, + "mermaid": { + "loading": "Generando diagrama mermaid...", + "render_error": "No se puede renderizar el diagrama" } } diff --git a/webview-ui/src/i18n/locales/fr/common.json b/webview-ui/src/i18n/locales/fr/common.json index fc7b0686df..caeb10851f 100644 --- a/webview-ui/src/i18n/locales/fr/common.json +++ b/webview-ui/src/i18n/locales/fr/common.json @@ -6,5 +6,9 @@ }, "ui": { "search_placeholder": "Rechercher..." + }, + "mermaid": { + "loading": "Génération du diagramme mermaid...", + "render_error": "Impossible de rendre le diagramme" } } diff --git a/webview-ui/src/i18n/locales/hi/common.json b/webview-ui/src/i18n/locales/hi/common.json index 5cf4876d32..de95d083b5 100644 --- a/webview-ui/src/i18n/locales/hi/common.json +++ b/webview-ui/src/i18n/locales/hi/common.json @@ -6,5 +6,9 @@ }, "ui": { "search_placeholder": "खोजें..." + }, + "mermaid": { + "loading": "मरमेड डायग्राम जनरेट हो रहा है...", + "render_error": "डायग्राम रेंडर नहीं किया जा सकता" } } diff --git a/webview-ui/src/i18n/locales/it/common.json b/webview-ui/src/i18n/locales/it/common.json index c6a797f7c6..c07023796a 100644 --- a/webview-ui/src/i18n/locales/it/common.json +++ b/webview-ui/src/i18n/locales/it/common.json @@ -6,5 +6,9 @@ }, "ui": { "search_placeholder": "Cerca..." + }, + "mermaid": { + "loading": "Generazione del diagramma mermaid...", + "render_error": "Impossibile renderizzare il diagramma" } } diff --git a/webview-ui/src/i18n/locales/ja/common.json b/webview-ui/src/i18n/locales/ja/common.json index 063ca02c31..c890f8baed 100644 --- a/webview-ui/src/i18n/locales/ja/common.json +++ b/webview-ui/src/i18n/locales/ja/common.json @@ -6,5 +6,9 @@ }, "ui": { "search_placeholder": "検索..." + }, + "mermaid": { + "loading": "Mermaidダイアグラムを生成中...", + "render_error": "ダイアグラムをレンダリングできません" } } diff --git a/webview-ui/src/i18n/locales/ko/common.json b/webview-ui/src/i18n/locales/ko/common.json index e4335f16ae..6996f6c387 100644 --- a/webview-ui/src/i18n/locales/ko/common.json +++ b/webview-ui/src/i18n/locales/ko/common.json @@ -6,5 +6,9 @@ }, "ui": { "search_placeholder": "검색..." + }, + "mermaid": { + "loading": "머메이드 다이어그램 생성 중...", + "render_error": "다이어그램을 렌더링할 수 없음" } } diff --git a/webview-ui/src/i18n/locales/pl/common.json b/webview-ui/src/i18n/locales/pl/common.json index 6163d7f10f..cf2da432f8 100644 --- a/webview-ui/src/i18n/locales/pl/common.json +++ b/webview-ui/src/i18n/locales/pl/common.json @@ -6,5 +6,9 @@ }, "ui": { "search_placeholder": "Szukaj..." + }, + "mermaid": { + "loading": "Generowanie diagramu mermaid...", + "render_error": "Nie można renderować diagramu" } } diff --git a/webview-ui/src/i18n/locales/pt-BR/common.json b/webview-ui/src/i18n/locales/pt-BR/common.json index 0a36a8483b..dd89eee333 100644 --- a/webview-ui/src/i18n/locales/pt-BR/common.json +++ b/webview-ui/src/i18n/locales/pt-BR/common.json @@ -6,5 +6,9 @@ }, "ui": { "search_placeholder": "Pesquisar..." + }, + "mermaid": { + "loading": "Gerando diagrama mermaid...", + "render_error": "Não foi possível renderizar o diagrama" } } diff --git a/webview-ui/src/i18n/locales/ru/common.json b/webview-ui/src/i18n/locales/ru/common.json index 25bc20927f..8327762467 100644 --- a/webview-ui/src/i18n/locales/ru/common.json +++ b/webview-ui/src/i18n/locales/ru/common.json @@ -6,5 +6,9 @@ }, "ui": { "search_placeholder": "Поиск..." + }, + "mermaid": { + "loading": "Создание диаграммы mermaid...", + "render_error": "Не удалось отобразить диаграмму" } } diff --git a/webview-ui/src/i18n/locales/tr/common.json b/webview-ui/src/i18n/locales/tr/common.json index a41fcaf6db..a66d24e02f 100644 --- a/webview-ui/src/i18n/locales/tr/common.json +++ b/webview-ui/src/i18n/locales/tr/common.json @@ -6,5 +6,9 @@ }, "ui": { "search_placeholder": "Ara..." + }, + "mermaid": { + "loading": "Mermaid diyagramı oluşturuluyor...", + "render_error": "Diyagram render edilemiyor" } } diff --git a/webview-ui/src/i18n/locales/vi/common.json b/webview-ui/src/i18n/locales/vi/common.json index 3ab6697795..19f8b8b801 100644 --- a/webview-ui/src/i18n/locales/vi/common.json +++ b/webview-ui/src/i18n/locales/vi/common.json @@ -6,5 +6,9 @@ }, "ui": { "search_placeholder": "Tìm kiếm..." + }, + "mermaid": { + "loading": "Đang tạo biểu đồ mermaid...", + "render_error": "Không thể hiển thị biểu đồ" } } diff --git a/webview-ui/src/i18n/locales/zh-CN/common.json b/webview-ui/src/i18n/locales/zh-CN/common.json index a437837df5..adaa86ec70 100644 --- a/webview-ui/src/i18n/locales/zh-CN/common.json +++ b/webview-ui/src/i18n/locales/zh-CN/common.json @@ -6,5 +6,9 @@ }, "ui": { "search_placeholder": "搜索..." + }, + "mermaid": { + "loading": "生成 Mermaid 图表中...", + "render_error": "无法渲染图表" } } diff --git a/webview-ui/src/i18n/locales/zh-TW/common.json b/webview-ui/src/i18n/locales/zh-TW/common.json index e8cc39e07e..12c42220dd 100644 --- a/webview-ui/src/i18n/locales/zh-TW/common.json +++ b/webview-ui/src/i18n/locales/zh-TW/common.json @@ -6,5 +6,9 @@ }, "ui": { "search_placeholder": "搜尋..." + }, + "mermaid": { + "loading": "產生 Mermaid 圖表中...", + "render_error": "無法渲染圖表" } }