♻️ Refactor the Markdown preview theme application logic

This commit is contained in:
2025-11-21 20:20:06 +08:00
parent 339ed53c2e
commit 4e82e2f6f7
6 changed files with 71 additions and 17 deletions

View File

@@ -142,7 +142,7 @@ onBeforeUnmount(() => {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
font-family: var(--voidraft-font-mono, SFMono-Regular, Consolas, "Liberation Mono", Menlo, monospace); font-family: var(--voidraft-font-mono),serif;
} }
.loading-word { .loading-word {

View File

@@ -30,7 +30,7 @@ import {generateContentHash} from "@/common/utils/hashUtils";
import {createTimerManager, type TimerManager} from '@/common/utils/timerUtils'; import {createTimerManager, type TimerManager} from '@/common/utils/timerUtils';
import {EDITOR_CONFIG} from '@/common/constant/editor'; import {EDITOR_CONFIG} from '@/common/constant/editor';
import {createHttpClientExtension} from "@/views/editor/extensions/httpclient"; import {createHttpClientExtension} from "@/views/editor/extensions/httpclient";
import {markdownPreviewExtension} from "@/views/editor/extensions/markdownPreview"; import {markdownPreviewExtension, updateMarkdownPreviewTheme} from "@/views/editor/extensions/markdownPreview";
import {createDebounce} from '@/common/utils/debounce'; import {createDebounce} from '@/common/utils/debounce';
export interface DocumentStats { export interface DocumentStats {
@@ -642,6 +642,13 @@ export const useEditorStore = defineStore('editor', () => {
}); });
}; };
// 应用 Markdown 预览主题
const applyPreviewThemeSettings = () => {
editorCache.values().forEach(instance => {
updateMarkdownPreviewTheme(instance.view);
});
};
// 应用Tab设置 // 应用Tab设置
const applyTabSettings = () => { const applyTabSettings = () => {
editorCache.values().forEach(instance => { editorCache.values().forEach(instance => {
@@ -783,6 +790,7 @@ export const useEditorStore = defineStore('editor', () => {
// 配置更新方法 // 配置更新方法
applyFontSettings, applyFontSettings,
applyThemeSettings, applyThemeSettings,
applyPreviewThemeSettings,
applyTabSettings, applyTabSettings,
applyKeymapSettings, applyKeymapSettings,

View File

@@ -141,6 +141,7 @@ export const useThemeStore = defineStore('theme', () => {
const editorStore = useEditorStore(); const editorStore = useEditorStore();
editorStore?.applyThemeSettings(); editorStore?.applyThemeSettings();
editorStore?.applyPreviewThemeSettings();
}; };
return { return {

View File

@@ -35,17 +35,16 @@ onMounted(async () => {
// onBeforeUnmount(() => { // onBeforeUnmount(() => {
// editorStore.clearAllEditors(); // editorStore.clearAllEditors();
//
// }); // });
</script> </script>
<template> <template>
<div class="editor-container"> <div class="editor-container">
<div ref="editorElement" class="editor"></div>
<Toolbar/>
<transition name="loading-fade"> <transition name="loading-fade">
<LoadingScreen v-if="editorStore.isLoading && enableLoadingAnimation" text="VOIDRAFT"/> <LoadingScreen v-if="editorStore.isLoading && enableLoadingAnimation" text="VOIDRAFT"/>
</transition> </transition>
<div ref="editorElement" class="editor"></div>
<Toolbar/>
</div> </div>
</template> </template>

View File

@@ -2,6 +2,7 @@
* Markdown 预览扩展主入口 * Markdown 预览扩展主入口
*/ */
import { EditorView } from "@codemirror/view"; import { EditorView } from "@codemirror/view";
import { Compartment } from "@codemirror/state";
import { useThemeStore } from "@/stores/themeStore"; import { useThemeStore } from "@/stores/themeStore";
import { usePanelStore } from "@/stores/panelStore"; import { usePanelStore } from "@/stores/panelStore";
import { useDocumentStore } from "@/stores/documentStore"; import { useDocumentStore } from "@/stores/documentStore";
@@ -52,11 +53,30 @@ export function toggleMarkdownPreview(view: EditorView): boolean {
/** /**
* 导出 Markdown 预览扩展 * 导出 Markdown 预览扩展
*/ */
export function markdownPreviewExtension() { const previewThemeCompartment = new Compartment();
const buildPreviewTheme = () => {
const themeStore = useThemeStore(); const themeStore = useThemeStore();
const colors = themeStore.currentColors; const colors = themeStore.currentColors;
return colors ? createMarkdownPreviewTheme(colors) : EditorView.baseTheme({});
};
const theme = colors ? createMarkdownPreviewTheme(colors) : EditorView.baseTheme({}); export function markdownPreviewExtension() {
return [
return [previewPanelState, previewPanelPlugin, theme]; previewPanelState,
previewPanelPlugin,
previewThemeCompartment.of(buildPreviewTheme())
];
}
export function updateMarkdownPreviewTheme(view: EditorView): void {
if (!view?.dispatch) return;
try {
view.dispatch({
effects: previewThemeCompartment.reconfigure(buildPreviewTheme())
});
} catch (error) {
console.error("Failed to update markdown preview theme", error);
}
} }

View File

@@ -22,7 +22,7 @@ export class MarkdownPreviewPanel {
private readonly resizeHandle: HTMLDivElement; private readonly resizeHandle: HTMLDivElement;
private readonly content: HTMLDivElement; private readonly content: HTMLDivElement;
private view: EditorView; private view: EditorView;
private themeUnwatch?: () => void; private themeUnwatchers: Array<() => void> = [];
private lastRenderedContent: string = ""; private lastRenderedContent: string = "";
private readonly debouncedUpdate: ReturnType<typeof createDebounce>; private readonly debouncedUpdate: ReturnType<typeof createDebounce>;
private isDestroyed: boolean = false; // 标记面板是否已销毁 private isDestroyed: boolean = false; // 标记面板是否已销毁
@@ -38,11 +38,22 @@ export class MarkdownPreviewPanel {
// 监听主题变化 // 监听主题变化
const themeStore = useThemeStore(); const themeStore = useThemeStore();
this.themeUnwatch = watch(() => themeStore.isDarkMode, (isDark) => { this.themeUnwatchers.push(
const newTheme = isDark ? "dark" : "default"; watch(() => themeStore.isDarkMode, (isDark) => {
updateMermaidTheme(newTheme); const newTheme = isDark ? "dark" : "default";
this.lastRenderedContent = ""; // 清空缓存,强制重新渲染 updateMermaidTheme(newTheme);
}); this.resetPreviewContent();
})
);
this.themeUnwatchers.push(
watch(
() => themeStore.currentColors,
() => {
this.resetPreviewContent();
},
{ deep: true }
)
);
// 创建 DOM 结构 // 创建 DOM 结构
this.dom = document.createElement("div"); this.dom = document.createElement("div");
@@ -315,6 +326,16 @@ export class MarkdownPreviewPanel {
}); });
} }
private resetPreviewContent(): void {
if (this.isDestroyed) {
return;
}
this.md = createMarkdownRenderer();
this.lastRenderedContent = "";
this.updateContentInternal();
}
/** /**
* 响应编辑器更新 * 响应编辑器更新
*/ */
@@ -342,6 +363,11 @@ export class MarkdownPreviewPanel {
// 清空缓存 // 清空缓存
this.lastRenderedContent = ""; this.lastRenderedContent = "";
if (this.themeUnwatchers.length) {
this.themeUnwatchers.forEach(unwatch => unwatch());
this.themeUnwatchers = [];
}
} }
/** /**