[md-loader]使用md来编写vue组件库文档

需求场景:

  • 当前项目公共组件比较多,需要一个文档来描述
  • 希望轻量化,没有额外资源部署一个文档项目,即内嵌在开发项目中

期望效果

一个md文件一个页面
在这里插入图片描述

生成如下,并且一个md文件可以同时写多个demo在这里插入图片描述

思路来源

使用 element-ui源码中的md-loader,抽取出来后,增强一些其他功能即可。
其中重点是实现md文件中的 :::demovuepress·也是这个思路。
根据 :::demo 将 md文件中的vue片段用 demo-block 组件包裹,然后传递给 vue-loader生成html 即可。

demo-block 组件是自己定义的一个vue组件容器,可在源码中找到。

过程

代码准备

  1. 将element-ui 中的 md-loader 拷贝到自己项目中.
  2. 安装所需要的依赖
"markdown-it": "^13.0.1",
"markdown-it-anchor": "^8.6.4",
"markdown-it-chain": "^1.3.0",
"markdown-it-container": "^3.0.0",
"transliteration": "^2.3.5",
  1. 配置md文件的loader
// vue.config.js
 chainWebpack: (config) => {
    // 使用自定义 loader
    config.module
      .rule("md-loader")
      .test(/\.md$/)
      .use("vue-loader")
      .loader("vue-loader")
      .end()
      .use("md-loader")
      .loader(path.join(__dirname, "./md-loader/index.js"))
      .end();
  },
  1. 准备好文件页面用到的初始组件,具体可以参考element-ui以及我的demo源码在这里插入图片描述
  2. 因为我的与 element-ui 一样使用的是路由切换页面的,所以配置了动态路由
import Vue from "vue";
import VueRouter from "vue-router";

Vue.use(VueRouter);
import Guide from "@/components/.components/Guide.vue";
// const routes = [{ path: "/", component: Guide }];
const routes = [
  { path: "/", redirect: "/fe/changelog" },
  { path: "/fe/:name", component: Guide },
];

const router = new VueRouter({
  routes,
});

export default router;

最后直接重新运行即可。

增强

md中的css直接作用于页面

由于element-ui 的文档中的css是单独写在文件中的,在md中的css并不会作用于页面,那么我是做了一点修改。

解析出demo中的css后,统一加入 style 标签中。
md-loader\index.js
在这里插入图片描述

在这里插入图片描述
当前只实现了匹配普通style,如果需要匹配 lang=“less” ,只要修改下匹配style的正则即可。

// util.js
function stripStyle(content) {
  const result = content.match(/<(style)\s*([\s\S]+)<\/\1>/);
  return result && result[2] ? result[2].trim() : "";
}

组件注册

首先是 md文件的注册

// src\components\.components\Guide.vue
<script>
import navsData from './nav.config.js'
import SideNav from './SideNav.vue'
const requireComponents = require.context('../docs/', false, /\.md/)
const loadDocsComponents = {}
requireComponents.keys().forEach(fileName => {
    // 组件实例
    const reqCom = requireComponents(fileName)
    // 截取路径作为组件名
    const reqComName = fileName.replace(/\.\//, '').replace(/\.md/, '')
    // 组件挂载
    loadDocsComponents['md-' + reqComName] = reqCom.default || reqCom
})
export default {
    components: { SideNav, ...loadDocsComponents }
};
</script>

其次是项目公共文件的注册。由于公共组件是内嵌到 demo-block 组件中,所以只能选择全局注册,但是注册入口不选择在 main.js。 选中在 src\components\.components\Guide.vue

// src\components\.components\Guide.vue
import Vue from 'vue'
const components = require.context('../', false, /\.vue/)
components.keys().forEach(fileName => {
    // 组件实例
    const reqCom = components(fileName)
    // 截取路径作为组件名
    const reqComName = fileName.replace(/\.\//, '').replace(/\.vue/, '')
    // 组件挂载
    Vue.component(reqComName, reqCom.default || reqCom)
})

其他问题

如果发现一些奇怪的报错,可以优先排查版本依赖兼容问题。

参考

本次例子的源码
element-ui的文档源码
若川视野 ElementUI 组件库 md-loader 的解析和优化
倪凡 Element-UI源码阅读之md显示到页面

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_pengliang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值