Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | 1x 1x 1x 1x 1x 1x 1x 1x 1x | import { memo, useMemo } from "react"
import CodeBlock, { CODE_BLOCK_BG_COLOR } from "@/components/common/CodeBlock"
import { getLanguageFromPath } from "@/utils/getLanguageFromPath"
interface CodeAccordianProps {
code?: string
diff?: string
language?: string | undefined
path?: string
isFeedback?: boolean
isConsoleLogs?: boolean
isExpanded: boolean
onToggleExpand: () => void
isLoading?: boolean
}
/*
We need to remove leading non-alphanumeric characters from the path in order for our leading ellipses trick to work.
^: Anchors the match to the start of the string.
[^a-zA-Z0-9]+: Matches one or more characters that are not alphanumeric.
The replace method removes these matched characters, effectively trimming the string up to the first alphanumeric character.
*/
export const cleanPathPrefix = (path: string): string => path.replace(/^[^\u4e00-\u9fa5a-zA-Z0-9]+/, "")
const CodeAccordian = ({
code,
diff,
language,
path,
isFeedback,
isConsoleLogs,
isExpanded,
onToggleExpand,
isLoading,
}: CodeAccordianProps) => {
const inferredLanguage = useMemo(
() => code && (language ?? (path ? getLanguageFromPath(path) : undefined)),
[path, language, code],
)
const numberOfEdits = useMemo(() => {
if (code) {
return (code.match(/[-]{3,} SEARCH/g) || []).length || undefined
}
return undefined
}, [code])
return (
<div
style={{
borderRadius: 3,
backgroundColor: CODE_BLOCK_BG_COLOR,
overflow: "hidden", // This ensures the inner scrollable area doesn't overflow the rounded corners
border: "1px solid var(--vscode-editorGroup-border)",
}}>
{(path || isFeedback || isConsoleLogs) && (
<div
onClick={isLoading ? undefined : onToggleExpand}
style={{
color: "var(--vscode-descriptionForeground)",
display: "flex",
alignItems: "center",
padding: "9px 10px",
cursor: isLoading ? "wait" : "pointer",
opacity: isLoading ? 0.7 : 1,
// pointerEvents: isLoading ? "none" : "auto",
userSelect: "none",
WebkitUserSelect: "none",
MozUserSelect: "none",
msUserSelect: "none",
}}>
{isFeedback || isConsoleLogs ? (
<div style={{ display: "flex", alignItems: "center" }}>
<span
className={`codicon codicon-${isFeedback ? "feedback" : "output"}`}
style={{ marginRight: "6px" }}></span>
<span
style={{
whiteSpace: "nowrap",
overflow: "hidden",
textOverflow: "ellipsis",
marginRight: "8px",
}}>
{isFeedback ? "User Edits" : "Console Logs"}
</span>
</div>
) : (
<>
{path?.startsWith(".") && <span>.</span>}
{path && !path.startsWith(".") && <span>/</span>}
<span
style={{
whiteSpace: "nowrap",
overflow: "hidden",
textOverflow: "ellipsis",
marginRight: "8px",
// trick to get ellipsis at beginning of string
direction: "rtl",
textAlign: "left",
}}>
{cleanPathPrefix(path ?? "") + "\u200E"}
</span>
</>
)}
<div style={{ flexGrow: 1 }}></div>
{numberOfEdits !== undefined && (
<div
style={{
display: "flex",
alignItems: "center",
marginRight: "8px",
color: "var(--vscode-descriptionForeground)",
}}>
<span className="codicon codicon-diff-single" style={{ marginRight: "4px" }}></span>
<span>{numberOfEdits}</span>
</div>
)}
<span className={`codicon codicon-chevron-${isExpanded ? "up" : "down"}`}></span>
</div>
)}
{(!(path || isFeedback || isConsoleLogs) || isExpanded) && (
<div
//className="code-block-scrollable" this doesn't seem to be necessary anymore, on silicon macs it shows the native mac scrollbar instead of the vscode styled one
style={{
overflowX: "auto",
overflowY: "hidden",
maxWidth: "100%",
}}>
<CodeBlock
source={`${"```"}${diff !== undefined ? "diff" : inferredLanguage}\n${(
code ?? diff ?? ""
).trim()}\n${"```"}`}
/>
</div>
)}
</div>
)
}
// memo does shallow comparison of props, so if you need it to re-render when a nested object changes, you need to pass a custom comparison function
export default memo(CodeAccordian)
|