610 字
3 分钟
在vite项目下支持markdown文件
2022-01-13

前言#

需求如下 在写xinyi-ui 官网时,需要对组件进行文档说明,说明文档都是md格式的文件,能否直接将md文件显示到页面上,而不改为html 呢? 现在有 install.md 和 get-started.md 两个文件

第一步 实现一个vite插件 md => html#

  • 将对md文件的请求进行数据处理
  • 通过markdown-it 将源文件转为html字符串
var MarkdownIt = require('markdown-it')
const marked = new MarkdownIt()
const mdToJs = str => {
const content = JSON.stringify(marked.render(str))
return `export default ${content}`
}
export function md() {
return {
name: 'md',
transform(src,url){
if(url.endsWith('.md')){
return {
code: mdToJs(src),
map: null // 如果可行将提供 source map
}
}
}
}
}

第二步创建组件模板 Markdown.vue#

因为只是md文件不同,可以使用同一个组件模板,通过文件路径显示不同的html内容

<template>
<article v-html="content"></article>
</template>

那么如何获取这个content 呢? 只要引入md 文件 vite插件就会自动将md文件转为html 字符串

router.js
// 通过渲染函数将 path 传递给 markdown.vue 在markdown.vue 中引入md文件
const md = (filename:string) => h(Markdown, { path: `../markdown/${filename}.md`, key: filename })
const routes = {
// component 可以使VNode
{ path: 'install', component: md('install')},
{ path: 'get-started', component: md('get-started') },
}

但是我们不能再setup 中使用 import xxx from ... 的语法,可以使用异步引入的方式

Markdown.vue
export default {
props: {
path: {
type: String,
required: true,
},
},
setup(props:any) {
const content = ref<string>('');
import(/* @vite-ignore */props.path).then((result) => {
content.value = result.default; // 这里可以获取到
});
return {
content,
};
},
};

显示在页面 并添加样式#

  • 安装 github-markdown-css
  • 在main.ts 或 MarkDown.vue中引入 css
  • 在article上添加class markdown-body
  • v-html 显示 html
<article class="markdown-body" v-html="content"></article>

将动态引入改为静态引入#

build后发现在生产环境会报错 是因为rollup打包不接受这种拼接字符串的模式 所以将动态引入文件 改为静态引入

这样也将异步引入改为了同步引入了

main.ts
import install from '../markdown/install.md'
import getStarted from '../markdown/get-started.md'
// 直接将content 传给Markdown.vue
const md = (content:string) => h(Markdown, { content })
const routes = {
{ path: 'install', component: md(install)},
{ path: 'get-started', component: md(getStarted) },
}

这样直接引入 ts 会报错 可以加 // @ts-ignore 不管 也可以在markdown中添加一个声明文件 markdown.d.ts

declare module "*.md" {
const content: string;
export default content;
}

这样打开就不会报错啦

Markdown.vue中显示markdown

<template>
<!--content 就是 html 格式的字符串-->
<article class="markdown-body" v-html="content"></article>
</template>
<script lang="ts">
import { ref } from "vue";
export default {
props: {
content: {
type: String,
required: true,
},
}
};
</script>
在vite项目下支持markdown文件
https://blog.cxyxiaoyu.top/posts/在vite项目下支持markdown/
作者
小宇
发布于
2022-01-13
许可协议
CC BY-NC-SA 4.0