mirror of
https://github.com/usememos/memos.git
synced 2025-11-12 10:21:53 +08:00
fix: code block style in dark mode
This commit is contained in:
parent
74769b3332
commit
d7ced7b738
2 changed files with 45 additions and 29 deletions
|
|
@ -1,13 +1,11 @@
|
||||||
import copy from "copy-to-clipboard";
|
import copy from "copy-to-clipboard";
|
||||||
import hljs from "highlight.js";
|
import hljs from "highlight.js";
|
||||||
import { CopyIcon } from "lucide-react";
|
import { CopyIcon } from "lucide-react";
|
||||||
import { useCallback, useMemo } from "react";
|
import { useEffect, useMemo } from "react";
|
||||||
import toast from "react-hot-toast";
|
import toast from "react-hot-toast";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import MermaidBlock from "./MermaidBlock";
|
import MermaidBlock from "./MermaidBlock";
|
||||||
import { BaseProps } from "./types";
|
import { BaseProps } from "./types";
|
||||||
import "highlight.js/styles/atom-one-dark.css";
|
|
||||||
import "highlight.js/styles/github.css";
|
|
||||||
|
|
||||||
// Special languages that are rendered differently.
|
// Special languages that are rendered differently.
|
||||||
enum SpecialLanguage {
|
enum SpecialLanguage {
|
||||||
|
|
@ -37,6 +35,44 @@ const CodeBlock: React.FC<Props> = ({ language, content }: Props) => {
|
||||||
return <MermaidBlock content={content} />;
|
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(() => {
|
const highlightedCode = useMemo(() => {
|
||||||
try {
|
try {
|
||||||
const lang = hljs.getLanguage(formatedLanguage);
|
const lang = hljs.getLanguage(formatedLanguage);
|
||||||
|
|
@ -55,16 +91,16 @@ const CodeBlock: React.FC<Props> = ({ language, content }: Props) => {
|
||||||
}).innerHTML;
|
}).innerHTML;
|
||||||
}, [formatedLanguage, content]);
|
}, [formatedLanguage, content]);
|
||||||
|
|
||||||
const handleCopyButtonClick = useCallback(() => {
|
const copyContent = () => {
|
||||||
copy(content);
|
copy(content);
|
||||||
toast.success("Copied to clipboard!");
|
toast.success("Copied to clipboard!");
|
||||||
}, [content]);
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-full my-1 bg-card border border-border rounded-md relative">
|
<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">
|
<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>
|
<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>
|
||||||
|
|
||||||
<div className="overflow-auto">
|
<div className="overflow-auto">
|
||||||
|
|
|
||||||
|
|
@ -1,37 +1,17 @@
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef } from "react";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
content: string;
|
content: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const MermaidBlock: React.FC<Props> = ({ content }: Props) => {
|
const MermaidBlock: React.FC<Props> = ({ content }: Props) => {
|
||||||
const [colorMode, setColorMode] = useState<"light" | "dark">("light");
|
|
||||||
const mermaidDockBlock = useRef<null>(null);
|
const mermaidDockBlock = useRef<null>(null);
|
||||||
|
|
||||||
// Simple dark mode detection
|
|
||||||
useEffect(() => {
|
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 initializeMermaid = async () => {
|
||||||
|
const isDark = document.documentElement.classList.contains("dark");
|
||||||
const mermaid = (await import("mermaid")).default;
|
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) {
|
if (mermaidDockBlock.current) {
|
||||||
mermaid.run({
|
mermaid.run({
|
||||||
nodes: [mermaidDockBlock.current],
|
nodes: [mermaidDockBlock.current],
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue