前言:
很多时候我们程序员写的文档都是以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。如果没有,就显示默认的主题色。这样就实现手动切换主题色啦~