diff --git a/surfsense_web/components/chat/ChatMessages.tsx b/surfsense_web/components/chat/ChatMessages.tsx
index 473564ddf..20aa07815 100644
--- a/surfsense_web/components/chat/ChatMessages.tsx
+++ b/surfsense_web/components/chat/ChatMessages.tsx
@@ -12,6 +12,9 @@ import ChatSourcesDisplay from "@/components/chat/ChatSources";
import { CitationDisplay } from "@/components/chat/ChatCitation";
import { ChatFurtherQuestions } from "@/components/chat/ChatFurtherQuestions";
import { AnimatedEmptyState } from "@/components/chat/AnimatedEmptyState";
+import { languageRenderers } from "@/components/chat/CodeBlock";
+
+
export function ChatMessagesUI() {
const { messages } = useChatUI();
@@ -63,6 +66,7 @@ function ChatMessageUI({
@@ -73,7 +77,9 @@ function ChatMessageUI({
) : (
-
+
)}
diff --git a/surfsense_web/components/chat/CodeBlock.tsx b/surfsense_web/components/chat/CodeBlock.tsx
new file mode 100644
index 000000000..f5474007e
--- /dev/null
+++ b/surfsense_web/components/chat/CodeBlock.tsx
@@ -0,0 +1,153 @@
+"use client";
+
+import React, { useState, useEffect } from "react";
+import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
+import {
+ oneLight,
+ oneDark,
+} from "react-syntax-highlighter/dist/cjs/styles/prism";
+import { Check, Copy } from "lucide-react";
+import { useTheme } from "next-themes";
+
+// Code block component with syntax highlighting and copy functionality
+export const CodeBlock = ({
+ children,
+ language,
+}: {
+ children: string;
+ language: string;
+}) => {
+ const [copied, setCopied] = useState(false);
+ const { resolvedTheme, theme } = useTheme();
+ const [mounted, setMounted] = useState(false);
+
+ // Prevent hydration issues
+ useEffect(() => {
+ setMounted(true);
+ }, []);
+
+ const handleCopy = async () => {
+ await navigator.clipboard.writeText(children);
+ setCopied(true);
+ setTimeout(() => setCopied(false), 2000);
+ };
+
+ // Choose theme based on current system/user preference
+ const isDarkTheme = mounted && (resolvedTheme === "dark" || theme === "dark");
+ const syntaxTheme = isDarkTheme ? oneDark : oneLight;
+
+ return (
+
+
+
+
+ {mounted ? (
+
+ {children}
+
+ ) : (
+
+ )}
+
+ );
+};
+
+// Create language renderer function
+const createLanguageRenderer = (lang: string) =>
+ ({ code }: { code: string }) => (
+ {code}
+ );
+
+// Define language renderers for common programming languages
+export const languageRenderers = {
+ "javascript": createLanguageRenderer("javascript"),
+ "typescript": createLanguageRenderer("typescript"),
+ "python": createLanguageRenderer("python"),
+ "java": createLanguageRenderer("java"),
+ "csharp": createLanguageRenderer("csharp"),
+ "cpp": createLanguageRenderer("cpp"),
+ "c": createLanguageRenderer("c"),
+ "php": createLanguageRenderer("php"),
+ "ruby": createLanguageRenderer("ruby"),
+ "go": createLanguageRenderer("go"),
+ "rust": createLanguageRenderer("rust"),
+ "swift": createLanguageRenderer("swift"),
+ "kotlin": createLanguageRenderer("kotlin"),
+ "scala": createLanguageRenderer("scala"),
+ "sql": createLanguageRenderer("sql"),
+ "json": createLanguageRenderer("json"),
+ "xml": createLanguageRenderer("xml"),
+ "yaml": createLanguageRenderer("yaml"),
+ "bash": createLanguageRenderer("bash"),
+ "shell": createLanguageRenderer("shell"),
+ "powershell": createLanguageRenderer("powershell"),
+ "dockerfile": createLanguageRenderer("dockerfile"),
+ "html": createLanguageRenderer("html"),
+ "css": createLanguageRenderer("css"),
+ "scss": createLanguageRenderer("scss"),
+ "less": createLanguageRenderer("less"),
+ "markdown": createLanguageRenderer("markdown"),
+ "text": createLanguageRenderer("text"),
+};
\ No newline at end of file
diff --git a/surfsense_web/components/chat/index.ts b/surfsense_web/components/chat/index.ts
index 55ab716c0..812bf805b 100644
--- a/surfsense_web/components/chat/index.ts
+++ b/surfsense_web/components/chat/index.ts
@@ -4,4 +4,5 @@ export * from './ConnectorComponents';
export * from './Citation';
export * from './SourceUtils';
export * from './ScrollUtils';
+export * from './CodeBlock';
export * from './types';
\ No newline at end of file