Commit 5fb069f432799e0d17a7102fae70757e320dc0c5
1 parent
2fbc4504
feat: add markdown component
Showing
8 changed files
with
177 additions
and
0 deletions
package.json
src/components/Markdown/index.ts
0 → 100644
src/components/Markdown/src/index.vue
0 → 100644
1 | +<template> | |
2 | + <div class="markdown" ref="wrapRef" /> | |
3 | +</template> | |
4 | +<script lang="ts"> | |
5 | + import { | |
6 | + defineComponent, | |
7 | + ref, | |
8 | + onMounted, | |
9 | + unref, | |
10 | + PropType, | |
11 | + onUnmounted, | |
12 | + nextTick, | |
13 | + watchEffect, | |
14 | + } from 'vue'; | |
15 | + import Vditor from 'vditor'; | |
16 | + import 'vditor/dist/index.css'; | |
17 | + export default defineComponent({ | |
18 | + emits: ['update:value'], | |
19 | + props: { | |
20 | + height: { | |
21 | + type: Number as PropType<number>, | |
22 | + default: 360, | |
23 | + }, | |
24 | + value: { | |
25 | + type: String, | |
26 | + default: '', | |
27 | + }, | |
28 | + }, | |
29 | + setup(props, { attrs, emit }) { | |
30 | + const wrapRef = ref<Nullable<HTMLDivElement>>(null); | |
31 | + const vditorRef = ref<Nullable<Vditor>>(null); | |
32 | + | |
33 | + const initedRef = ref(false); | |
34 | + | |
35 | + function init() { | |
36 | + const wrapEl = unref(wrapRef); | |
37 | + if (!wrapEl) return; | |
38 | + const data = { ...attrs, ...props }; | |
39 | + vditorRef.value = new Vditor(wrapEl, { | |
40 | + mode: 'sv', | |
41 | + preview: { | |
42 | + actions: [], | |
43 | + }, | |
44 | + input: (v) => { | |
45 | + emit('update:value', v); | |
46 | + }, | |
47 | + ...data, | |
48 | + cache: { | |
49 | + enable: false, | |
50 | + }, | |
51 | + }); | |
52 | + initedRef.value = true; | |
53 | + } | |
54 | + | |
55 | + watchEffect(() => { | |
56 | + nextTick(() => { | |
57 | + const vditor = unref(vditorRef); | |
58 | + if (unref(initedRef) && props.value && vditor) { | |
59 | + vditor.setValue(props.value); | |
60 | + } | |
61 | + }); | |
62 | + }); | |
63 | + | |
64 | + onMounted(() => { | |
65 | + nextTick(() => { | |
66 | + init(); | |
67 | + }); | |
68 | + }); | |
69 | + | |
70 | + onUnmounted(() => { | |
71 | + const vditorInstance = unref(vditorRef); | |
72 | + if (!vditorInstance) return; | |
73 | + vditorInstance.destroy(); | |
74 | + }); | |
75 | + | |
76 | + return { | |
77 | + wrapRef, | |
78 | + getVditor: (): Vditor => vditorRef.value!, | |
79 | + }; | |
80 | + }, | |
81 | + }); | |
82 | +</script> | ... | ... |
src/components/Markdown/src/types.ts
0 → 100644
src/router/menus/modules/demo/editor.ts
0 → 100644
src/router/routes/modules/demo/editor.ts
0 → 100644
1 | +import type { AppRouteModule } from '/@/router/types'; | |
2 | + | |
3 | +import { PAGE_LAYOUT_COMPONENT } from '/@/router/constant'; | |
4 | + | |
5 | +export default { | |
6 | + layout: { | |
7 | + path: '/editor', | |
8 | + name: 'Editor', | |
9 | + component: PAGE_LAYOUT_COMPONENT, | |
10 | + redirect: '/editor/markdown', | |
11 | + meta: { | |
12 | + icon: 'ant-design:table-outlined', | |
13 | + title: '编辑器', | |
14 | + }, | |
15 | + }, | |
16 | + | |
17 | + routes: [ | |
18 | + { | |
19 | + path: '/markdown', | |
20 | + name: 'MarkdownDemo', | |
21 | + component: () => import('/@/views/demo/editor/Markdown.vue'), | |
22 | + meta: { | |
23 | + title: 'markdown编辑器', | |
24 | + }, | |
25 | + }, | |
26 | + ], | |
27 | +} as AppRouteModule; | ... | ... |
src/views/demo/editor/Markdown.vue
0 → 100644
1 | +<template> | |
2 | + <div class="p-4"> | |
3 | + <a-button @click="toggleTheme" class="mb-2" type="primary">黑暗主题</a-button> | |
4 | + <MarkDown v-model:value="value" ref="markDownRef" /> | |
5 | + </div> | |
6 | +</template> | |
7 | +<script lang="ts"> | |
8 | + import { defineComponent, ref, unref } from 'vue'; | |
9 | + import { MarkDown, MarkDownActionType } from '/@/components/Markdown'; | |
10 | + export default defineComponent({ | |
11 | + components: { MarkDown }, | |
12 | + setup() { | |
13 | + const markDownRef = ref<Nullable<MarkDownActionType>>(null); | |
14 | + const valueRef = ref(` | |
15 | +# title | |
16 | + | |
17 | +# content | |
18 | +`); | |
19 | + | |
20 | + function toggleTheme() { | |
21 | + const markDown = unref(markDownRef); | |
22 | + if (!markDown) return; | |
23 | + const vditor = markDown.getVditor(); | |
24 | + vditor.setTheme('dark'); | |
25 | + } | |
26 | + return { | |
27 | + value: valueRef, | |
28 | + toggleTheme, | |
29 | + markDownRef, | |
30 | + }; | |
31 | + }, | |
32 | + }); | |
33 | +</script> | ... | ... |
yarn.lock
... | ... | @@ -2346,6 +2346,11 @@ detect-indent@6.0.0: |
2346 | 2346 | resolved "https://registry.npmjs.org/detect-indent/-/detect-indent-6.0.0.tgz#0abd0f549f69fc6659a254fe96786186b6f528fd" |
2347 | 2347 | integrity sha512-oSyFlqaTHCItVRGK5RmrmjB+CmaMOW7IaNA/kdxqhoa6d17j/5ce9O9eWXmV/KEdRwqpQA+Vqe8a8Bsybu4YnA== |
2348 | 2348 | |
2349 | +diff-match-patch@^1.0.5: | |
2350 | + version "1.0.5" | |
2351 | + resolved "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.5.tgz#abb584d5f10cd1196dfc55aa03701592ae3f7b37" | |
2352 | + integrity sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw== | |
2353 | + | |
2349 | 2354 | diff@^4.0.1: |
2350 | 2355 | version "4.0.2" |
2351 | 2356 | resolved "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" |
... | ... | @@ -6980,6 +6985,13 @@ vary@^1.1.2: |
6980 | 6985 | resolved "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" |
6981 | 6986 | integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= |
6982 | 6987 | |
6988 | +vditor@^3.5.5: | |
6989 | + version "3.5.5" | |
6990 | + resolved "https://registry.npmjs.org/vditor/-/vditor-3.5.5.tgz#03b7c965470fd434cd098e3f6ac6c7e65ca5a52a" | |
6991 | + integrity sha512-NpBa0c1tK3jnH/E+rWkDO2x/bDx33KIWuThjF70gING58zuluxicGczuVb2KvdLxWoozJ6MaH5DQjj66Jct1QA== | |
6992 | + dependencies: | |
6993 | + diff-match-patch "^1.0.5" | |
6994 | + | |
6983 | 6995 | vfile-location@^3.0.0: |
6984 | 6996 | version "3.1.0" |
6985 | 6997 | resolved "https://registry.npmjs.org/vfile-location/-/vfile-location-3.1.0.tgz#81cd8a04b0ac935185f4fce16f270503fc2f692f" | ... | ... |