vitepress中实现在线编写

1,124 阅读2分钟

最近又在倒腾vitepress,想着能不能在线编写文档,然后直接上传,然后就有了这篇文档(这就是用在线编写功能写的)。

顺便把之前的网站精简一下,因为有些方法,官方已经提供了,就不用自己写了,然后又新加了一些功能。

初始化项目的步奏看看官网,重点说一下如何实现在线编写的,该功能只是我自己的一个想法,如果大佬们有更好的方法,欢迎提供一下。

MarkDown编辑器

编辑器我选用的是md-editor-v3,使用简单,功能完善。

安装

pnpm i md-editor-v3

用法

<template>
  <MdEditor v-model="text" />
</template>

<script setup>
import { ref } from 'vue';
import { MdEditor } from 'md-editor-v3';
import 'md-editor-v3/lib/style.css';

const text = ref('# Hello Editor');
</script>

vitepress中使用

vitepress是可以直接在md文件中写vue3的,所以这里可以直接新建一个md文件,然后引入组件。

// editor.md
<script setup>
import editor from '../.vitepress/components/editor.vue'
</script>
<editor />
<!-- editor.vue -->
<script setup>
import { ref, computed } from 'vue';
import { MdEditor } from 'md-editor-v3';
import 'md-editor-v3/lib/style.css';
import { useData } from 'vitepress';

const content = ref('# Hello Editor');
const theme = computed(()=>useData().isDark.value ? 'dark' : 'light')

const handleSave = () => {
  // 请求保存接口
  ...
}
</script>
<template>
  <MdEditor v-model="content" :theme="theme"/>
  <button class="save-btn" @click="handleSave">保存</button>
</template>
<style>
.save-btn{
  float: right;
  margin-top: 10px;
}
</style>

保存

说一下我的整个想法,我是在前端请求保存以后,后端(nodejs)直接把传过来的数据保存到vitepress对应的文件夹下,整个的数据格式就是一个markdown形式的字符串,然后切换到vitepress目录下运行npm run build。

关键代码

获取数据,拼接处理

  // 前端传过来的 text: 文档标题,link:文件名(vitepress用于跳转),content:文档内容
  const params = ctx.request.body
  const dates = dayjs(new Date).format('YYYY-MM-DD')
  const fileName = `${params.link}.md`
  // vitepress对应的文件夹
  const toFilePath = path.resolve(__dirname, '../../../Woung/docs/blog');
  // 需要保存的当前文件路径
  const filePath = path.join(toFilePath, fileName)
  let msg = ''
  // 拼接文档frontmatter
  let markdown = `---
title: ${params.text}
author: Younglina
date:  ${dates}
categories:
- 文档
tags:
- 记录
---
${params.content}
`

保存数据,重新打包

fs.writeFile(filePath, markdown, 'utf-8', (err) => {
  if (err) {
    ctx.body = {
      "code": 200,
      "message": err
    }
  }

  // 处理vitepress的sidebar,我的vitepress是把sidebar抽离出了一个json文件
  const sidebarPath = path.resolve(__dirname, '../../../Woung/docs/.vitepress/sidebar.json');
  // 读取文件内容
  fs.readFile(sidebarPath, 'utf8', (err, data) => {
    if (err) {
      console.error('Error reading file:', err);
      return;
    }

    const sidebar = JSON.parse(data)
    const blogs = sidebar['/blog/'].items[0].items
    // 把当前文件信息存储到sidebar中,并覆盖原文件
    blogs.push({ text: params.text, link: params.link })
    fs.writeFile(sidebarPath, JSON.stringify(sidebar), 'utf-8', (err) => {
      if (err) {
        console.error(err)
      }
    })
  });

  // 最后使用nodejs的child_process,切换到vitepress根目录,执行build
  const buildPath = path.resolve(__dirname, '../../../Woung');
  const command = `cd ${buildPath} && npm run build`;

  exec(command, (error, stdout, stderr) => {
    if (error) {
      console.error('Error executing command:', error);
      return;
    }

    console.log('Command executed successfully:', stdout);
  });
})

效果

觉得编写的地方小,编辑器有全屏的功能