实现使用markdown编写的个人组件库说明文档
前一篇文章实现了按需加载封装个人的组件库功能,有了组件库,当然还要有配套说明文档,这样使者用起来才更方便。打包完成的dist目录是最终可放到服务器中,直接访问到文档的哟。
项目github地址:https://github.com/yuanalina/installAsRequired
在项目中配置打包examples
上篇文章中,执行打包命令会将项目打包至lib下,打包完成的目录结构是适合直接发布为npm包,使用时使用import等引入的。其中并没有html文件入口,所以要有说明文档,直接在浏览器中可访问,还需要重新配置打包。
打包examples相关目录结构及webpack配置
一、package.json增加打包命令"build_example": "node build/build.js examples"
二、在src同级增加examples目录,存放文档相关文件
examples目录中:1、assets目录存放静态资源依赖,2、components存放vue组件,3、docs目录存放.md文件,说明文档,4、main.js会作为打包的入口,在这里引入项目的组件、第三方依赖:element-ui、路由配置等,5、route.js路由配置,6、index.html作为打包的html模版,7、App.vue
三、webpack相关配置
在build目录中增加webpack.prod.examples.conf.js文件,配置打包example。这个文件是vue-cli生成项目中的webpack.prod.conf.js稍作修改,改动部分:
1、增加output出口配置,由于之前在config中将这个值设置成了../lib,这里把值设置为../dist,将examples打包后输出到dist
2、设置打包入口为examples下的main.js
3、设置html模版为./examples/index.html
另外在build/build.js中,需要判断example参数,更改一下output出口路径,如图:
技术实现
编写说明文档,最直观的还是使用markdown编写,看了elementUI的实现方案,决定按elementUI的技术方案去实现。特别说明:本文中有部分实现是copy了elementUI的代码实现的。后面会特别指出
相关依赖安装
npm i highlight -D //安装语法高亮
npm i markdown-it markdown-it-anchor markdown-it-container -D // 安装markdown相关依赖
npm i vue-markdown-loader -D //安装vue-markdown-loader,解析.md文件为.vue文件
webpack相关配置
安装了vue-markdown-loader解析.md文件,在webpack.base.conf.js文件中,需要进行相关的loader配置,这里的配置相关,都是copy的element-ui中的代码。改动部分如下:
一、首先增加strip-tags文件到/build目录中,strip-tags内容如下:
/*!
* strip-tags
*
* Copyright (c) 2015 Jon Schlinkert, contributors.
* Licensed under the MIT license.
*/
'use strict';
var cheerio = require('cheerio');
exports.strip = function(str, tags) {
var $ = cheerio.load(str, {decodeEntities: false});
if (!tags || tags.length === 0) {
return str;
}
tags = !Array.isArray(tags) ? [tags] : tags;
var len = tags.length;
while (len--) {
$(tags[len]).remove();
}
return $.html();
};
exports.fetch = function(str, tag) {
var $ = cheerio.load(str, {decodeEntities: false});
if (!tag) return str;
return $(tag).html();
};
二、webpack.base.conf.js的改动
1、增加引入strip-tags和markdown-it
const striptags = require('./strip-tags')
const md = require('markdown-it')()
2、增加工具函数
const wrap = function(render) {
return function() {
return render.apply(this, arguments)
.replace('', '')
}
}
function convert(str) {
str = str.replace(/()(\w{4});/gi, function($0) {
return String.fromCharCode(parseInt(encodeURIComponent($0).replace(/(%26%23x)(\w{4})(%3B)/g, '$2'), 16))
})
return str
}
3、增加.md相关loader配置,将.md文件解析为.vue文件,同时,解析处理::: demo :::代码块等,解析处理::: demo :::代码块为demo-block vue组件,并传入对应参数.
{
test: /\.md$/,
loader: 'vue-markdown-loader',
options: {
use: [
[require('markdown-it-container'), 'demo', {
validate: function(params) {
return params.trim().match(/^demo\s*(.*)$/)
},
render: function(tokens, idx) {
var m = tokens[idx].info.trim().match(/^demo\s*(.*)$/)
if (tokens[idx].nesting === 1) {
var description = (m && m.length > 1) ? m[1] : ''
var content = tokens[idx + 1].content
var html = convert(striptags.strip(content, ['script', 'style'])).replace(/(<[^>]*)=""(?=.*>)/g, '$1')
var script = striptags.fetch(content, 'script')
var style = striptags.fetch(content, 'style')
var jsfiddle = { html: html, script: script, style: style }
var descriptionHTML = description
? md.render(description)
: ''
jsfiddle = md.utils.escapeHtml(JSON.stringify(jsfiddle))
return `
${html}
${descriptionHTML}
`
}
return ' \n'
}
}],
[require('markdown-it-container'), 'tip'],
[require('markdown-it-container'), 'warning']
],
preprocess: function(MarkdownIt, source) {
MarkdownIt.renderer.rules.table_open = function() {
return '