前言:
很多时候我们程序员写的文档都是以markdown为主,但是我们每次找相关资料极为不便,如果能直接把markdown文档引进vue项目里,解析成html并且展示出来,然后部署在服务器上,查看是不是极为方便呢。(在做公司的私有组件库的时候,每一个组件都有一个README.md,我们在代码里查看并不方便,何不在展示组件的时候,把对应的README.md的也引进来解析出来,边看效果,边看文档多香啊)。
安装插件:
需要安装marked 和highlight.js两种插件
npm i marked highlight.js -D
编写mdToJs.js,用于将markdown文档转化为js
以下代码可直接复制应用
import path from "path";
import fs from "fs";
import { marked } from "marked";
const mdToJs = (str) => {
const content = JSON.stringify(marked(str));
return `export default ${content}`;
};
export function md() {
return {
name: "md",
configureServer() {
// 用于开发
async ({ app }) => {
app.use(async (ctx, next) => {
// koa
if (ctx.path.endsWith(".md")) {
ctx.type = "js";
const filePath = path.join(process.cwd(), ctx.path);
ctx.body = mdToJs(fs.readFileSync(filePath).toString());
} else {
await next();
}
});
};
},
transform(code, id) {
// 用于 rollup // 插件
// 获取文件后缀名
const fileArr = id.split("."); //根据.分割数组
const fileType = fileArr[fileArr.length - 1]; //取最后一个
if (/\md$/.test(fileType)) {
return mdToJs(code);
}
return;
},
};
}
配置vite.config.js
引入上面的md.js,在plugins里注入调用
import { fileURLToPath, URL } from "node:url";
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import { md } from "./mdToJs";
// https://vitejs.dev/config/
export default defineConfig({
base: "/",
server: {
open: true,
hmr: true,
},
plugins: [vue(), md()],
resolve: {
alias: {
"@": fileURLToPath(new URL("./src", import.meta.url)),
},
},
});
到这里,项目里已经可以正常引入md文档,不报错了
我们来看看效果
因为解析成js,所以我们渲染的时候,需要用v-html来渲染
<template>
<div>MD</div>
<article v-html="MDFile" />
</template>
<script setup>
import MDFile from "./assets/README.md";
</script>
我们可以看到,代码块是没有高亮显示的
接下来,我们将会借助highlight.js进行高亮显示代码块
高亮显示
写一个自定义hooks,然后在需要高亮的页面里调用这个hooks
src/hooks/md.js
下面的hooks可以直接复制到项目里用
import { onMounted } from "vue";
import hljs from "highlight.js"; // 引入 highlight.js
export function useHighLight() {
const handleHighLight = () => {
let blocks = document.querySelectorAll("pre code");
blocks.forEach((block) => {
hljs.highlightBlock(block);
});
};
onMounted(() => {
handleHighLight();
});
}
highlight.js事实上提供了很多种主题的高亮样式,我们看一下node_modules里
我们选择其中一种引入到全局里就好
main.js
// import './assets/main.css'
import { createApp } from "vue";
import ElementPlus from "element-plus";
import "element-plus/dist/index.css";
import App from "./App.vue";
//引入highlight.js其中一种主题样式
import "highlight.js/styles/monokai-sublime.css";
const app = createApp(App);
app.use(ElementPlus);
app.mount("#app");
在需要高亮显示代码块的页面里调用上面的hooks
<template>
<div>MD</div>
<article v-html="MDFile" />
</template>
<script setup>
import MDFile from "./assets/README.md";
import { useHighLight } from '../src/hooks/md'
useHighLight()
</script>
再看一下效果
md解析完成,高亮显示代码块完成~
拓展:
下面是一些其他方面的心得,感兴趣的可以看下。
事实上,我们在plugins注入的md函数将markdown转化为js。还有其他方式,比如可以把markdown转化为vue。让我们来看下如何运用
编写mdToVue.js将markdown转化为vue
/*
* @Description:
* @Author: yangxiao
* @Date: 2024-04-10 13:20:15
* @LastEditTime: 2024-04-12 11:16:23
* @LastEditors: yangxiao
*/
import { marked} from 'marked'
export default function (options) {
return {
name: 'vitePluginMd2Vue',
transform(src, id) {
/**
* id是导入的文件路径
* src是导入的文件内容
*/
if (id.endsWith(".md")) { // 判断结尾字符串判断是否为markdown文件
return {
// code中使用sfc会导致没有走vite的解析流程,所以直接使用渲染函数编写
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`, // code是转换后最终输出的代码
map: null // 是否提供source map,这里可以不用考虑
}
}
}
}
}
在vite.config.js的plugins里注入调用
import { fileURLToPath, URL } from "node:url";
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import mdToVue from './examples/plugin/mdToVue.js'
// https://vitejs.dev/config/
export default defineConfig({
base: "/",
server: {
open: true,
hmr: true,
},
plugins: [vue(), mdToVue()],
resolve: {
alias: {
"@": fileURLToPath(new URL("./src", import.meta.url)),
},
},
});
这个时候我们可以直接在页面里引入markdown文件,解析成html进行展示
<template>
<div>MD</div>
<MDFile/>
</template>
<script setup>
import MDFile from "./assets/README.md";
</script>
高亮的相关配置和上面的没有区别~
高亮随机主题色
我们从上面的node_modules的截图里可以看到,事实上,highlight.js提供了很多种高亮样式主题,我们只用一种未免过于单调,所以笔者呢,挑了10种,做了个随机代码高亮主题
编写一个mdCodeTheme.js用于存放随机高亮主题的代码
@/utils/mdCodeTheme.js
function getRandomInt() {
return Math.floor(Math.random() * 10) + 1;
}
switch (getRandomInt()) {
case 1:
import("highlight.js/styles/devibeans.css");
break;
case 2:
import("highlight.js/styles/a11y-dark.css");
break;
case 3:
import("highlight.js/styles/agate.css");
break;
case 4:
import("highlight.js/styles/an-old-hope.css");
break;
case 5:
import("highlight.js/styles/androidstudio.css");
break;
case 6:
import("highlight.js/styles/felipec.css");
break;
case 7:
import("highlight.js/styles/arta.css");
break;
case 8:
import("highlight.js/styles/github-dark-dimmed.css");
break;
case 9:
import("highlight.js/styles/atom-one-dark-reasonable.css");
break;
case 10:
import("highlight.js/styles/monokai-sublime.css");
break;
}
然后把上面的mdCodeTheme.js引入到main.js里就好
// import './assets/main.css'
import { createApp } from "vue";
import ElementPlus from "element-plus";
import "element-plus/dist/index.css";
import App from "./App.vue";
import './src/utils/mdCodeTheme'
const app = createApp(App);
app.use(ElementPlus);
app.mount("#app");
这样就能每次进入项目的时候随机切换主题色啦~
手动切换高亮主题色
这里提供一个思路吧,就不再进行代码演示了。
在header区域加一个下拉框。然后写死一个数据源,给每一个主题色标上序号,切换主题色的时候,把对应的序号存到localStorage里,然后强制刷新页面(window.location.reload())。重新进入项目的时候。main.js里判断localStorage里存没存高亮主题色的序号,如果有,就懒加载对应的主题色css。如果没有,就显示默认的主题色。这样就实现手动切换主题色啦~