mirror of
https://github.com/sipeed/picoclaw.git
synced 2026-06-12 18:08:54 +00:00
refactor(web): use official highlight themes for markdown
This commit is contained in:
@@ -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",
|
||||
|
||||
Generated
+3
@@ -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()
|
||||
}
|
||||
}, [])
|
||||
}
|
||||
@@ -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% {
|
||||
|
||||
@@ -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>,
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user