refactor(web): use official highlight themes for markdown

This commit is contained in:
lc6464
2026-04-15 17:19:48 +08:00
parent 25ac563406
commit 389f492d8c
7 changed files with 63 additions and 68 deletions
+1
View File
@@ -26,6 +26,7 @@
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"dayjs": "^1.11.20",
"highlight.js": "^11.11.1",
"i18next": "^26.0.3",
"i18next-browser-languagedetector": "^8.2.1",
"jotai": "^2.19.1",
+3
View File
@@ -35,6 +35,9 @@ importers:
dayjs:
specifier: ^1.11.20
version: 1.11.20
highlight.js:
specifier: ^11.11.1
version: 11.11.1
i18next:
specifier: ^26.0.3
version: 26.0.3(typescript@5.9.3)
@@ -172,7 +172,7 @@ export function DetailSheet({
</div>
{detailView === "preview" ? (
<div className="prose prose-zinc dark:prose-invert prose-sm sm:prose-base prose-pre:rounded-xl prose-pre:border prose-pre:border-border/40 prose-pre:bg-zinc-950/90 prose-pre:shadow-sm prose-headings:tracking-tight prose-a:text-primary prose-a:no-underline hover:prose-a:underline max-w-none">
<div className="prose prose-zinc dark:prose-invert prose-sm sm:prose-base prose-pre:rounded-xl prose-pre:border prose-pre:border-border/40 prose-pre:bg-zinc-100 prose-pre:p-0 prose-pre:shadow-sm dark:prose-pre:bg-zinc-950/90 prose-headings:tracking-tight prose-a:text-primary prose-a:no-underline hover:prose-a:underline max-w-none">
<ReactMarkdown
remarkPlugins={[remarkGfm]}
rehypePlugins={[rehypeRaw, rehypeSanitize, rehypeHighlight]}
@@ -64,7 +64,7 @@ export function AssistantMessage({
>
<div
className={cn(
"prose dark:prose-invert prose-pre:my-2 prose-pre:overflow-x-auto prose-pre:rounded-lg prose-pre:border prose-pre:bg-zinc-950 prose-pre:p-3 max-w-none [overflow-wrap:anywhere] break-words",
"prose dark:prose-invert prose-pre:my-2 prose-pre:overflow-x-auto prose-pre:rounded-lg prose-pre:border prose-pre:bg-zinc-100 prose-pre:p-0 dark:prose-pre:bg-zinc-950 max-w-none [overflow-wrap:anywhere] break-words",
isThought
? "prose-p:my-1.5 p-3 text-[13px] leading-relaxed opacity-90"
: "prose-p:my-2 p-4 text-[15px] leading-relaxed",
@@ -0,0 +1,45 @@
import { useEffect } from "react"
import githubDarkCss from "highlight.js/styles/github-dark.css?inline"
import githubLightCss from "highlight.js/styles/github.css?inline"
const THEME_STYLE_ID = "hljs-theme-style"
function getOrCreateThemeStyleElement() {
let styleElement = document.getElementById(THEME_STYLE_ID)
if (!styleElement) {
styleElement = document.createElement("style")
styleElement.id = THEME_STYLE_ID
document.head.appendChild(styleElement)
}
return styleElement
}
export function useHighlightTheme() {
useEffect(() => {
const root = document.documentElement
const styleElement = getOrCreateThemeStyleElement()
const applyTheme = () => {
const nextThemeCss = root.classList.contains("dark")
? githubDarkCss
: githubLightCss
styleElement.textContent = nextThemeCss
}
applyTheme()
const observer = new MutationObserver(() => {
applyTheme()
})
observer.observe(root, {
attributes: true,
attributeFilter: ["class"],
})
return () => {
observer.disconnect()
}
}, [])
}
-63
View File
@@ -157,69 +157,6 @@
height: calc(100svh - 3.5rem);
}
/* Markdown code highlighting (rehype-highlight / highlight.js classes) */
.prose pre code.hljs,
.prose pre code[class*="language-"] {
display: block;
overflow-x: auto;
background: transparent;
padding: 0;
color: #e4e4e7;
}
.prose pre code .hljs-comment,
.prose pre code .hljs-quote {
color: #71717a;
}
.prose pre code .hljs-keyword,
.prose pre code .hljs-selector-tag,
.prose pre code .hljs-subst {
color: #f472b6;
}
.prose pre code .hljs-string,
.prose pre code .hljs-doctag,
.prose pre code .hljs-regexp,
.prose pre code .hljs-addition,
.prose pre code .hljs-attribute,
.prose pre code .hljs-template-tag,
.prose pre code .hljs-template-variable {
color: #34d399;
}
.prose pre code .hljs-number,
.prose pre code .hljs-literal,
.prose pre code .hljs-bullet,
.prose pre code .hljs-meta,
.prose pre code .hljs-built_in,
.prose pre code .hljs-builtin-name,
.prose pre code .hljs-symbol,
.prose pre code .hljs-variable,
.prose pre code .hljs-link,
.prose pre code .hljs-type,
.prose pre code .hljs-selector-class,
.prose pre code .hljs-selector-attr,
.prose pre code .hljs-selector-pseudo {
color: #22d3ee;
}
.prose pre code .hljs-title,
.prose pre code .hljs-section,
.prose pre code .hljs-name,
.prose pre code .hljs-selector-id,
.prose pre code .hljs-deletion {
color: #60a5fa;
}
.prose pre code .hljs-emphasis {
font-style: italic;
}
.prose pre code .hljs-strong {
font-weight: 700;
}
/* Typing indicator animations */
@keyframes shimmer {
0% {
+12 -3
View File
@@ -3,6 +3,7 @@ import { RouterProvider, createRouter } from "@tanstack/react-router"
import { StrictMode } from "react"
import ReactDOM from "react-dom/client"
import { useHighlightTheme } from "./hooks/use-highlight-theme"
import "./i18n"
import "./index.css"
import { routeTree } from "./routeTree.gen"
@@ -22,14 +23,22 @@ declare module "@tanstack/react-router" {
}
}
function AppProviders() {
useHighlightTheme()
return (
<QueryClientProvider client={queryClient}>
<RouterProvider router={router} />
</QueryClientProvider>
)
}
const rootElement = document.getElementById("root")!
if (!rootElement.innerHTML) {
const root = ReactDOM.createRoot(rootElement)
root.render(
<StrictMode>
<QueryClientProvider client={queryClient}>
<RouterProvider router={router} />
</QueryClientProvider>
<AppProviders />
</StrictMode>,
)
}