feat(code-block): user-configurable Shiki theme (light/dark independent) - #142
Merged
Merged
Conversation
Owner
|
我之前改了用户信息,导致后面的 commit hash 都变了,所以你当前的 PR 分支需要基于新的历史重新整理一下。麻烦先备份原分支,然后从最新的 git fetch upstream --prune --force
git switch <PR分支名>
git branch backup/<PR分支名>-before-rewrite
git switch -c <PR分支名>-rebuilt upstream/main
git cherry-pick <本次PR的commit1> <commit2> ...
git branch -f <PR分支名> HEAD
git switch <PR分支名>
git push --force-with-lease origin <PR分支名>强推原分支后,现有 PR 会自动更新,不需要关闭或重新提交。不要直接执行普通 感谢,麻烦了,之前用的是别的设备写的代码,导致用户信息填错了 |
Code block syntax highlighting was previously hardcoded to GitHub Dark/Light Default regardless of the active UI theme (src/lib/shikiTheme.ts returned github-*-default for any isDark). This made theme switching feel half-done — UI chrome changed but every code block still looked like GitHub. Now the user can pick any of Shiki's 65 bundled themes for each side (light + dark) in Appearance settings. Defaults preserve existing behavior (GitHub Light/Dark Default). Implementation: - themeStore: new codeBlockThemeLight / codeBlockThemeDark fields with localStorage persistence + export/import backup. - src/lib/codeBlockThemes.ts: wraps bundledThemesInfo from shiki/themes for the dropdown, plus normalizeCodeBlockTheme fallback. - shikiWorker: theme map comes from bundledThemesInfo (each entry's import field is a literal '@shikijs/themes/<id>' static import, so Vite generates one lazy chunk per theme). ensureTheme() lazy-loads on first highlight request for an unknown theme; init preloads the user's current 2 choices. - shikiWorkerClient.ensureShikiWorkerReady: reads localStorage to preload user's configured themes instead of hardcoded GitHub. - shikiTheme.getShikiTheme: new signature (isDark, light, dark) — picks by resolved mode, falls back to GitHub on invalid id. - useSyntaxHighlight: 3 call sites pass user's configured themes via a new useCodeBlockThemes() subscription (only re-renders when the IDs actually change — other appearance tweaks don't trigger code-block re-render). - CodeBlockThemeSettings.tsx: new Appearance section with two grouped <select> dropdowns + live Shiki-rendered preview. Per-theme chunks (one-dark-pro 33KB, dracula 21KB, github-dark-default 14KB, etc.) lazy-load on first use. Total init cost unchanged when user keeps GitHub defaults.
SsparKluo
force-pushed
the
feat/code-block-theme-settings
branch
from
July 19, 2026 12:42
04f96c5 to
40bb61a
Compare
Contributor
Author
|
已基于最新的 操作记录:
GitHub 这边显示 |
SsparKluo
added a commit
to SsparKluo/OpenCodeUI
that referenced
this pull request
Jul 20, 2026
Upstream (v0.6.33 → v0.6.34) merged in: - PR lehhair#142 (feat/code-block): user-configurable Shiki theme (originally our PR) - Settings dialog search + navigation + config editor drilldown - Sidebar UI tweaks (control interactions, folder drag-sort fix) - Settings: align CSS override toolbar - Markdown: 思考折叠时渲染单行预览 - Settings: default chat-related values - Various settings dialog component refactors Conflict resolution: - CodeBlockThemeSettings.tsx, themeStore.ts, locales, code-block-related code: take upstream — the merged PR lehhair#142 is the canonical implementation - ServersSettings.tsx: upstream rewrite + re-apply fork 'canDeleteDefault' (allow deleting default server on non-Tauri when others exist) - AppearanceSettings.tsx: take upstream import additions (DropdownMenu, MenuItem, SettingField, etc.) - SidePanel.tsx: drop upstream project selector dropdown + search input (fork customization: single 'add workspace' button next to New Chat) — also drop now-unused refs/state (projectsExpanded, searchInputRef, ...) - SidebarFooter.tsx: keep fork's slim cog+dot design — context stats stay in InputToolbar via ContextUsageButton (fork customization)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Code block syntax highlighting is hardcoded to GitHub Dark/Light Default regardless of the active UI theme.
getShikiTheme(isDark)insrc/lib/shikiTheme.tsignores the preset entirely, so every Shiki-rendered surface — fenced markdown code, bash tool commands, diffs, file previews — looks like GitHub even when the user has picked a different UI theme.Solution
Make the Shiki theme user-configurable in Appearance settings, with light and dark picked independently (each switches with the resolved color mode). Defaults preserve current behavior (GitHub Light/Dark Default), so existing users see no change.
Highlights
bundledThemesInfofromshiki/themesdirectly as the canonical catalog — no maintenance burden when Shiki adds new themes.import('@shikijs/themes/<id>')literal, so Vite generates one ~14–46 KB chunk per theme and only fetches on first use. Init preloads just the user's current 2 choices; total init cost unchanged for default users.BashRenderer,DiffViewer,CodeMirrorReadonly,CodeBlock,CodePreview,AttachmentDetailModal) go throughuseSyntaxHighlight, so changing the setting updates every code-bearing surface automatically.useCodeBlockThemes()hook subscribes to a derived string key, so code blocks only re-render when the theme IDs actually change — not on every appearance tweak.Implementation
themeStore: newcodeBlockThemeLight/codeBlockThemeDarkfields with localStorage persistence + export/import backup.src/lib/codeBlockThemes.ts: catalog wrappingbundledThemesInfo, withnormalizeCodeBlockThemefallback.src/workers/shikiWorker.ts: theme map frombundledThemesInfo, newensureTheme(instance, themeId)for lazy loading.src/lib/shikiWorkerClient.ts: init reads localStorage to preload user's choices (was hardcoded GitHub).src/lib/shikiTheme.ts: newgetShikiTheme(isDark, light, dark)signature, falls back to GitHub on invalid id.src/hooks/useSyntaxHighlight.ts: 3 call sites pass user's configured themes; newuseCodeBlockThemes()subscription.src/features/settings/components/CodeBlockThemeSettings.tsx: new Appearance section with two grouped<select>dropdowns (themes grouped by light/dark, but cross-picking allowed) + live Shiki-rendered preview.Backward compatibility
github-light-default/github-dark-default→ identical to current behaviorVerification
tsc --noEmit: cleanvitest: 525/525 passing (added 2 cases forgetShikiTheme)npm run build: success — per-theme chunks emitted as separate files (e.g.one-dark-pro-*.js33KB,dracula-*.js21KB,github-dark-default-*.js14KB)