Skip to content
This repository was archived by the owner on May 15, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 16 additions & 15 deletions webview-ui/src/components/common/CodeBlock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { useCopyToClipboard } from "@src/utils/clipboard"
import { getHighlighter, isLanguageLoaded, normalizeLanguage, ExtendedLanguage } from "@src/utils/highlighter"
import { bundledLanguages } from "shiki"
import type { ShikiTransformer } from "shiki"
import { ChevronDown, ChevronUp, WrapText, AlignJustify, Copy, Check } from "lucide-react"
import { useAppTranslation } from "@src/i18n/TranslationContext"
export const CODE_BLOCK_BG_COLOR = "var(--vscode-editor-background, --vscode-sideBar-background, rgb(30 30 30))"
export const WRAPPER_ALPHA = "cc" // 80% opacity
// Configuration constants
Expand Down Expand Up @@ -34,13 +36,6 @@ interface CodeBlockProps {
onLanguageChange?: (language: string) => void
}

const ButtonIcon = styled.span`
display: inline-block;
width: 1.2em;
text-align: center;
vertical-align: middle;
`

const CodeBlockButton = styled.button`
background: transparent;
border: none;
Expand All @@ -50,16 +45,23 @@ const CodeBlockButton = styled.button`
margin: 0 0px;
display: flex;
align-items: center;
justify-content: center;
opacity: 0.4;
border-radius: 3px;
pointer-events: var(--copy-button-events, none);
margin-left: 4px;
height: 24px;
width: 24px;

&:hover {
background: var(--vscode-toolbar-hoverBackground);
opacity: 1;
}

/* Style for Lucide icons to ensure consistent sizing and positioning */
svg {
display: block;
}
`

const CodeBlockButtonWrapper = styled.div`
Expand Down Expand Up @@ -229,6 +231,7 @@ const CodeBlock = memo(
const preRef = useRef<HTMLDivElement>(null)
const copyButtonWrapperRef = useRef<HTMLDivElement>(null)
const { showCopyFeedback, copyWithFeedback } = useCopyToClipboard()
const { t } = useAppTranslation()

// Update current language when prop changes, but only if user hasn't made a selection
useEffect(() => {
Expand Down Expand Up @@ -696,19 +699,17 @@ const CodeBlock = memo(
WINDOW_SHADE_SETTINGS.transitionDelayS * 1000 + 50,
)
}}
title={`${windowShade ? "Expand" : "Collapse"} code block`}>
<ButtonIcon style={{ fontSize: "16px" }}>{windowShade ? "⌄" : "⌃"}</ButtonIcon>
title={t(`chat:codeblock.tooltips.${windowShade ? "expand" : "collapse"}`)}>
{windowShade ? <ChevronDown size={16} /> : <ChevronUp size={16} />}
</CodeBlockButton>
)}
<CodeBlockButton
onClick={() => setWordWrap(!wordWrap)}
title={`${wordWrap ? "Disable" : "Enable"} word wrap`}>
<ButtonIcon style={{ fontSize: "16px", fontWeight: 900 }}>
{wordWrap ? "⟼" : "⤸"}
</ButtonIcon>
title={t(`chat:codeblock.tooltips.${wordWrap ? "disable_wrap" : "enable_wrap"}`)}>
{wordWrap ? <AlignJustify size={16} /> : <WrapText size={16} />}
</CodeBlockButton>
<CodeBlockButton onClick={handleCopy} title="Copy code">
<ButtonIcon className={`codicon codicon-${showCopyFeedback ? "check" : "copy"}`} />
<CodeBlockButton onClick={handleCopy} title={t("chat:codeblock.tooltips.copy_code")}>
{showCopyFeedback ? <Check size={16} /> : <Copy size={16} />}
</CodeBlockButton>
</CodeBlockButtonWrapper>
)}
Expand Down
33 changes: 33 additions & 0 deletions webview-ui/src/components/common/__tests__/CodeBlock.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,23 @@ import { render, screen, fireEvent, act } from "@testing-library/react"
import "@testing-library/jest-dom"
import CodeBlock from "../CodeBlock"

// Mock the translation context
jest.mock("../../../i18n/TranslationContext", () => ({
useAppTranslation: () => ({
t: (key: string) => {
// Return fixed English strings for tests
const translations: { [key: string]: string } = {
"chat:codeblock.tooltips.copy_code": "Copy code",
"chat:codeblock.tooltips.expand": "Expand code block",
"chat:codeblock.tooltips.collapse": "Collapse code block",
"chat:codeblock.tooltips.enable_wrap": "Enable word wrap",
"chat:codeblock.tooltips.disable_wrap": "Disable word wrap",
}
return translations[key] || key
},
}),
}))

// Mock shiki module
jest.mock("shiki", () => ({
bundledLanguages: {
Expand All @@ -11,6 +28,22 @@ jest.mock("shiki", () => ({
},
}))

// Mock all lucide-react icons with a proxy to handle any icon requested
jest.mock("lucide-react", () => {
return new Proxy(
{},
{
get: function (obj, prop) {
// Return a component factory for any icon that's requested
if (prop === "__esModule") {
return true
}
return () => <div data-testid={`${String(prop)}-icon`}>{String(prop)}</div>
},
},
)
})

// Mock the highlighter utility
jest.mock("../../../utils/highlighter", () => {
const mockHighlighter = {
Expand Down
9 changes: 9 additions & 0 deletions webview-ui/src/i18n/locales/ca/chat.json
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,15 @@
"close": "Tancar navegador"
}
},
"codeblock": {
"tooltips": {
"expand": "Expandir bloc de codi",
"collapse": "Contraure bloc de codi",
"enable_wrap": "Activar ajustament de línia",
"disable_wrap": "Desactivar ajustament de línia",
"copy_code": "Copiar codi"
}
},
"systemPromptWarning": "ADVERTÈNCIA: S'ha activat una substitució personalitzada d'instruccions del sistema. Això pot trencar greument la funcionalitat i causar un comportament impredictible.",
"shellIntegration": {
"title": "Advertència d'execució d'ordres",
Expand Down
9 changes: 9 additions & 0 deletions webview-ui/src/i18n/locales/de/chat.json
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,15 @@
"close": "Browser schließen"
}
},
"codeblock": {
"tooltips": {
"expand": "Code-Block erweitern",
"collapse": "Code-Block reduzieren",
"enable_wrap": "Zeilenumbruch aktivieren",
"disable_wrap": "Zeilenumbruch deaktivieren",
"copy_code": "Code kopieren"
}
},
"systemPromptWarning": "WARNUNG: Benutzerdefinierte Systemaufforderung aktiv. Dies kann die Funktionalität erheblich beeinträchtigen und zu unvorhersehbarem Verhalten führen.",
"shellIntegration": {
"title": "Befehlsausführungswarnung",
Expand Down
9 changes: 9 additions & 0 deletions webview-ui/src/i18n/locales/en/chat.json
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,15 @@
"close": "Close browser"
}
},
"codeblock": {
"tooltips": {
"expand": "Expand code block",
"collapse": "Collapse code block",
"enable_wrap": "Enable word wrap",
"disable_wrap": "Disable word wrap",
"copy_code": "Copy code"
}
},
"systemPromptWarning": "WARNING: Custom system prompt override active. This can severely break functionality and cause unpredictable behavior.",
"shellIntegration": {
"title": "Command Execution Warning",
Expand Down
9 changes: 9 additions & 0 deletions webview-ui/src/i18n/locales/es/chat.json
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,15 @@
"close": "Cerrar navegador"
}
},
"codeblock": {
"tooltips": {
"expand": "Expandir bloque de código",
"collapse": "Contraer bloque de código",
"enable_wrap": "Activar ajuste de línea",
"disable_wrap": "Desactivar ajuste de línea",
"copy_code": "Copiar código"
}
},
"systemPromptWarning": "ADVERTENCIA: Anulación de instrucciones del sistema personalizada activa. Esto puede romper gravemente la funcionalidad y causar un comportamiento impredecible.",
"shellIntegration": {
"title": "Advertencia de ejecución de comandos",
Expand Down
9 changes: 9 additions & 0 deletions webview-ui/src/i18n/locales/fr/chat.json
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,15 @@
"close": "Fermer le navigateur"
}
},
"codeblock": {
"tooltips": {
"expand": "Développer le bloc de code",
"collapse": "Réduire le bloc de code",
"enable_wrap": "Activer le retour à la ligne",
"disable_wrap": "Désactiver le retour à la ligne",
"copy_code": "Copier le code"
}
},
"systemPromptWarning": "AVERTISSEMENT : Remplacement d'instructions système personnalisées actif. Cela peut gravement perturber la fonctionnalité et provoquer un comportement imprévisible.",
"shellIntegration": {
"title": "Avertissement d'exécution de commande",
Expand Down
9 changes: 9 additions & 0 deletions webview-ui/src/i18n/locales/hi/chat.json
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,15 @@
"close": "ब्राउज़र बंद करें"
}
},
"codeblock": {
"tooltips": {
"expand": "कोड ब्लॉक का विस्तार करें",
"collapse": "कोड ब्लॉक को संकुचित करें",
"enable_wrap": "वर्ड रैप सक्षम करें",
"disable_wrap": "वर्ड रैप अक्षम करें",
"copy_code": "कोड कॉपी करें"
}
},
"systemPromptWarning": "चेतावनी: कस्टम सिस्टम प्रॉम्प्ट ओवरराइड सक्रिय है। यह कार्यक्षमता को गंभीर रूप से बाधित कर सकता है और अनियमित व्यवहार का कारण बन सकता है.",
"shellIntegration": {
"title": "कमांड निष्पादन चेतावनी",
Expand Down
9 changes: 9 additions & 0 deletions webview-ui/src/i18n/locales/it/chat.json
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,15 @@
"close": "Chiudi browser"
}
},
"codeblock": {
"tooltips": {
"expand": "Espandi blocco di codice",
"collapse": "Comprimi blocco di codice",
"enable_wrap": "Attiva a capo automatico",
"disable_wrap": "Disattiva a capo automatico",
"copy_code": "Copia codice"
}
},
"systemPromptWarning": "ATTENZIONE: Sovrascrittura personalizzata delle istruzioni di sistema attiva. Questo può compromettere gravemente le funzionalità e causare comportamenti imprevedibili.",
"shellIntegration": {
"title": "Avviso di esecuzione comando",
Expand Down
9 changes: 9 additions & 0 deletions webview-ui/src/i18n/locales/ja/chat.json
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,15 @@
"close": "ブラウザを閉じる"
}
},
"codeblock": {
"tooltips": {
"expand": "コードブロックを展開",
"collapse": "コードブロックを折りたたむ",
"enable_wrap": "折り返しを有効化",
"disable_wrap": "折り返しを無効化",
"copy_code": "コードをコピー"
}
},
"systemPromptWarning": "警告:カスタムシステムプロンプトの上書きが有効です。これにより機能が深刻に損なわれ、予測不可能な動作が発生する可能性があります。",
"shellIntegration": {
"title": "コマンド実行警告",
Expand Down
9 changes: 9 additions & 0 deletions webview-ui/src/i18n/locales/ko/chat.json
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,15 @@
"close": "브라우저 닫기"
}
},
"codeblock": {
"tooltips": {
"expand": "코드 블록 확장",
"collapse": "코드 블록 축소",
"enable_wrap": "자동 줄바꿈 활성화",
"disable_wrap": "자동 줄바꿈 비활성화",
"copy_code": "코드 복사"
}
},
"systemPromptWarning": "경고: 사용자 정의 시스템 프롬프트 재정의가 활성화되었습니다. 이로 인해 기능이 심각하게 손상되고 예측할 수 없는 동작이 발생할 수 있습니다.",
"shellIntegration": {
"title": "명령 실행 경고",
Expand Down
9 changes: 9 additions & 0 deletions webview-ui/src/i18n/locales/pl/chat.json
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,15 @@
"close": "Zamknij przeglądarkę"
}
},
"codeblock": {
"tooltips": {
"expand": "Rozwiń blok kodu",
"collapse": "Zwiń blok kodu",
"enable_wrap": "Włącz zawijanie wierszy",
"disable_wrap": "Wyłącz zawijanie wierszy",
"copy_code": "Kopiuj kod"
}
},
"systemPromptWarning": "OSTRZEŻENIE: Aktywne niestandardowe zastąpienie instrukcji systemowych. Może to poważnie zakłócić funkcjonalność i powodować nieprzewidywalne zachowanie.",
"shellIntegration": {
"title": "Ostrzeżenie wykonania polecenia",
Expand Down
9 changes: 9 additions & 0 deletions webview-ui/src/i18n/locales/pt-BR/chat.json
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,15 @@
"close": "Fechar navegador"
}
},
"codeblock": {
"tooltips": {
"expand": "Expandir bloco de código",
"collapse": "Recolher bloco de código",
"enable_wrap": "Ativar quebra de linha",
"disable_wrap": "Desativar quebra de linha",
"copy_code": "Copiar código"
}
},
"systemPromptWarning": "AVISO: Substituição personalizada de instrução do sistema ativa. Isso pode comprometer gravemente a funcionalidade e causar comportamento imprevisível.",
"shellIntegration": {
"title": "Aviso de execução de comando",
Expand Down
9 changes: 9 additions & 0 deletions webview-ui/src/i18n/locales/ru/chat.json
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,15 @@
"close": "Закрыть браузер"
}
},
"codeblock": {
"tooltips": {
"expand": "Развернуть блок кода",
"collapse": "Свернуть блок кода",
"enable_wrap": "Включить перенос строк",
"disable_wrap": "Отключить перенос строк",
"copy_code": "Копировать код"
}
},
"systemPromptWarning": "ПРЕДУПРЕЖДЕНИЕ: Активна пользовательская системная подсказка. Это может серьезно нарушить работу и вызвать непредсказуемое поведение.",
"shellIntegration": {
"title": "Предупреждение о выполнении команды",
Expand Down
9 changes: 9 additions & 0 deletions webview-ui/src/i18n/locales/tr/chat.json
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,15 @@
"close": "Tarayıcıyı kapat"
}
},
"codeblock": {
"tooltips": {
"expand": "Kod bloğunu genişlet",
"collapse": "Kod bloğunu daralt",
"enable_wrap": "Satır kaydırmayı etkinleştir",
"disable_wrap": "Satır kaydırmayı devre dışı bırak",
"copy_code": "Kodu kopyala"
}
},
"systemPromptWarning": "UYARI: Özel sistem komut geçersiz kılma aktif. Bu işlevselliği ciddi şekilde bozabilir ve öngörülemeyen davranışlara neden olabilir.",
"shellIntegration": {
"title": "Komut Çalıştırma Uyarısı",
Expand Down
9 changes: 9 additions & 0 deletions webview-ui/src/i18n/locales/vi/chat.json
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,15 @@
"close": "Đóng trình duyệt"
}
},
"codeblock": {
"tooltips": {
"expand": "Mở rộng khối mã",
"collapse": "Thu gọn khối mã",
"enable_wrap": "Bật tự động xuống dòng",
"disable_wrap": "Tắt tự động xuống dòng",
"copy_code": "Sao chép mã"
}
},
"systemPromptWarning": "CẢNH BÁO: Đã kích hoạt ghi đè lệnh nhắc hệ thống tùy chỉnh. Điều này có thể phá vỡ nghiêm trọng chức năng và gây ra hành vi không thể dự đoán.",
"shellIntegration": {
"title": "Cảnh báo thực thi lệnh",
Expand Down
9 changes: 9 additions & 0 deletions webview-ui/src/i18n/locales/zh-CN/chat.json
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,15 @@
"close": "关闭浏览器"
}
},
"codeblock": {
"tooltips": {
"expand": "展开代码块",
"collapse": "收起代码块",
"enable_wrap": "启用自动换行",
"disable_wrap": "禁用自动换行",
"copy_code": "复制代码"
}
},
"systemPromptWarning": "警告:自定义系统提示词覆盖已激活。这可能严重破坏功能并导致不可预测的行为。",
"shellIntegration": {
"title": "命令执行警告",
Expand Down
9 changes: 9 additions & 0 deletions webview-ui/src/i18n/locales/zh-TW/chat.json
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,15 @@
"close": "關閉瀏覽器"
}
},
"codeblock": {
"tooltips": {
"expand": "展開程式碼區塊",
"collapse": "摺疊程式碼區塊",
"enable_wrap": "啟用自動換行",
"disable_wrap": "停用自動換行",
"copy_code": "複製程式碼"
}
},
"systemPromptWarning": "警告:自訂系統提示詞覆蓋已啟用。這可能嚴重破壞功能並導致不可預測的行為。",
"shellIntegration": {
"title": "命令執行警告",
Expand Down