vue组件库用markdown生成文档
前言:
开发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生成文档的更多相关文章
- 使用Ldoc给Lua生成文档
Ldoc介绍 LDoc是一个Lua的文档生成工具,过去,比较常用的Lua生成文档的工具是LuaDoc,可惜作者自从2008年之后就再也没有发布过新的版本了,说明作者基本上已经放弃维护了.而LDoc则是 ...
- SpringBoot 集成Swagger2自动生成文档和导出成静态文件
目录 1. 简介 2. 集成Swagger2 2.1 导入Swagger库 2.2 配置Swagger基本信息 2.3 使用Swagger注解 2.4 文档效果图 3. 常用注解介绍 4. Swagg ...
- 使用 Swagger 自动生成 ASP.NET Core Web API 的文档、在线帮助测试文档(ASP.NET Core Web API 自动生成文档)
对于开发人员来说,构建一个消费应用程序时去了解各种各样的 API 是一个巨大的挑战.在你的 Web API 项目中使用 Swagger 的 .NET Core 封装 Swashbuckle 可以帮助你 ...
- MVC WEB api 自动生成文档
最近在一直在用webapi做接口给移动端用.但是让我纠结的时候每次新加接口或者改动接口的时候,就需要重新修改文档这让我很是苦恼.无意中发现.webapi居然有自动生成文档的功能....真是看见了救星啊 ...
- newlisp 注释生成文档
最近写了一个newlisp_armory库,用来实现一些newlisp自身不支持的操作.比如跨windows和ubuntu的目录拷贝功能等. 自己用的时候,发现没有API reference文档参考, ...
- Vue组件库的那些事儿,你都知道吗?
前段时间一直在研究Vue组件库,终于在组内派上了用场.来给大家贡献一篇关于Vue组件库的相关知识.经验不多,如果有不合理的地方还请多多指出哦--- 回想一下,在你们公司或者你们小组是否有一个以上的项目 ...
- JavaScript 实现命名空间(namespace)的最佳方案——兼容主流的定义类(class)的方法,兼容所有浏览器,支持用JSDuck生成文档
作者: zyl910 一.缘由 在很多的面向对象编程语言中,我们可以使用命名空间(namespace)来组织代码,避免全局变量污染.命名冲突.遗憾的是,JavaScript中并不提供对命名空间的原生支 ...
- 使用Sphinx为你的python模块自动生成文档
Sphinx是一个可以用于Python的自动文档生成工具,可以自动的把docstring转换为文档,并支持多种输出格式包括html,latex,pdf等. 安装 创建一个sphinx项目 下面的命令会 ...
- 仿ElementUI构建自己的Vue组件库用babel-plugin-component按需加载组件及自定义SASS主题
最近使用ElementUI做项目的时候用Babel的插件babel-plugin-component做按需加载,使得组件打包的JS和CSS包体积大大缩小,加载速度也大大提升,所有想模仿做一个组件库也来 ...
随机推荐
- springboot 集成mybatis时日志输出
application.properties(yml)中配置的两种方式: 这两种方式的效果是一样的,但是下面一种可以指定某个包下的SQL打印出来,上面这个会全部的都会打印出来.
- vue 组件传参及跨域传参
可以完成跨组件传参的四种方式 // 1) localStorage:永久存储数据 // 2) sessionStorage:临时存储数据(刷新页面数据不重置,关闭再重新开启标签页数据重置) // 3) ...
- 搜索引擎-SHODAN
shodan这个搜索引擎不会爬取网页内容,而是爬取所有的联网设备. 这个搜索引擎还是很强大的,下图就是我用shodan查自己的案例服务器的结果: 如图,可以查到这台服务器安装了wdcp管理面板,黑客完 ...
- Flink1.10全文跟读翻译
前言 突然的一个想法,我想把flink官网英语版全部看一遍翻译出来,并且带上自己的理解.自己不是什么大神,只是想这样做一遍,有人说不是有中文版,因为我自己想练习一下英语和对flink的理解吧!工作是一 ...
- el-table表头与内容右边框错位问题
在用element写一个后台管理系统时遇到一个坑,el-table标签渲染出数据后表头th和内容会有错位,之前没有的 修改大小都没用 于是看百度搜索一波最终解决修改之前 虽然不大 但是别扭 在全局添加 ...
- ajax前后端交互原理(1)
1.Node.js简介 1.1.前后台数据交互流程 在web开发中,我们经常听说前端和后台,他们分别是做什么具体工作的呢?他们怎样交互的呢?我们得把这些基础的问题都搞明白了,才有一个大致的学习方向,首 ...
- JQuery 优缺点略谈
1.jQuery实现脚本与页面的分离 ; 2.最少的代码做最多的事情; 3.性能; 在大型JavaScript框架中,jQuery对性能的理解最好.尽管不同版本拥有众多新功能,其最精简版本只有18KB ...
- hive sql 解析json
在hive中会有很多数据是用json格式来存储的,而我们用数据的时候又必须要将json格式的数据解析成为正常的数据,今天我们就来聊聊hive中是如何解析json数据的. 下面这张表就是json格式的表 ...
- 阿里云centos7安装redis全过程记录
Redis下载地址:https://redis.io/download(这个连接可能得翻墙查看,但是在centos7服务器上安装过程不需要翻墙,我查看了最新的是redis-4.0.9.tar.gz ) ...
- ant design pro---ProTable关闭Table上的提示信息
toolBarRender={false} tableAlertRender={false}