前言:

开发vue组件库需要提供组件的使用文档,最好是有渲染到浏览器的demo实例,既能操作又能查看源代码。markdown作为常用的文档编写载体,如果能在里面直接写vue组件,同时编写使用说明就再好不过。流行的组件库element-ui的文档就是用markdown写出来的,看了看其处理md的程序后,自己也决定写一个类似的处理程序,研究一下其中的细节。

技术点

1.markdown-it

处理markdown最常用的工具是markdown-it,它能把我们写的markdown文件转换为html。类似于babel,markdown也有自己的插件系统,通过设置或者编写自定义插件改变渲染的路径。

2.webpack-loader

处理md文件可以使用自定义webpack-loader来处理,先把md内容转为合适html,然后再给vue-loader处理。

3.cheerio

使用markdown-it把md内容转为html之后,需要操作html,cherrio以类似jquery的方式操作html,简单方便。

4.hljs

代码需要高亮渲染,hijs的功能就是将代码处理成html,通过样式使其高亮显示出来。

步骤

1.配置webpack解析md

{
test: /\.md$/,
use:[
{loader: 'vue-loader'},
{ loader: path.resolve(__dirname,'./markdown-loader/index.js') }
]
},

2.markdown-loader的入口

module.exports = function (source) {
this.cacheable && this.cacheable();
const {resourcePath=''} = this
const fileName = path.basename(resourcePath,'.md')
// @符号在markdown中是特殊符号
source = source.replace(/@/g, '__at__'); var content = parser.render(source).replace(/__at__/g, '@'); var result = renderMd(content,fileName) return result
};

3.添加插件markdown-it-container

markdown-it-container是一个插件,使用这个插件之后就可以在markdown中添加自己的标识,然后就能自定义处理标识里面的内容。在这里可以在把代码块放到标识内部,主要是防止markdown-it把vue组件转成html,由自己处理这些代码,最终返回想要的内容。

::: demo
​```html
<i class="kv-icon-close fs-24"></i>
<i class="kv-icon-link fs-24"></i>
​```
:::

上面就是插件的用法,demo由自己定义,初始注入的代码如下:

parser.use(require('markdown-it-container'), 'demo', {
validate(params) {
return params.trim().match(/^demo\s*(.*)$/);
},
// 把demo代码放到div.kv-demo里面
render(tokens, idx) {
const m = tokens[idx].info.trim().match(/^demo\s*(.*)$/);
if (tokens[idx].nesting === 1) {
const content = tokens[idx + 1].type === 'fence' ? tokens[idx + 1].content : '';
// 先把demo中的代码放到demo-block的之中,然后程序继续render fence,按照上面的fence规则渲染出代码部分,作为隐藏的查看代码。
return `<demo-block><div class="kv-demo">${content}</div>`;
}
return '</demo-block>';
}
})

render方法仿照的是npm包里的例子。其中的tokens是AST节点,可以从这个网址看到markdown-it解析的AST,对照着做判断。

根据自己的理解,因为html是有起始标签和结束标签,markdown-it的render也是成对的,也就是在标记的起始和结束都会调用render方法,所以在demo起始的时候返回了一个起始<demo-block> (这是个全局定义的vue组件),然后把代码放到内部;

markdown会继续处理demo标识内部``` 标识,这个标识在markdown-it中有自己的rules (rules.fence)来处理;然而我们的目标是把这个代码放到一个标签中渲染成html,然后作为查看源码的部分展示出来,这就需要自定义了:

// 先保存下来
const defaultRender = parser.renderer.rules.fence;
parser.renderer.rules.fence = (tokens, idx, options, env, self) => {
const token = tokens[idx];
// 判断该 fence 是否在 :::demo 内
const prevToken = tokens[idx - 1];
const isInDemoContainer = prevToken && prevToken.nesting === 1 && prevToken.info.trim().match(/^demo\s*(.*)$/);
if (token.info === 'html' && isInDemoContainer) {
return `<template slot="highlight">
<pre v-pre><code class="html">${hljs.highlight('html',token.content.replace(/^(\s*)|(\s*)$/g,'')).value}</code></pre>
</template>`;
} return `<div class="code-common">${defaultRender(tokens, idx, options, env, self)}</div>`
};

需要注意的是如果初始化parser的时候如果配置了 highlight: renderHighlight,调用defaultRender的时候会自动处理成高亮;否则需要就需要自己处理了,就是上面的hljs.highlight('html',token.....

做完以上部分之后,md的内容会被渲染成代码片断,内部包含普通的html标签和vue组件标签,大概如下:

<div>一些文字</div>
<demo-block>
<div class="kv-demo">
<ul class="icon-list">
<li v-for="name in icons" :key="name">
<span>
<i :class=" iconPre+ name"></i>
{{'kv-' + name}}
</span>
</li>
</ul>
<script>
export default {
data() {
return {
icons: require('../icon.json'),
iconPre:'kv-icon-'
};
}
}
</script> <style lang="scss">
.demo-icon {
.....
}
</style>
</div>
<template slot="highlight">
......
</template>
</demo-block>

组装成vue模板

这个代码和vue的组件的代码不一致,是无法解析的,需要修正一下。

另外一篇文档中会有多个demo即多个export default,解决方案就是把各个demo提取成组件,注册当前文档这个vue组件中,把demo的部分替换组件的名字。

第一部分:组装当前文档为vue组件 ,同时挂载提取出来demo组件https://github.com/blank-x/kv/blob/master/build/markdown-loader/index.js#L15

var renderMd = function (html,fileName) {
......
}

第二部分:提取其中的demo为组件,https://github.com/blank-x/kv/blob/master/build/markdown-loader/index.js#L57)

var renderVueTemplate = function (content) {
......
}

结果类似于如下:

<template>
<div class="demo-">
<demo-block>
<template slot="source">
<kv-demo0></kv-demo0>
</template>
<template slot="highlight">
<pre v-pre><code class="html">......</code></pre>
</template>
</demo-block>
.......
<demo-block>
<template slot="source">
<kv-demo1></kv-demo1>
</template>
<template slot="highlight">
<pre v-pre><code class="html"><span class="hljs-tag">.......</code></pre>
</template>
</demo-block>
</div>
</template>
<script>
export default {
name: "component-doc0",
components: {
"kv-demo0": {
template: `<div class="kv-demo0"><kv-tag>标签一</kv-tag></div>`
},
"kv-demo1": {
template: `<div class="kv-demo1">
<kv-tag :key="tag.name" v-for="tag in dynamicTags"
closable :disable-transitions="false" @close="handleClose(tag)" :type="tag.color">
{{tag.name}}
</kv-tag>
</div>`,
data() {
return {
dynamicTags: [{
name: "标签一",
color: "primary"
}]
};
},
methods: {
handleClose(tag) {
this.dynamicTags.splice(this.dynamicTags.indexOf(tag), 1);
}
}
}
}
};
</script>
<style lang="scss" >
.kv-tag {
margin-right: 8px;
}
</style>

组件kv-demo0 和kv-demo1 在components中定义;

在demo内部的scss会被提出来,放到了外层vue组件中,如果需要修改样式,可以参考如下写法:

.demo-tag .kv-demo1{
//
}
.demo-tag .kv-demo0{
//
}
tag // md的名字
demo0 // 页面内第几个demo

未解决的问题

每一个demo中script标签和export之间的代码被丢弃。如果需要引入其他文件,可以在data中通过require引入;

最后

本代码仅为练手使用,未在实际开发中使用,如有不正之处望指正。

vue组件库用markdown生成文档的更多相关文章

  1. 使用Ldoc给Lua生成文档

    Ldoc介绍 LDoc是一个Lua的文档生成工具,过去,比较常用的Lua生成文档的工具是LuaDoc,可惜作者自从2008年之后就再也没有发布过新的版本了,说明作者基本上已经放弃维护了.而LDoc则是 ...

  2. SpringBoot 集成Swagger2自动生成文档和导出成静态文件

    目录 1. 简介 2. 集成Swagger2 2.1 导入Swagger库 2.2 配置Swagger基本信息 2.3 使用Swagger注解 2.4 文档效果图 3. 常用注解介绍 4. Swagg ...

  3. 使用 Swagger 自动生成 ASP.NET Core Web API 的文档、在线帮助测试文档(ASP.NET Core Web API 自动生成文档)

    对于开发人员来说,构建一个消费应用程序时去了解各种各样的 API 是一个巨大的挑战.在你的 Web API 项目中使用 Swagger 的 .NET Core 封装 Swashbuckle 可以帮助你 ...

  4. MVC WEB api 自动生成文档

    最近在一直在用webapi做接口给移动端用.但是让我纠结的时候每次新加接口或者改动接口的时候,就需要重新修改文档这让我很是苦恼.无意中发现.webapi居然有自动生成文档的功能....真是看见了救星啊 ...

  5. newlisp 注释生成文档

    最近写了一个newlisp_armory库,用来实现一些newlisp自身不支持的操作.比如跨windows和ubuntu的目录拷贝功能等. 自己用的时候,发现没有API reference文档参考, ...

  6. Vue组件库的那些事儿,你都知道吗?

    前段时间一直在研究Vue组件库,终于在组内派上了用场.来给大家贡献一篇关于Vue组件库的相关知识.经验不多,如果有不合理的地方还请多多指出哦--- 回想一下,在你们公司或者你们小组是否有一个以上的项目 ...

  7. JavaScript 实现命名空间(namespace)的最佳方案——兼容主流的定义类(class)的方法,兼容所有浏览器,支持用JSDuck生成文档

    作者: zyl910 一.缘由 在很多的面向对象编程语言中,我们可以使用命名空间(namespace)来组织代码,避免全局变量污染.命名冲突.遗憾的是,JavaScript中并不提供对命名空间的原生支 ...

  8. 使用Sphinx为你的python模块自动生成文档

    Sphinx是一个可以用于Python的自动文档生成工具,可以自动的把docstring转换为文档,并支持多种输出格式包括html,latex,pdf等. 安装 创建一个sphinx项目 下面的命令会 ...

  9. 仿ElementUI构建自己的Vue组件库用babel-plugin-component按需加载组件及自定义SASS主题

    最近使用ElementUI做项目的时候用Babel的插件babel-plugin-component做按需加载,使得组件打包的JS和CSS包体积大大缩小,加载速度也大大提升,所有想模仿做一个组件库也来 ...

随机推荐

  1. springboot 集成mybatis时日志输出

    application.properties(yml)中配置的两种方式: 这两种方式的效果是一样的,但是下面一种可以指定某个包下的SQL打印出来,上面这个会全部的都会打印出来.

  2. vue 组件传参及跨域传参

    可以完成跨组件传参的四种方式 // 1) localStorage:永久存储数据 // 2) sessionStorage:临时存储数据(刷新页面数据不重置,关闭再重新开启标签页数据重置) // 3) ...

  3. 搜索引擎-SHODAN

    shodan这个搜索引擎不会爬取网页内容,而是爬取所有的联网设备. 这个搜索引擎还是很强大的,下图就是我用shodan查自己的案例服务器的结果: 如图,可以查到这台服务器安装了wdcp管理面板,黑客完 ...

  4. Flink1.10全文跟读翻译

    前言 突然的一个想法,我想把flink官网英语版全部看一遍翻译出来,并且带上自己的理解.自己不是什么大神,只是想这样做一遍,有人说不是有中文版,因为我自己想练习一下英语和对flink的理解吧!工作是一 ...

  5. el-table表头与内容右边框错位问题

    在用element写一个后台管理系统时遇到一个坑,el-table标签渲染出数据后表头th和内容会有错位,之前没有的 修改大小都没用 于是看百度搜索一波最终解决修改之前 虽然不大 但是别扭 在全局添加 ...

  6. ajax前后端交互原理(1)

    1.Node.js简介 1.1.前后台数据交互流程 在web开发中,我们经常听说前端和后台,他们分别是做什么具体工作的呢?他们怎样交互的呢?我们得把这些基础的问题都搞明白了,才有一个大致的学习方向,首 ...

  7. JQuery 优缺点略谈

    1.jQuery实现脚本与页面的分离 ; 2.最少的代码做最多的事情; 3.性能; 在大型JavaScript框架中,jQuery对性能的理解最好.尽管不同版本拥有众多新功能,其最精简版本只有18KB ...

  8. hive sql 解析json

    在hive中会有很多数据是用json格式来存储的,而我们用数据的时候又必须要将json格式的数据解析成为正常的数据,今天我们就来聊聊hive中是如何解析json数据的. 下面这张表就是json格式的表 ...

  9. 阿里云centos7安装redis全过程记录

    Redis下载地址:https://redis.io/download(这个连接可能得翻墙查看,但是在centos7服务器上安装过程不需要翻墙,我查看了最新的是redis-4.0.9.tar.gz ) ...

  10. ant design pro---ProTable关闭Table上的提示信息

    toolBarRender={false} tableAlertRender={false}