fix: code block style in dark mode

pull/4841/head
Steven 3 months ago
parent 74769b3332
commit d7ced7b738

@ -1,13 +1,11 @@
import copy from "copy-to-clipboard";
import hljs from "highlight.js";
import { CopyIcon } from "lucide-react";
import { useCallback, useMemo } from "react";
import { useEffect, useMemo } from "react";
import toast from "react-hot-toast";
import { cn } from "@/lib/utils";
import MermaidBlock from "./MermaidBlock";
import { BaseProps } from "./types";
import "highlight.js/styles/atom-one-dark.css";
import "highlight.js/styles/github.css";
// Special languages that are rendered differently.
enum SpecialLanguage {
@ -37,6 +35,44 @@ const CodeBlock: React.FC<Props> = ({ language, content }: Props) => {
return <MermaidBlock content={content} />;
}
useEffect(() => {
const dynamicImportStyle = async () => {
const isDark = document.documentElement.classList.contains("dark");
// Remove any existing highlight.js style
const existingStyle = document.querySelector("style[data-hljs-theme]");
if (existingStyle) {
existingStyle.remove();
}
try {
// Dynamically import the appropriate CSS.
const cssModule = isDark
? await import("highlight.js/styles/atom-one-dark.css?inline")
: await import("highlight.js/styles/github.css?inline");
// Create and inject the style
const style = document.createElement("style");
style.textContent = cssModule.default;
style.setAttribute("data-hljs-theme", isDark ? "dark" : "light");
document.head.appendChild(style);
} catch (error) {
console.warn("Failed to load highlight.js theme:", error);
}
};
dynamicImportStyle();
// Watch for changes to the dark class
const observer = new MutationObserver(dynamicImportStyle);
observer.observe(document.documentElement, {
attributes: true,
attributeFilter: ["class"],
});
return () => observer.disconnect();
}, []);
const highlightedCode = useMemo(() => {
try {
const lang = hljs.getLanguage(formatedLanguage);
@ -55,16 +91,16 @@ const CodeBlock: React.FC<Props> = ({ language, content }: Props) => {
}).innerHTML;
}, [formatedLanguage, content]);
const handleCopyButtonClick = useCallback(() => {
const copyContent = () => {
copy(content);
toast.success("Copied to clipboard!");
}, [content]);
};
return (
<div className="w-full my-1 bg-card border border-border rounded-md relative">
<div className="w-full px-2 py-0.5 flex flex-row justify-between items-center text-muted-foreground">
<span className="text-xs font-mono">{formatedLanguage}</span>
<CopyIcon className="w-3 h-auto cursor-pointer hover:text-foreground" onClick={handleCopyButtonClick} />
<CopyIcon className="w-3 h-auto cursor-pointer hover:text-foreground" onClick={copyContent} />
</div>
<div className="overflow-auto">

@ -1,37 +1,17 @@
import { useEffect, useRef, useState } from "react";
import { useEffect, useRef } from "react";
interface Props {
content: string;
}
const MermaidBlock: React.FC<Props> = ({ content }: Props) => {
const [colorMode, setColorMode] = useState<"light" | "dark">("light");
const mermaidDockBlock = useRef<null>(null);
// Simple dark mode detection
useEffect(() => {
const updateMode = () => {
const isDark = document.documentElement.classList.contains("dark");
setColorMode(isDark ? "dark" : "light");
};
updateMode();
// Watch for changes to the dark class
const observer = new MutationObserver(updateMode);
observer.observe(document.documentElement, {
attributes: true,
attributeFilter: ["class"],
});
return () => observer.disconnect();
}, []);
useEffect(() => {
// Dynamically import mermaid to ensure compatibility with Vite
const initializeMermaid = async () => {
const isDark = document.documentElement.classList.contains("dark");
const mermaid = (await import("mermaid")).default;
mermaid.initialize({ startOnLoad: false, theme: colorMode == "dark" ? "dark" : "default" });
mermaid.initialize({ startOnLoad: false, theme: isDark ? "dark" : "default" });
if (mermaidDockBlock.current) {
mermaid.run({
nodes: [mermaidDockBlock.current],

Loading…
Cancel
Save