fix: markdown深色模式内容区和代码块未适配bug; markdownViewer改为vidtor自带预览模式 (#2023)
* fix(Markdown): 修复深色模式 内容区和代码块 未改变主题bug * perf(Markdown): MarkDown组件示例增加不同功能示例; 切换深色主题按钮 同时改变 内容区和代码块主题 * perf(MarkdownViewer): MarkdownViewer改为vditor自带的预览模式; 同时适配深色模式 Co-authored-by: 苗大 <v.caoshm@yoozoo.com>
This commit is contained in:
parent
0f50e0458e
commit
a89e497e82
|
|
@ -19,6 +19,7 @@
|
|||
import { useModalContext } from '../../Modal';
|
||||
import { useRootSetting } from '/@/hooks/setting/useRootSetting';
|
||||
import { onMountedOrActivated } from '/@/hooks/core/onMountedOrActivated';
|
||||
import { getTheme } from './getTheme';
|
||||
|
||||
type Lang = 'zh_CN' | 'en_US' | 'ja_JP' | 'ko_KR' | undefined;
|
||||
|
||||
|
|
@ -46,8 +47,9 @@
|
|||
if (!inited) {
|
||||
return;
|
||||
}
|
||||
const theme = val === 'dark' ? 'dark' : 'classic';
|
||||
instance.getVditor()?.setTheme(theme);
|
||||
instance
|
||||
.getVditor()
|
||||
?.setTheme(getTheme(val) as any, getTheme(val, 'content'), getTheme(val, 'code'));
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
|
|
@ -87,13 +89,22 @@
|
|||
if (!wrapEl) return;
|
||||
const bindValue = { ...attrs, ...props };
|
||||
const insEditor = new Vditor(wrapEl, {
|
||||
theme: getDarkMode.value === 'dark' ? 'dark' : 'classic',
|
||||
// 设置外观主题
|
||||
theme: getTheme(getDarkMode.value) as any,
|
||||
lang: unref(getCurrentLang),
|
||||
mode: 'sv',
|
||||
fullscreen: {
|
||||
index: 520,
|
||||
},
|
||||
preview: {
|
||||
theme: {
|
||||
// 设置内容主题
|
||||
current: getTheme(getDarkMode.value, 'content'),
|
||||
},
|
||||
hljs: {
|
||||
// 设置代码块主题
|
||||
style: getTheme(getDarkMode.value, 'code'),
|
||||
},
|
||||
actions: [],
|
||||
},
|
||||
input: (v) => {
|
||||
|
|
|
|||
|
|
@ -1,23 +1,62 @@
|
|||
<template>
|
||||
<!-- eslint-disable vue/no-v-html -->
|
||||
<div v-html="getHtmlData" :class="$props.class" class="markdown-viewer"></div>
|
||||
<div ref="viewerRef" id="markdownViewer" :class="$props.class"></div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, defineProps } from 'vue';
|
||||
import showdown from 'showdown';
|
||||
|
||||
const converter = new showdown.Converter();
|
||||
converter.setOption('tables', true);
|
||||
import { defineProps, onBeforeUnmount, onDeactivated, Ref, ref, unref, watch } from 'vue';
|
||||
import VditorPreview from 'vditor/dist/method.min';
|
||||
import { onMountedOrActivated } from '/@/hooks/core/onMountedOrActivated';
|
||||
import { useRootSetting } from '/@/hooks/setting/useRootSetting';
|
||||
import { getTheme } from './getTheme';
|
||||
const props = defineProps({
|
||||
value: { type: String },
|
||||
class: { type: String },
|
||||
});
|
||||
const getHtmlData = computed(() => converter.makeHtml(props.value || ''));
|
||||
</script>
|
||||
const viewerRef = ref<ElRef>(null);
|
||||
const vditorPreviewRef = ref(null) as Ref<Nullable<VditorPreview>>;
|
||||
const { getDarkMode } = useRootSetting();
|
||||
|
||||
<style scoped>
|
||||
.markdown-viewer {
|
||||
width: 100%;
|
||||
function init() {
|
||||
const viewerEl = unref(viewerRef) as HTMLElement;
|
||||
vditorPreviewRef.value = VditorPreview.preview(viewerEl, props.value, {
|
||||
mode: getTheme(getDarkMode.value, 'content'),
|
||||
theme: {
|
||||
// 设置内容主题
|
||||
current: getTheme(getDarkMode.value, 'content'),
|
||||
},
|
||||
hljs: {
|
||||
// 设置代码块主题
|
||||
style: getTheme(getDarkMode.value, 'code'),
|
||||
},
|
||||
});
|
||||
}
|
||||
</style>
|
||||
watch(
|
||||
() => getDarkMode.value,
|
||||
(val) => {
|
||||
VditorPreview.setContentTheme(getTheme(val, 'content'));
|
||||
VditorPreview.setCodeTheme(getTheme(val, 'code'));
|
||||
init();
|
||||
},
|
||||
);
|
||||
|
||||
watch(
|
||||
() => props.value,
|
||||
(v, oldValue) => {
|
||||
v !== oldValue && init();
|
||||
},
|
||||
);
|
||||
|
||||
function destroy() {
|
||||
const vditorInstance = unref(vditorPreviewRef);
|
||||
if (!vditorInstance) return;
|
||||
try {
|
||||
vditorInstance?.destroy?.();
|
||||
} catch (error) {}
|
||||
vditorPreviewRef.value = null;
|
||||
}
|
||||
|
||||
onMountedOrActivated(init);
|
||||
|
||||
onBeforeUnmount(destroy);
|
||||
onDeactivated(destroy);
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
/**
|
||||
* 获取主题类型 深色浅色模式 对应的值
|
||||
* @param darkModeVal 深色模式值
|
||||
* @param themeMode 主题类型——外观(默认), 内容, 代码块
|
||||
*/
|
||||
export const getTheme = (
|
||||
darkModeVal: 'light' | 'dark' | string,
|
||||
themeMode: 'default' | 'content' | 'code' = 'default',
|
||||
) => {
|
||||
const isDark = darkModeVal === 'dark';
|
||||
switch (themeMode) {
|
||||
case 'default':
|
||||
return isDark ? 'dark' : 'classic';
|
||||
case 'content':
|
||||
return isDark ? 'dark' : 'light';
|
||||
case 'code':
|
||||
return isDark ? 'dracula' : 'github';
|
||||
}
|
||||
};
|
||||
|
|
@ -28,16 +28,53 @@
|
|||
setup() {
|
||||
const markDownRef = ref<Nullable<MarkDownActionType>>(null);
|
||||
const valueRef = ref(`
|
||||
# title
|
||||
# 标题h1
|
||||
|
||||
# content
|
||||
##### 标题h5
|
||||
|
||||
**加粗**
|
||||
*斜体*
|
||||
~~删除线~~
|
||||
[链接](https://github.com/vbenjs/vue-vben-admin)
|
||||
↓分割线↓
|
||||
|
||||
---
|
||||
|
||||
|
||||
* 无序列表1
|
||||
* 无序列表1.1
|
||||
|
||||
1. 有序列表1
|
||||
2. 有序列表2
|
||||
|
||||
* [ ] 任务列表1
|
||||
* [x] 任务列表2
|
||||
|
||||
> 引用示例
|
||||
|
||||
\`\`\`js
|
||||
// 代码块:
|
||||
(() => {
|
||||
var htmlRoot = document.getElementById('htmlRoot');
|
||||
var theme = window.localStorage.getItem('__APP__DARK__MODE__');
|
||||
if (htmlRoot && theme) {
|
||||
htmlRoot.setAttribute('data-theme', theme);
|
||||
theme = htmlRoot = null;
|
||||
}
|
||||
})();
|
||||
\`\`\`
|
||||
|
||||
| 表格 | 示例 | 🎉️ |
|
||||
| --- | --- | --- |
|
||||
| 1 | 2 | 3 |
|
||||
| 4 | 5 | 6 |
|
||||
`);
|
||||
|
||||
function toggleTheme() {
|
||||
const markDown = unref(markDownRef);
|
||||
if (!markDown) return;
|
||||
const vditor = markDown.getVditor();
|
||||
vditor.setTheme('dark');
|
||||
vditor.setTheme('dark', 'dark', 'dracula');
|
||||
}
|
||||
|
||||
function handleChange(v: string) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue