bytemd
ByteMD 是一个使用 Svelte 构建的 Markdown 编辑器组件。它也可以用于其他库/框架,例如 React、Vue 和 Angular。
特性
- 轻量级和框架无关:ByteMD 是用Svelte构建的。它编译为 vanilla JS DOM 操作,无需导入任何 UI 框架运行时包,这使其轻量级,并易于适应其他库/框架。
- 易于扩展:ByteMD 有一个插件系统来扩展基本的 Markdown 语法,这使得添加附加功能变得很容易,例如代码语法高亮、数学方程和美人鱼流程图。如果这些插件不能满足您的需求,您也可以编写自己的插件。
- 默认情况下是安全的:ByteMD已经正确处理了跨站点脚本(XSS) 攻击。无需引入额外的 DOM 清理步骤。
- SSR 兼容:ByteMD 可以在服务器端渲染(SSR)环境中使用,无需额外配置。SSR 在某些情况下被广泛使用,因为它具有更好的 SEO 和在慢速网络连接中快速获取内容的时间。
以上都是官方给出的讲解
安装
Package | Status | Description |
---|---|---|
bytemd | Svelte/Vanilla JS component | |
@bytemd/react | React component | |
@bytemd/vue | Vue 2 component | |
@bytemd/vue-next | Vue 3 component |
我使用的是 框架是 nuxt3 所以选择 @bytemd/vue-next 这个
npm i @bytemd/vue-next
使用
首先他有两个组件 Editor
和 Viewer
这两个,比较通俗易懂
Editor
顾名思义,就是 Markdown 编辑器,viewer
用于显示渲染的 Markdown 结果
在使用组件之前,请记住导入 CSS 文件以使样式正确(如果引入的话,样式会有错误):
import 'bytemd/dist/index.css'
这是我配置的文件
// bytemd.js
<template>
<div class="hj-bytemd">
<Editor
:value="content" // 页面编辑内容
:locale="zhHans" // 汉化使用
:plugins="plugins" // bytemd 使用的插件
@change="handleContentChange"
// 通过change方法改变value
:uploadImages="uploadImages"
// 上传图片需要是用的,如果不需要上传图片可以不加
/>
</div>
</template>
<script lang="ts" setup>
import 'highlight.js/styles/a11y-light.css' // 代码高亮的 css 文件 后期会在配置
import gfm from '@bytemd/plugin-gfm'
import zhHans from './../../../utils/zh_Hans.json'
// 默认bytemd不是中文,需要自行引入汉化
import frontMatter from '@bytemd/plugin-frontmatter'
import highlightSSR from '@bytemd/plugin-highlight-ssr'
import mediumZoom from '@bytemd/plugin-medium-zoom'
const content = ref('')
const plugins = [
gfm(),
frontMatter(),
highlightSSR(),
mediumZoom()
// 还可以自己再配置
]
const handleContentChange = (v) => {
content.value = v
}
const uploadImages = (files: File[]) => {
// TODO... 上传文件的代码
return [
{
title: files.map((i) => i.name),
url: 'http' // 这里需要的是自己上传服务器返回的地址
}
]
}
</script>
关于高度这里的问题 编辑器默认会是 300px
需要自己配置样式github 也有说明
.bytemd {
height: calc(100vh - 200px);
}
这样一个在线编辑器 Markdown
编辑器就有了
以上讲的都是
Editor
的使用
Viewer
这个组件,默认使用方法是
<Viewer
:value="value" // 回显的结果
/>
这里一般这么使用就会显示出来结果,但是我在 nuxt3
遇到不渲染的情况,问题有两点:
- 1. 这个组件的 value
这个字段不是响应式的,如果我给定默认值才会显示,动态值不会显示
- 2. 如果 viewer
在获取内容之前渲染就不会显示任何内容,将会是 null
但是打印会打印出来
解决方案:
使用 v-if
+ nextTick
控制 Viewer
在页面渲染完成之后在显示,例如:
const isContent = ref<boolean>(false)
onMounted(() => {
nextTick(() => {
isContent.value = true
})
})
<div class="content" v-if="isContent">
<Viewer
:value="articleItem.content"
:tabindex="2"
:sanitize="23"
/>
</div>
关于主题这里需要自己去配置 例如: juejin-markdown-themes and github-markdown-css. 可以自己找一找