Skip to content

Commit 65958d8

Browse files
authored
Overhaul CodeBlock rendering (#3019)
1 parent 04fa72e commit 65958d8

File tree

14 files changed

+1129
-210
lines changed

14 files changed

+1129
-210
lines changed

.changeset/five-pumpkins-carry.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"roo-cline": patch
3+
---
4+
5+
Overhaul CodeBlock rendering

src/core/webview/ClineProvider.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -748,7 +748,7 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
748748
<meta charset="utf-8">
749749
<meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no">
750750
<meta name="theme-color" content="#000000">
751-
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; font-src ${webview.cspSource}; style-src ${webview.cspSource} 'unsafe-inline'; img-src ${webview.cspSource} data:; script-src 'nonce-${nonce}' https://us-assets.i.posthog.com; connect-src https://openrouter.ai https://api.requesty.ai https://us.i.posthog.com https://us-assets.i.posthog.com;">
751+
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; font-src ${webview.cspSource}; style-src ${webview.cspSource} 'unsafe-inline'; img-src ${webview.cspSource} data:; script-src ${webview.cspSource} 'wasm-unsafe-eval' 'nonce-${nonce}' https://us-assets.i.posthog.com 'strict-dynamic'; connect-src https://openrouter.ai https://api.requesty.ai https://us.i.posthog.com https://us-assets.i.posthog.com;">
752752
<link rel="stylesheet" type="text/css" href="${stylesUri}">
753753
<link href="${codiconsUri}" rel="stylesheet" />
754754
<script nonce="${nonce}">

src/core/webview/__tests__/ClineProvider.test.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,14 @@ describe("ClineProvider", () => {
375375
expect(mockWebviewView.webview.html).toContain(
376376
"connect-src https://openrouter.ai https://api.requesty.ai https://us.i.posthog.com https://us-assets.i.posthog.com;",
377377
)
378-
expect(mockWebviewView.webview.html).toContain("script-src 'nonce-")
378+
379+
// Extract the script-src directive section and verify required security elements
380+
const html = mockWebviewView.webview.html
381+
const scriptSrcMatch = html.match(/script-src[^;]*;/)
382+
expect(scriptSrcMatch).not.toBeNull()
383+
expect(scriptSrcMatch![0]).toContain("'nonce-")
384+
// Verify wasm-unsafe-eval is present for Shiki syntax highlighting
385+
expect(scriptSrcMatch![0]).toContain("'wasm-unsafe-eval'")
379386
})
380387

381388
test("postMessageToWebview sends message to webview", async () => {

webview-ui/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
"remark-gfm": "^4.0.1",
5858
"remove-markdown": "^0.6.0",
5959
"shell-quote": "^1.8.2",
60+
"shiki": "^3.2.1",
6061
"styled-components": "^6.1.13",
6162
"tailwind-merge": "^2.6.0",
6263
"tailwindcss": "^4.0.0",
@@ -91,7 +92,6 @@
9192
"jest": "^29.7.0",
9293
"jest-environment-jsdom": "^29.7.0",
9394
"jest-simple-dot-reporter": "^1.0.5",
94-
"shiki": "^2.3.2",
9595
"storybook": "^8.5.6",
9696
"storybook-dark-mode": "^4.0.2",
9797
"ts-jest": "^29.2.5",

webview-ui/src/components/chat/BrowserSessionRow.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -357,9 +357,7 @@ const BrowserSessionRow = memo((props: BrowserSessionRowProps) => {
357357
<span style={{ fontSize: "0.8em" }}>{t("chat:browser.consoleLogs")}</span>
358358
</div>
359359
{consoleLogsExpanded && (
360-
<CodeBlock
361-
source={`${"```"}shell\n${displayState.consoleLogs || t("chat:browser.noNewLogs")}\n${"```"}`}
362-
/>
360+
<CodeBlock source={displayState.consoleLogs || t("chat:browser.noNewLogs")} language="shell" />
363361
)}
364362
</div>
365363
</div>
@@ -488,7 +486,7 @@ const BrowserSessionRowContent = ({
488486
overflow: "hidden",
489487
backgroundColor: CODE_BLOCK_BG_COLOR,
490488
}}>
491-
<CodeBlock source={`${"```"}shell\n${message.text}\n${"```"}`} forceWrap={true} />
489+
<CodeBlock source={message.text} language="shell" />
492490
</div>
493491
</>
494492
)

webview-ui/src/components/chat/ChatRow.tsx

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,7 @@ export const ChatRowContent = ({
511511
<CodeAccordian
512512
code={tool.content!}
513513
path={tool.path! + (tool.filePattern ? `/(${tool.filePattern})` : "")}
514-
language="plaintext"
514+
language="log"
515515
isExpanded={isExpanded}
516516
onToggleExpand={onToggleExpand}
517517
/>
@@ -731,10 +731,7 @@ export const ChatRowContent = ({
731731
backgroundColor: "var(--vscode-editor-background)",
732732
borderTop: "none",
733733
}}>
734-
<CodeBlock
735-
source={`${"```"}plaintext\n${message.text || ""}\n${"```"}`}
736-
forceWrap={true}
737-
/>
734+
<CodeBlock source={`${"```"}plaintext\n${message.text || ""}\n${"```"}`} />
738735
</div>
739736
)}
740737
</div>
@@ -1111,7 +1108,6 @@ export const ChatRowContent = ({
11111108
language="json"
11121109
isExpanded={true}
11131110
onToggleExpand={onToggleExpand}
1114-
forceWrap={true}
11151111
/>
11161112
</div>
11171113
)}

webview-ui/src/components/common/CodeAccordian.tsx

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ interface CodeAccordianProps {
1515
onToggleExpand: () => void
1616
isLoading?: boolean
1717
progressStatus?: ToolProgressStatus
18-
forceWrap?: boolean
1918
}
2019

2120
/*
@@ -40,7 +39,6 @@ const CodeAccordian = ({
4039
onToggleExpand,
4140
isLoading,
4241
progressStatus,
43-
forceWrap,
4442
}: CodeAccordianProps) => {
4543
const inferredLanguage = useMemo(
4644
() => code && (language ?? (path ? getLanguageFromPath(path) : undefined)),
@@ -126,12 +124,8 @@ const CodeAccordian = ({
126124
maxWidth: "100%",
127125
}}>
128126
<CodeBlock
129-
source={`${"```"}${diff !== undefined ? "diff" : inferredLanguage}\n${(
130-
code ??
131-
diff ??
132-
""
133-
).trim()}\n${"```"}`}
134-
forceWrap={forceWrap}
127+
source={(code ?? diff ?? "").trim()}
128+
language={diff !== undefined ? "diff" : inferredLanguage}
135129
/>
136130
</div>
137131
)}

0 commit comments

Comments
 (0)