diff --git a/app/src/App.scss b/app/src/App.scss
index 4f55b6a..eb90e3c 100644
--- a/app/src/App.scss
+++ b/app/src/App.scss
@@ -108,29 +108,3 @@ $navbar-height: 64px;
.tree {
padding-top: $padding;
}
-
-// Syntax highlighting themes
-@import 'highlight.js/styles/github.css' layer(light-theme);
-@import 'highlight.js/styles/github-dark.css' layer(dark-theme);
-
-// Show light theme by default
-@layer light-theme {
- [data-mantine-color-scheme='light'] .markdown-preview {
- pre code.hljs {
- display: block;
- overflow-x: auto;
- padding: 1em;
- }
- }
-}
-
-// Show dark theme in dark mode
-@layer dark-theme {
- [data-mantine-color-scheme='dark'] .markdown-preview {
- pre code.hljs {
- display: block;
- overflow-x: auto;
- padding: 1em;
- }
- }
-}
diff --git a/app/src/components/editor/MarkdownPreview.test.tsx b/app/src/components/editor/MarkdownPreview.test.tsx
index 444ee3a..268d5b5 100644
--- a/app/src/components/editor/MarkdownPreview.test.tsx
+++ b/app/src/components/editor/MarkdownPreview.test.tsx
@@ -120,6 +120,34 @@ describe('MarkdownPreview', () => {
});
});
+ it('renders code blocks with correct structure for theme switching', async () => {
+ const content = '```javascript\nconst hello = "world";\n```';
+
+ render(
+
+ );
+
+ await waitFor(() => {
+ // Check that rehype-highlight generates the correct structure
+ const preElement = screen
+ .getByRole('code', { hidden: true })
+ .closest('pre');
+ const codeElement = preElement?.querySelector('code');
+
+ expect(preElement).toBeInTheDocument();
+ expect(codeElement).toBeInTheDocument();
+
+ // The code element should have hljs class for theme switching to work
+ expect(codeElement).toHaveClass('hljs');
+
+ // Should also have language class
+ expect(codeElement).toHaveClass('language-javascript');
+ });
+ });
+
it('handles image loading errors gracefully', async () => {
const content = '';
diff --git a/app/src/components/editor/MarkdownPreview.tsx b/app/src/components/editor/MarkdownPreview.tsx
index 74ab924..9e72472 100644
--- a/app/src/components/editor/MarkdownPreview.tsx
+++ b/app/src/components/editor/MarkdownPreview.tsx
@@ -10,6 +10,7 @@ import * as prod from 'react/jsx-runtime';
import { notifications } from '@mantine/notifications';
import { remarkWikiLinks } from '../../utils/remarkWikiLinks';
import { useWorkspace } from '../../hooks/useWorkspace';
+import { useHighlightTheme } from '../../hooks/useHighlightTheme';
interface MarkdownPreviewProps {
content: string;
@@ -28,12 +29,6 @@ interface MarkdownLinkProps {
[key: string]: unknown;
}
-interface MarkdownCodeProps {
- children: ReactNode;
- className?: string;
- [key: string]: unknown;
-}
-
const MarkdownPreview: React.FC = ({
content,
handleFileSelect,
@@ -42,7 +37,10 @@ const MarkdownPreview: React.FC = ({
null
);
const baseUrl = window.API_BASE_URL;
- const { currentWorkspace } = useWorkspace();
+ const { currentWorkspace, colorScheme } = useWorkspace();
+
+ // Use the highlight theme hook
+ useHighlightTheme(colorScheme === 'auto' ? 'light' : colorScheme);
const processor = useMemo(() => {
const handleLinkClick = (
@@ -107,13 +105,6 @@ const MarkdownPreview: React.FC = ({
{children}
),
- code: ({ children, className, ...props }: MarkdownCodeProps) => {
- return (
-
- {children}
-
- );
- },
},
} as Options);
}, [currentWorkspace?.name, baseUrl, handleFileSelect]);
diff --git a/app/src/hooks/useHighlightTheme.ts b/app/src/hooks/useHighlightTheme.ts
new file mode 100644
index 0000000..c814ee7
--- /dev/null
+++ b/app/src/hooks/useHighlightTheme.ts
@@ -0,0 +1,36 @@
+import { useEffect } from 'react';
+// Import theme CSS as text that will be bundled
+import atomOneLightTheme from 'highlight.js/styles/atom-one-light.css?inline';
+import atomOneDarkTheme from 'highlight.js/styles/atom-one-dark.css?inline';
+
+export const useHighlightTheme = (colorScheme: 'light' | 'dark') => {
+ useEffect(() => {
+ // Remove existing highlight theme
+ const existingStylesheet = document.querySelector(
+ 'style[data-highlight-theme]'
+ );
+ if (existingStylesheet) {
+ existingStylesheet.remove();
+ }
+
+ // Add new theme stylesheet using bundled CSS
+ const style = document.createElement('style');
+ style.setAttribute('data-highlight-theme', 'true');
+
+ if (colorScheme === 'dark') {
+ style.textContent = atomOneDarkTheme as string;
+ } else {
+ style.textContent = atomOneLightTheme as string;
+ }
+
+ document.head.appendChild(style);
+
+ return () => {
+ // Cleanup on unmount
+ const stylesheet = document.querySelector('style[data-highlight-theme]');
+ if (stylesheet) {
+ stylesheet.remove();
+ }
+ };
+ }, [colorScheme]);
+};