♻️ 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;
align-items: 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 {

View File

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

View File

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

View File

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

View File

@@ -2,6 +2,7 @@
* Markdown 预览扩展主入口
*/
import { EditorView } from "@codemirror/view";
import { Compartment } from "@codemirror/state";
import { useThemeStore } from "@/stores/themeStore";
import { usePanelStore } from "@/stores/panelStore";
import { useDocumentStore } from "@/stores/documentStore";
@@ -52,11 +53,30 @@ export function toggleMarkdownPreview(view: EditorView): boolean {
/**
* 导出 Markdown 预览扩展
*/
export function markdownPreviewExtension() {
const previewThemeCompartment = new Compartment();
const buildPreviewTheme = () => {
const themeStore = useThemeStore();
const colors = themeStore.currentColors;
const theme = colors ? createMarkdownPreviewTheme(colors) : EditorView.baseTheme({});
return [previewPanelState, previewPanelPlugin, theme];
return colors ? createMarkdownPreviewTheme(colors) : EditorView.baseTheme({});
};
export function markdownPreviewExtension() {
return [
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 content: HTMLDivElement;
private view: EditorView;
private themeUnwatch?: () => void;
private themeUnwatchers: Array<() => void> = [];
private lastRenderedContent: string = "";
private readonly debouncedUpdate: ReturnType<typeof createDebounce>;
private isDestroyed: boolean = false; // 标记面板是否已销毁
@@ -38,11 +38,22 @@ export class MarkdownPreviewPanel {
// 监听主题变化
const themeStore = useThemeStore();
this.themeUnwatch = watch(() => themeStore.isDarkMode, (isDark) => {
const newTheme = isDark ? "dark" : "default";
updateMermaidTheme(newTheme);
this.lastRenderedContent = ""; // 清空缓存,强制重新渲染
});
this.themeUnwatchers.push(
watch(() => themeStore.isDarkMode, (isDark) => {
const newTheme = isDark ? "dark" : "default";
updateMermaidTheme(newTheme);
this.resetPreviewContent();
})
);
this.themeUnwatchers.push(
watch(
() => themeStore.currentColors,
() => {
this.resetPreviewContent();
},
{ deep: true }
)
);
// 创建 DOM 结构
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();
}
/**
* 响应编辑器更新
*/
@@ -339,9 +360,14 @@ export class MarkdownPreviewPanel {
if (this.debouncedUpdate) {
this.debouncedUpdate.cancel();
}
// 清空缓存
this.lastRenderedContent = "";
if (this.themeUnwatchers.length) {
this.themeUnwatchers.forEach(unwatch => unwatch());
this.themeUnwatchers = [];
}
}
/**