Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: syntax highlighting auto detecting lang #32

Merged
merged 4 commits into from
Jan 7, 2025
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
11 changes: 0 additions & 11 deletions docker-compose.yml

This file was deleted.

20 changes: 0 additions & 20 deletions dockerfile

This file was deleted.

28 changes: 0 additions & 28 deletions nginx.conf

This file was deleted.

28 changes: 24 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"date-fns": "^4.1.0",
"highlight.js": "^11.11.1",
"lucide-react": "^0.462.0",
"prismjs": "^1.29.0",
"react": "19.0.0",
Expand Down
2 changes: 1 addition & 1 deletion src/components/Chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export function Chat() {
<div className="w-[calc(100vw-18rem)]">
<ChatMessageList>
{(chat?.question_answers ?? []).map(({ question, answer }, index) => (
<div key={index} className="flex flex-col w-full h-full p-4 gap-6">
<div key={index} className="flex flex-col w-full h-full gap-6">
<ChatBubble variant="sent">
<ChatBubbleAvatar fallback="User" className="w-14" />
<ChatBubbleMessage variant="sent" className="bg-zinc-700">
Expand Down
10 changes: 6 additions & 4 deletions src/components/Dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,15 @@ const wrapObjectOutput = (input: string | MaliciousPkgType | null) => {
const isObject = /\{"/.test(input);
if (isObject) {
return (
<pre className="max-h-40 overflow-y-auto whitespace-pre-wrap bg-gray-100 p-2">
<pre className="max-h-40 overflow-y-auto whitespace-pre-wrap bg-secondary p-2">
<code>{input}</code>
</pre>
);
}
return (
<Markdown className="bg-gray-100 overflow-auto w-fit p-1">{input}</Markdown>
<Markdown className="bg-secondary rounded-lg overflow-auto w-fit p-1">
{input}
</Markdown>
);
};

Expand Down Expand Up @@ -119,7 +121,7 @@ export function Dashboard() {
setSearchParams(searchParams);
toggleMaliciousFilter(isChecked);
},
[setSearchParams, setSearch, searchParams, toggleMaliciousFilter]
[setSearchParams, setSearch, searchParams, toggleMaliciousFilter],
);

const handleSearch = useCallback(
Expand All @@ -135,7 +137,7 @@ export function Dashboard() {
}
setSearchParams(searchParams);
},
[searchParams, setSearch, setSearchParams, toggleMaliciousFilter]
[searchParams, setSearch, setSearchParams, toggleMaliciousFilter],
);

return (
Expand Down
109 changes: 54 additions & 55 deletions src/components/Markdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,32 @@ import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
import { oneDark } from "react-syntax-highlighter/dist/esm/styles/prism";
import { cn } from "@/lib/utils";
import { CopyToClipboard } from "./CopyToClipboard";
import hljs from "highlight.js";

const LANGUAGES_SUBSET_DETECTION = [
"c",
"cpp",
"csharp",
"css",
"elixir",
"go",
"groovy",
"haskell",
"html",
"java",
"javascript",
"json",
"kotlin",
"markdown",
"php",
"python",
"ruby",
"rust",
"scala",
"sql",
"typescript",
"yaml",
];

interface Props {
children: string;
Expand All @@ -12,85 +38,58 @@ interface Props {

const customStyle = {
...oneDark,
'code[class*="language-"]': {
...oneDark['code[class*="language-"]'],
background: "none",
},
'pre[class*="language-"]': {
...oneDark['pre[class*="language-"]'],
whiteSpace: "pre-wrap",
background: "#1a1b26",
padding: "1.5rem",
borderRadius: "0.5rem",
margin: "1.5rem 0",
fontSize: "10px",
width: "80%", // Ensure the block takes full width
width: "100%",
position: "relative",
boxSizing: "border-box",
},
};

export function Markdown({ children, className = "" }: Props) {
SyntaxHighlighter.supportedLanguages = LANGUAGES_SUBSET_DETECTION;
return (
<ReactMarkdown
components={{
/* eslint-disable @typescript-eslint/no-explicit-any */
code({ className, children, ...props }: any) {
code({ className, children, ...props }) {
const detectedLanguage =
hljs.highlightAuto(children, LANGUAGES_SUBSET_DETECTION).language ??
"plaintext";
const match = /language-(\w+)/.exec(className || "");
const inline = !match;
return !inline ? (
<div className="relative group w-full ml-0 px-4">
const language = match ? match[1] : detectedLanguage;
return (
<div className="relative group w-full ml-0 my-4">
<SyntaxHighlighter
style={{
...customStyle,
'pre[class*="language-"]': {
...oneDark['pre[class*="language-"]'],
background: "#1a1b26",
fontSize: "10x",
whiteSpace: "pre-wrap",
padding: "1.5rem",
borderRadius: "0.5rem",
margin: "1.5rem 0",
position: "relative", // Critical for clipboard positioning
width: "100%", // Ensure full width of parent container
boxSizing: "border-box", // Prevent padding overflow
},
}}
language={match[1]}
style={customStyle}
supportedLanguages={LANGUAGES_SUBSET_DETECTION}
language={language}
PreTag="div"
className="rounded-lg overflow-hidden shadow-lg text-sm"
showLineNumbers={false}
wrapLines={true}
className="rounded-lg overflow-hidden shadow-lg text-sm my-6 whitespace-normal"
wrapLines
{...props}
>
{String(children).replace(/\n$/, "")}
</SyntaxHighlighter>
<CopyToClipboard text={String(children).replace(/\n$/, "")} />
{match && (
<CopyToClipboard text={String(children).replace(/\n$/, "")} />
)}
</div>
) : (
<SyntaxHighlighter
style={{
...customStyle,
'pre[class*="language-"]': {
...oneDark['pre[class*="language-"]'],
fontSize: "10x",
whiteSpace: "pre-wrap",
padding: "1.5rem",
borderRadius: "0.5rem",
margin: "1.5rem 0",
position: "relative", // Critical for clipboard positioning
width: "100%", // Ensure full width of parent container
boxSizing: "border-box", // Prevent padding overflow
},
}}
PreTag="div"
className="rounded-lg overflow-hidden shadow-lg text-sm"
showLineNumbers={false}
wrapLines={true}
{...props}
>
{children}
</SyntaxHighlighter>
);
},
p({ children }) {
return (
<p className={cn("text-gray-600 leading-relaxed mb-4", className)}>
<p
className={cn(
"text-gray-600 leading-relaxed mt-6 mb-3",
className,
)}
>
{children}
</p>
);
Expand Down
Loading
Loading