Remove language selection and word wrap toggle from CodeBlock (#8208)

This commit is contained in:
Matt Rubens 2025-09-21 23:05:08 -04:00 committed by GitHub
parent ceb9d2b9f2
commit 6a4dab0dfa
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 5 additions and 151 deletions

View file

@ -1,12 +1,11 @@
import { memo, useEffect, useRef, useCallback, useState } from "react"
import styled from "styled-components"
import { useCopyToClipboard } from "@src/utils/clipboard"
import { getHighlighter, isLanguageLoaded, normalizeLanguage, ExtendedLanguage } from "@src/utils/highlighter"
import { bundledLanguages } from "shiki"
import { getHighlighter, isLanguageLoaded, normalizeLanguage } from "@src/utils/highlighter"
import type { ShikiTransformer } from "shiki"
import { toJsxRuntime } from "hast-util-to-jsx-runtime"
import { Fragment, jsx, jsxs } from "react/jsx-runtime"
import { ChevronDown, ChevronUp, WrapText, AlignJustify, Copy, Check } from "lucide-react"
import { ChevronDown, ChevronUp, Copy, Check } from "lucide-react"
import { useAppTranslation } from "@src/i18n/TranslationContext"
import { StandardTooltip } from "@/components/ui"
@ -38,7 +37,6 @@ interface CodeBlockProps {
initialWordWrap?: boolean
collapsedHeight?: number
initialWindowShade?: boolean
onLanguageChange?: (language: string) => void
}
const CodeBlockButton = styled.button`
@ -167,52 +165,6 @@ export const StyledPre = styled.div<{
}
`
const LanguageSelect = styled.select`
font-size: 12px;
color: var(--vscode-foreground);
opacity: 0.4;
font-family: monospace;
appearance: none;
background: transparent;
border: none;
cursor: pointer;
padding: 4px;
margin: 0;
vertical-align: middle;
height: 24px;
& option {
background: var(--vscode-editor-background);
color: var(--vscode-foreground);
padding: 0;
margin: 0;
}
&::-webkit-scrollbar {
width: 6px;
}
&::-webkit-scrollbar-thumb {
background: var(--vscode-scrollbarSlider-background);
}
&::-webkit-scrollbar-track {
background: var(--vscode-editor-background);
}
&:hover {
opacity: 1;
background: var(--vscode-toolbar-hoverBackground);
border-radius: 3px;
}
&:focus {
opacity: 1;
outline: none;
border-radius: 3px;
}
`
const CodeBlock = memo(
({
source,
@ -222,12 +174,11 @@ const CodeBlock = memo(
initialWordWrap = true,
initialWindowShade = true,
collapsedHeight,
onLanguageChange,
}: CodeBlockProps) => {
const [wordWrap, setWordWrap] = useState(initialWordWrap)
// Use word wrap from props, default to true
const wordWrap = initialWordWrap
const [windowShade, setWindowShade] = useState(initialWindowShade)
const [currentLanguage, setCurrentLanguage] = useState<ExtendedLanguage>(() => normalizeLanguage(language))
const userChangedLanguageRef = useRef(false)
const currentLanguage = normalizeLanguage(language)
const [highlightedCode, setHighlightedCode] = useState<React.ReactNode>(null)
const [showCollapseButton, setShowCollapseButton] = useState(true)
const codeBlockRef = useRef<HTMLDivElement>(null)
@ -240,16 +191,6 @@ const CodeBlock = memo(
const collapseTimeout1Ref = useRef<NodeJS.Timeout | null>(null)
const collapseTimeout2Ref = useRef<NodeJS.Timeout | null>(null)
// Update current language when prop changes, but only if user hasn't
// made a selection.
useEffect(() => {
const normalizedLang = normalizeLanguage(language)
if (normalizedLang !== currentLanguage && !userChangedLanguageRef.current) {
setCurrentLanguage(normalizedLang)
}
}, [language, currentLanguage])
// Syntax highlighting with cached Shiki instance and mounted state management
useEffect(() => {
// Set mounted state at the beginning of this effect
@ -707,48 +648,6 @@ const CodeBlock = memo(
ref={copyButtonWrapperRef}
onMouseOver={() => updateCodeBlockButtonPosition()}
style={{ gap: 0 }}>
<LanguageSelect
value={currentLanguage}
style={{
width: `calc(${currentLanguage?.length || 0}ch + 9px)`,
}}
onClick={(e) => {
e.currentTarget.focus()
}}
onChange={(e) => {
const newLang = normalizeLanguage(e.target.value)
userChangedLanguageRef.current = true
setCurrentLanguage(newLang)
if (onLanguageChange) {
onLanguageChange(newLang)
}
}}>
<option
value={normalizeLanguage(language)}
style={{ fontWeight: "bold", textAlign: "left", fontSize: "1.2em" }}>
{normalizeLanguage(language)}
</option>
{
// Display all available languages in alphabetical order
Object.keys(bundledLanguages)
.sort()
.map((lang) => {
const normalizedLang = normalizeLanguage(lang)
return (
<option
key={normalizedLang}
value={normalizedLang}
style={{
fontWeight: normalizedLang === currentLanguage ? "bold" : "normal",
textAlign: "left",
fontSize: normalizedLang === currentLanguage ? "1.2em" : "inherit",
}}>
{normalizedLang}
</option>
)
})
}
</LanguageSelect>
{showCollapseButton && (
<StandardTooltip
content={t(`chat:codeblock.tooltips.${windowShade ? "expand" : "collapse"}`)}
@ -787,13 +686,6 @@ const CodeBlock = memo(
</CodeBlockButton>
</StandardTooltip>
)}
<StandardTooltip
content={t(`chat:codeblock.tooltips.${wordWrap ? "disable_wrap" : "enable_wrap"}`)}
side="top">
<CodeBlockButton onClick={() => setWordWrap(!wordWrap)}>
{wordWrap ? <AlignJustify size={16} /> : <WrapText size={16} />}
</CodeBlockButton>
</StandardTooltip>
<StandardTooltip content={t("chat:codeblock.tooltips.copy_code")} side="top">
<CodeBlockButton onClick={handleCopy}>
{showCopyFeedback ? <Check size={16} /> : <Copy size={16} />}

View file

@ -13,8 +13,6 @@ vi.mock("../../../i18n/TranslationContext", () => ({
"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
},

View file

@ -317,8 +317,6 @@
"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"
}
},

View file

@ -317,8 +317,6 @@
"tooltips": {
"expand": "Code-Block erweitern",
"collapse": "Code-Block reduzieren",
"enable_wrap": "Zeilenumbruch aktivieren",
"disable_wrap": "Zeilenumbruch deaktivieren",
"copy_code": "Code kopieren"
}
},

View file

@ -335,8 +335,6 @@
"tooltips": {
"expand": "Expand code block",
"collapse": "Collapse code block",
"enable_wrap": "Enable word wrap",
"disable_wrap": "Disable word wrap",
"copy_code": "Copy code"
}
},

View file

@ -317,8 +317,6 @@
"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"
}
},

View file

@ -317,8 +317,6 @@
"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"
}
},

View file

@ -317,8 +317,6 @@
"tooltips": {
"expand": "कोड ब्लॉक का विस्तार करें",
"collapse": "कोड ब्लॉक को संकुचित करें",
"enable_wrap": "वर्ड रैप सक्षम करें",
"disable_wrap": "वर्ड रैप अक्षम करें",
"copy_code": "कोड कॉपी करें"
}
},

View file

@ -338,8 +338,6 @@
"tooltips": {
"expand": "Perluas blok kode",
"collapse": "Tutup blok kode",
"enable_wrap": "Aktifkan word wrap",
"disable_wrap": "Nonaktifkan word wrap",
"copy_code": "Salin kode"
}
},

View file

@ -317,8 +317,6 @@
"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"
}
},

View file

@ -317,8 +317,6 @@
"tooltips": {
"expand": "コードブロックを展開",
"collapse": "コードブロックを折りたたむ",
"enable_wrap": "折り返しを有効化",
"disable_wrap": "折り返しを無効化",
"copy_code": "コードをコピー"
}
},

View file

@ -317,8 +317,6 @@
"tooltips": {
"expand": "코드 블록 확장",
"collapse": "코드 블록 축소",
"enable_wrap": "자동 줄바꿈 활성화",
"disable_wrap": "자동 줄바꿈 비활성화",
"copy_code": "코드 복사"
}
},

View file

@ -317,8 +317,6 @@
"tooltips": {
"expand": "Codeblok uitvouwen",
"collapse": "Codeblok samenvouwen",
"enable_wrap": "Regelafbreking inschakelen",
"disable_wrap": "Regelafbreking uitschakelen",
"copy_code": "Code kopiëren"
}
},

View file

@ -317,8 +317,6 @@
"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"
}
},

View file

@ -317,8 +317,6 @@
"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"
}
},

View file

@ -318,8 +318,6 @@
"tooltips": {
"expand": "Развернуть блок кода",
"collapse": "Свернуть блок кода",
"enable_wrap": "Включить перенос строк",
"disable_wrap": "Отключить перенос строк",
"copy_code": "Копировать код"
}
},

View file

@ -318,8 +318,6 @@
"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"
}
},

View file

@ -318,8 +318,6 @@
"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ã"
}
},

View file

@ -318,8 +318,6 @@
"tooltips": {
"expand": "展开代码块",
"collapse": "收起代码块",
"enable_wrap": "启用自动换行",
"disable_wrap": "禁用自动换行",
"copy_code": "复制代码"
}
},

View file

@ -336,8 +336,6 @@
"tooltips": {
"expand": "展開程式碼區塊",
"collapse": "摺疊程式碼區塊",
"enable_wrap": "啟用自動換行",
"disable_wrap": "停用自動換行",
"copy_code": "複製程式碼"
}
},