138 lines
4.2 KiB
Vue
138 lines
4.2 KiB
Vue
<script setup lang="ts">
|
|
import { Editor } from '@bytemd/vue-next'
|
|
import type { BytemdPlugin } from "bytemd";
|
|
import gfm from '@bytemd/plugin-gfm'
|
|
import gfmZhHans from "@bytemd/plugin-gfm/locales/zh_Hans.json";
|
|
import math from '@bytemd/plugin-math'
|
|
import highlight from '@bytemd/plugin-highlight'
|
|
import 'highlight.js/styles/default.css'
|
|
import mediumZoom from '@bytemd/plugin-medium-zoom'
|
|
import mermaid from '@bytemd/plugin-mermaid'
|
|
import breaks from '@bytemd/plugin-breaks'
|
|
import gemoji from '@bytemd/plugin-gemoji'
|
|
import rehypeHighlightCodeLines from "rehype-highlight-code-lines";
|
|
import {useNiMessage} from "~/composables/useNiMessage";
|
|
const niMessage = useNiMessage()
|
|
|
|
// Markdown内容
|
|
const content = ref('')
|
|
// 自定义插件
|
|
const customPlugins = {
|
|
actions: [{
|
|
title: '插入时间',
|
|
icon: h('span', { class: 'iconfont icon-time' }, ['🕒']),
|
|
handler: {
|
|
type: 'action',
|
|
click: (targer) => {
|
|
// wrapText 环绕式字符,像“”【】《》<>之类的
|
|
// replaceLines((line) => "- [ ] " + line); // 单向的
|
|
// editor.focus() 聚焦
|
|
targer.replaceLines((line) => new Date() + line);
|
|
targer.editor.focus();
|
|
},
|
|
},
|
|
}]
|
|
}
|
|
// 显示代码行号
|
|
const highlightCodeLinesPlugin = (): BytemdPlugin => {
|
|
return {
|
|
rehype: (processor) =>
|
|
processor
|
|
// 添加代码行号
|
|
.use(rehypeHighlightCodeLines, {
|
|
showLineNumbers: true,
|
|
lineContainerTagName: "div",
|
|
}),
|
|
};
|
|
};
|
|
// 代码复制按钮
|
|
const codeCopyPlugin = (): BytemdPlugin => {
|
|
const createCopyDom = (text: any): HTMLElement => {
|
|
const copyDom = document.createElement("div");
|
|
copyDom.className = "icon-[ph--copy-bold] absolute right-2 top-2 cursor-pointer";
|
|
copyDom.addEventListener("click", () => {
|
|
window.copyToClipboard(text);
|
|
niMessage.info("复制成功");
|
|
});
|
|
return copyDom;
|
|
};
|
|
|
|
return {
|
|
viewerEffect: ({ markdownBody }) => {
|
|
// 获取所有code标签
|
|
const els = markdownBody.querySelectorAll("pre>code");
|
|
if (els.length === 0) return;
|
|
|
|
// 往pre标签中append copy节点
|
|
els.forEach((itm: HTMLElement) => {
|
|
itm.parentNode.appendChild(createCopyDom(itm.innerText));
|
|
});
|
|
},
|
|
};
|
|
};
|
|
// ByteMD的插件
|
|
const plugins = [
|
|
// DFM 任务列表、表格、删除线
|
|
gfm({locale: gfmZhHans}),
|
|
// 数学公式
|
|
math(),
|
|
// 代码高亮
|
|
highlight(),
|
|
// 图片放大
|
|
mediumZoom(),
|
|
// Mermaid 图表(流程图、时序图、甘特图等)
|
|
mermaid(),
|
|
// 自动将换行符转换为 <br>,支持 GitHub 风格的换行行为
|
|
breaks(),
|
|
// 支持 GitHub 风格的表情符号短代码(如 :+1: → 👍)
|
|
gemoji(),
|
|
// 代码行号
|
|
highlightCodeLinesPlugin(),
|
|
// 代码复制
|
|
codeCopyPlugin(),
|
|
// 自定义插件
|
|
customPlugins,]
|
|
// 当Markdown内容修改时
|
|
const handleChange = (v: string) => {
|
|
content.value = v
|
|
}
|
|
// 模式 ['auto', 'split', 'tab'] 自动:根据屏幕宽度,自行选择分屏还是标签选择
|
|
const mode = ref('auto');
|
|
// 语言
|
|
const language = await import('~/node_modules/bytemd/locales/zh_Hans.json')
|
|
// 编辑器配置
|
|
const editorConfig = {
|
|
toolbar: [] // 清空默认工具栏
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<Editor class="byteMd"
|
|
:value="content"
|
|
:plugins="plugins"
|
|
:editorConfig
|
|
:locale="language"
|
|
@change="handleChange" >
|
|
<!-- 添加自定义工具栏 -->
|
|
<template #toolbar="{ editor }">
|
|
<div class="custom-toolbar">
|
|
<button
|
|
title="插入时间"
|
|
@click="editor.insertContent(`当前时间:${new Date().toLocaleString()}`)">
|
|
⏰ 插入时间
|
|
</button>
|
|
</div>
|
|
</template>
|
|
</Editor>
|
|
</template>
|
|
|
|
<style scoped lang="scss">
|
|
.byteMd{
|
|
position: relative;
|
|
height: 100%;
|
|
}
|
|
:global(.bytemd) {
|
|
height: 100%;
|
|
}
|
|
</style>
|