starwait/docs/f01-mrkdown/byteMD-Markdown.vue
2025-04-29 02:39:55 +08:00

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>