Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
C
canifa_note
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Vũ Hoàng Anh
canifa_note
Commits
d7ced7b7
Commit
d7ced7b7
authored
Jul 18, 2025
by
Steven
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix: code block style in dark mode
parent
74769b33
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
45 additions
and
29 deletions
+45
-29
CodeBlock.tsx
web/src/components/MemoContent/CodeBlock.tsx
+42
-6
MermaidBlock.tsx
web/src/components/MemoContent/MermaidBlock.tsx
+3
-23
No files found.
web/src/components/MemoContent/CodeBlock.tsx
View file @
d7ced7b7
import
copy
from
"copy-to-clipboard"
;
import
hljs
from
"highlight.js"
;
import
{
CopyIcon
}
from
"lucide-react"
;
import
{
use
Callback
,
useMemo
}
from
"react"
;
import
{
use
Effect
,
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"
>
...
...
web/src/components/MemoContent/MermaidBlock.tsx
View file @
d7ced7b7
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
],
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment