feat(editor): Shiki highlighting for code files in PlanView and SkillsPage

Reuse the file-editor Shiki extension for the PlanView and SkillsPage editors,
gated to non-markdown files. Markdown sources keep the lezer highlighter (its
markdown-aware styling is better for editing and there's no Shiki view to match).

- PlanView: code files opened through it get Shiki colors; plan .md stays lezer.
- SkillsPage: code supporting files get Shiki colors; SKILL.md stays lezer.
This commit is contained in:
Bohdan Triapitsyn
2026-06-16 01:08:54 +03:00
parent 782982cdd3
commit e904abda04
2 changed files with 28 additions and 2 deletions
+14 -1
View File
@@ -19,6 +19,8 @@ import { getLanguageFromExtension } from '@/lib/toolHelpers';
import { useDeviceInfo } from '@/lib/device';
import { useThemeSystem } from '@/contexts/useThemeSystem';
import { createFlexokiCodeMirrorTheme } from '@/lib/codemirror/flexokiTheme';
import { shikiHighlightExtension } from '@/lib/codemirror/shikiHighlight';
import { getResolvedShikiTheme } from '@/lib/shiki/appThemeRegistry';
import { languageByExtension } from '@/lib/codemirror/languageByExtension';
import { useSessionUIStore } from '@/sync/session-ui-store';
import { useSessions } from '@/sync/sync-context';
@@ -344,11 +346,22 @@ export const PlanView: React.FC<PlanViewProps> = ({ targetPath = null }) => {
}, [cancel, commentText, editingDraftId, isMobile, lineSelection]);
const editorExtensions = React.useMemo(() => {
const extensions = [createFlexokiCodeMirrorTheme(currentTheme)];
// Shiki token colors only for code files; markdown keeps the lezer
// highlighter (markdown-aware bold headings etc., and no Shiki view to match).
const shikiLanguage = resolvedPath ? getLanguageFromExtension(resolvedPath) : null;
const useShiki = Boolean(shikiLanguage) && shikiLanguage !== 'markdown';
const extensions = [createFlexokiCodeMirrorTheme(currentTheme, useShiki ? { syntaxColors: false } : undefined)];
const language = languageByExtension(resolvedPath || 'plan.md');
if (language) {
extensions.push(language);
}
if (useShiki && shikiLanguage) {
extensions.push(shikiHighlightExtension({
language: shikiLanguage,
themeName: currentTheme.metadata.id,
theme: getResolvedShikiTheme(currentTheme),
}));
}
extensions.push(EditorView.lineWrapping);
return extensions;
}, [currentTheme, resolvedPath]);