vite插件,实现将markdown转成vue组件
分类:javascript
本文目标是实现vite插件,面向vue做的代码实现,所以代码全是以vue的api形式展示,不过不管什么框架实现思路基本一致。
前言
我们在开发库或者文档系统的时候,希望能够直接将编写的markdown作为组件的内容,目前多数博客提供的解决方案要干两个事
- 利用markdown的解析库将md解析成html内容
- 在业务中编写一个组件将前一步解析出的html文本作为v-html属性的值
那么问题来了,这个承载markdown的组件作用仅仅是提供了插入html文本的容器,而你需要在业务里编写,即便提出到组件库,也需要进行导入和使用,可以说是事倍功半。
所以我们希望能够将编写的md文件直接导入成可使用的组件,比如:
<template>
<Start />
</template>
<script>
import { defineComponent } from 'vue';
import Start from 'docs/start.md';
export default defineComponent({
name: 'App',
components: { Start },
})
</script>
也就是插件需要把前面所提到的两件事都干完,输出一个vue组件。
实现
理清需求
遇到markdown文件,将内容解析成html,利用vue渲染函数的api编写代码,将html内容插入,最终输出整个代码
解析markdown文件
我们采用marked库对markdown文件做解析,所以先安装
yarn add marked
vite插件
vite插件的使用和基本api可以直接看中文文档,这里不做赘述,直接看实现。
拦截markdown文件我们利用的是transform
,意思是转换,功能类似webpack的loader,基本结构代码如下:
// /plugins/vite-plugin-md2vue.js
const marked = require('marked')
export default function (options) {
return {
name: 'vitePluginMd2Vue',
transform(src, id) {
/**
* id是导入的文件路径
* src是导入的文件内容
*/
if (id.endsWith(".md")) { // 判断结尾字符串判断是否为markdown文件
return {
code: ``, // code是转换后最终输出的代码
map: null // 是否提供source map,这里可以不用考虑
}
}
}
}
}
code中我们需要编写组件代码,但是这里不能使用sfc也就是单文件组件的形式去写,因为vite中会专门拦截.vue
结尾的文件去做解析,如果我们直接导出sfc形式的代码,就没有走vite中的解析流程导致报错,所以我们直接编写渲染函数,代码如下:
import {h, defineComponent} from "vue";
const _sfc_md = defineComponent({
name: "Markdown",
});
const _sfc_render =() => {
return h("div", {
// 这里赋值解析好的markdown内容,marked是上一段代码中导入的解析库
// src也是上一段代码中md文件的导入内容,我们直接解析后转成字符串
innerHTML: ${JSON.stringify(marked(src))},
})
};
_sfc_md.render = _sfc_render
export default _sfc_md
最终合成代码如下:
// /plugins/vite-plugin-md2vue.js
const marked = require('marked')
export default function (options) {
return {
name: 'vitePluginMd2Vue',
transform(src, id) {
if (id.endsWith(".md")) {
return {
code: `import {h, defineComponent} from "vue";
const _sfc_md = defineComponent({
name: "Markdown",
});
const _sfc_render =() => {
return h("div", {
innerHTML: ${JSON.stringify(marked(src))},
})
};
_sfc_md.render = _sfc_render
export default _sfc_md`,
map: null
}
}
}
}
}
使用插件
在vite.config.js
使用插件,代码如下:
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import vitePluginMd2Vue from "./plugins/vite-plugin-md2vue";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue(), vitePluginMd2Vue()],
...
});
最终实现的代码在vite-plugin-md2vue