Commit a89e497e82829e9f7f26c7df1e42ed0d74e5dd71

Authored by Wit〆苗大
Committed by GitHub
1 parent 0f50e045

fix: markdown深色模式内容区和代码块未适配bug; markdownViewer改为vidtor自带预览模式 (#2023)

* fix(Markdown): 修复深色模式 内容区和代码块 未改变主题bug

* perf(Markdown): MarkDown组件示例增加不同功能示例; 切换深色主题按钮 同时改变 内容区和代码块主题

* perf(MarkdownViewer): MarkdownViewer改为vditor自带的预览模式; 同时适配深色模式

Co-authored-by: 苗大 <v.caoshm@yoozoo.com>
src/components/Markdown/src/Markdown.vue
... ... @@ -19,6 +19,7 @@
19 19 import { useModalContext } from '../../Modal';
20 20 import { useRootSetting } from '/@/hooks/setting/useRootSetting';
21 21 import { onMountedOrActivated } from '/@/hooks/core/onMountedOrActivated';
  22 + import { getTheme } from './getTheme';
22 23  
23 24 type Lang = 'zh_CN' | 'en_US' | 'ja_JP' | 'ko_KR' | undefined;
24 25  
... ... @@ -46,8 +47,9 @@
46 47 if (!inited) {
47 48 return;
48 49 }
49   - const theme = val === 'dark' ? 'dark' : 'classic';
50   - instance.getVditor()?.setTheme(theme);
  50 + instance
  51 + .getVditor()
  52 + ?.setTheme(getTheme(val) as any, getTheme(val, 'content'), getTheme(val, 'code'));
51 53 },
52 54 {
53 55 immediate: true,
... ... @@ -87,13 +89,22 @@
87 89 if (!wrapEl) return;
88 90 const bindValue = { ...attrs, ...props };
89 91 const insEditor = new Vditor(wrapEl, {
90   - theme: getDarkMode.value === 'dark' ? 'dark' : 'classic',
  92 + // 设置外观主题
  93 + theme: getTheme(getDarkMode.value) as any,
91 94 lang: unref(getCurrentLang),
92 95 mode: 'sv',
93 96 fullscreen: {
94 97 index: 520,
95 98 },
96 99 preview: {
  100 + theme: {
  101 + // 设置内容主题
  102 + current: getTheme(getDarkMode.value, 'content'),
  103 + },
  104 + hljs: {
  105 + // 设置代码块主题
  106 + style: getTheme(getDarkMode.value, 'code'),
  107 + },
97 108 actions: [],
98 109 },
99 110 input: (v) => {
... ...
src/components/Markdown/src/MarkdownViewer.vue
1 1 <template>
2   - <!-- eslint-disable vue/no-v-html -->
3   - <div v-html="getHtmlData" :class="$props.class" class="markdown-viewer"></div>
  2 + <div ref="viewerRef" id="markdownViewer" :class="$props.class"></div>
4 3 </template>
5 4  
6 5 <script lang="ts" setup>
7   - import { computed, defineProps } from 'vue';
8   - import showdown from 'showdown';
9   -
10   - const converter = new showdown.Converter();
11   - converter.setOption('tables', true);
  6 + import { defineProps, onBeforeUnmount, onDeactivated, Ref, ref, unref, watch } from 'vue';
  7 + import VditorPreview from 'vditor/dist/method.min';
  8 + import { onMountedOrActivated } from '/@/hooks/core/onMountedOrActivated';
  9 + import { useRootSetting } from '/@/hooks/setting/useRootSetting';
  10 + import { getTheme } from './getTheme';
12 11 const props = defineProps({
13 12 value: { type: String },
14 13 class: { type: String },
15 14 });
16   - const getHtmlData = computed(() => converter.makeHtml(props.value || ''));
17   -</script>
  15 + const viewerRef = ref<ElRef>(null);
  16 + const vditorPreviewRef = ref(null) as Ref<Nullable<VditorPreview>>;
  17 + const { getDarkMode } = useRootSetting();
  18 +
  19 + function init() {
  20 + const viewerEl = unref(viewerRef) as HTMLElement;
  21 + vditorPreviewRef.value = VditorPreview.preview(viewerEl, props.value, {
  22 + mode: getTheme(getDarkMode.value, 'content'),
  23 + theme: {
  24 + // 设置内容主题
  25 + current: getTheme(getDarkMode.value, 'content'),
  26 + },
  27 + hljs: {
  28 + // 设置代码块主题
  29 + style: getTheme(getDarkMode.value, 'code'),
  30 + },
  31 + });
  32 + }
  33 + watch(
  34 + () => getDarkMode.value,
  35 + (val) => {
  36 + VditorPreview.setContentTheme(getTheme(val, 'content'));
  37 + VditorPreview.setCodeTheme(getTheme(val, 'code'));
  38 + init();
  39 + },
  40 + );
18 41  
19   -<style scoped>
20   - .markdown-viewer {
21   - width: 100%;
  42 + watch(
  43 + () => props.value,
  44 + (v, oldValue) => {
  45 + v !== oldValue && init();
  46 + },
  47 + );
  48 +
  49 + function destroy() {
  50 + const vditorInstance = unref(vditorPreviewRef);
  51 + if (!vditorInstance) return;
  52 + try {
  53 + vditorInstance?.destroy?.();
  54 + } catch (error) {}
  55 + vditorPreviewRef.value = null;
22 56 }
23   -</style>
  57 +
  58 + onMountedOrActivated(init);
  59 +
  60 + onBeforeUnmount(destroy);
  61 + onDeactivated(destroy);
  62 +</script>
... ...
src/components/Markdown/src/getTheme.ts 0 → 100644
  1 +/**
  2 + * 获取主题类型 深色浅色模式 对应的值
  3 + * @param darkModeVal 深色模式值
  4 + * @param themeMode 主题类型——外观(默认), 内容, 代码块
  5 + */
  6 +export const getTheme = (
  7 + darkModeVal: 'light' | 'dark' | string,
  8 + themeMode: 'default' | 'content' | 'code' = 'default',
  9 +) => {
  10 + const isDark = darkModeVal === 'dark';
  11 + switch (themeMode) {
  12 + case 'default':
  13 + return isDark ? 'dark' : 'classic';
  14 + case 'content':
  15 + return isDark ? 'dark' : 'light';
  16 + case 'code':
  17 + return isDark ? 'dracula' : 'github';
  18 + }
  19 +};
... ...
src/views/demo/editor/markdown/index.vue
... ... @@ -28,16 +28,53 @@
28 28 setup() {
29 29 const markDownRef = ref<Nullable<MarkDownActionType>>(null);
30 30 const valueRef = ref(`
31   -# title
  31 +# 标题h1
32 32  
33   -# content
  33 +##### 标题h5
  34 +
  35 +**加粗**
  36 +*斜体*
  37 +~~删除线~~
  38 +[链接](https://github.com/vbenjs/vue-vben-admin)
  39 +↓分割线↓
  40 +
  41 +---
  42 +
  43 +
  44 +* 无序列表1
  45 + * 无序列表1.1
  46 +
  47 +1. 有序列表1
  48 +2. 有序列表2
  49 +
  50 +* [ ] 任务列表1
  51 +* [x] 任务列表2
  52 +
  53 +> 引用示例
  54 +
  55 +\`\`\`js
  56 +// 代码块:
  57 +(() => {
  58 + var htmlRoot = document.getElementById('htmlRoot');
  59 + var theme = window.localStorage.getItem('__APP__DARK__MODE__');
  60 + if (htmlRoot && theme) {
  61 + htmlRoot.setAttribute('data-theme', theme);
  62 + theme = htmlRoot = null;
  63 + }
  64 +})();
  65 +\`\`\`
  66 +
  67 +| 表格 | 示例 | 🎉️ |
  68 +| --- | --- | --- |
  69 +| 1 | 2 | 3 |
  70 +| 4 | 5 | 6 |
34 71 `);
35 72  
36 73 function toggleTheme() {
37 74 const markDown = unref(markDownRef);
38 75 if (!markDown) return;
39 76 const vditor = markDown.getVditor();
40   - vditor.setTheme('dark');
  77 + vditor.setTheme('dark', 'dark', 'dracula');
41 78 }
42 79  
43 80 function handleChange(v: string) {
... ...