diff --git a/web/frontend/package.json b/web/frontend/package.json index a8a963ca9..7595c46bf 100644 --- a/web/frontend/package.json +++ b/web/frontend/package.json @@ -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", diff --git a/web/frontend/pnpm-lock.yaml b/web/frontend/pnpm-lock.yaml index e12e6b351..721bd7e75 100644 --- a/web/frontend/pnpm-lock.yaml +++ b/web/frontend/pnpm-lock.yaml @@ -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) diff --git a/web/frontend/src/components/agent/skills/detail-sheet.tsx b/web/frontend/src/components/agent/skills/detail-sheet.tsx index 41f56b057..4579926d8 100644 --- a/web/frontend/src/components/agent/skills/detail-sheet.tsx +++ b/web/frontend/src/components/agent/skills/detail-sheet.tsx @@ -172,7 +172,7 @@ export function DetailSheet({ {detailView === "preview" ? ( -
+
{ + 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() + } + }, []) +} diff --git a/web/frontend/src/index.css b/web/frontend/src/index.css index 7958233f3..fc55a3a32 100644 --- a/web/frontend/src/index.css +++ b/web/frontend/src/index.css @@ -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% { diff --git a/web/frontend/src/main.tsx b/web/frontend/src/main.tsx index 81e72c29f..17eb18291 100644 --- a/web/frontend/src/main.tsx +++ b/web/frontend/src/main.tsx @@ -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 ( + + + + ) +} + const rootElement = document.getElementById("root")! if (!rootElement.innerHTML) { const root = ReactDOM.createRoot(rootElement) root.render( - - - + , ) }