最近閱讀了
element-ui的源碼才知道像這類UI庫的官方說明文檔都是用markdown寫的.
改造webpack配置
const markdownRender = require('markdown-it')();
...
{
test: /\.md$/,
use: [
{
loader: 'vue-loader'
},
{
loader: 'vue-markdown-loader/lib/markdown-compiler',
options: {
raw: true,
preventExtract: true,
use: [
[
require('markdown-it-container'),
'demo',
{
validate: function(params) {
return params.trim().match(/^demo\s+(.*)$/);
},
render: function(tokens, idx) {
if (tokens[idx].nesting === 1) {
// 1.獲取第一行的內(nèi)容使用markdown渲染html作為組件的描述
let demoInfo = tokens[idx].info
.trim()
.match(/^demo\s+(.*)$/);
let description =
demoInfo && demoInfo.length > 1
? demoInfo[1]
: '';
let descriptionHTML = description
? markdownRender.render(description)
: '';
// 2.獲取代碼塊內(nèi)的html和js代碼
let content = tokens[idx + 1].content;
// 3.使用自定義開發(fā)組件【DemoBlock】來包裹內(nèi)容并且渲染成案例和代碼示例
return `<demo-block>
<div class="source" slot="source">${content}</div>
${descriptionHTML}
<div class="highlight" slot="highlight">`;
} else {
return '</div></demo-block>\n';
}
}
}
]
}
}]
}
添加demo-block.vue
用于包含markdown文件
<template>
<div class="demo-block">
<div class="demo-block-source">
<slot name="source"></slot>
<span class="demo-block-code-icon"
v-if="!$slots.default"
@click="showCode=!showCode"><img alt="expand code"
src="https://gw.alipayobjects.com/zos/rmsportal/wSAkBuJFbdxsosKKpqyq.svg"
class="code-expand-icon-show"></span>
</div>
<div class="demo-block-meta"
v-if="$slots.default">
<slot></slot>
<span v-if="$slots.default"
class="demo-block-code-icon"
@click="showCode=!showCode"><img alt="expand code"
src="https://gw.alipayobjects.com/zos/rmsportal/wSAkBuJFbdxsosKKpqyq.svg"
class="code-expand-icon-show"></span>
</div>
<div class="demo-block-code"
v-show="showCode">
<slot name="highlight"></slot>
</div>
</div>
</template>
<script type="text/babel">
export default {
data() {
return {
showCode: false
};
}
};
</script>
<style>
.demo-block {
border: 1px solid #ebedf0;
border-radius: 2px;
display: inline-block;
width: 100%;
position: relative;
margin: 0 0 16px;
-webkit-transition: all 0.2s;
transition: all 0.2s;
border-radius: 2px;
}
.demo-block p {
padding: 0;
margin: 0;
}
.demo-block .demo-block-code-icon {
position: absolute;
right: 16px;
bottom: 14px;
cursor: pointer;
width: 18px;
height: 18px;
line-height: 18px;
text-align: center;
}
.demo-block .demo-block-code-icon img {
-webkit-transition: all 0.4s;
transition: all 0.4s;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
position: absolute;
left: 0;
top: 0;
margin: 0;
max-width: 100%;
width: 100%;
vertical-align: baseline;
-webkit-box-shadow: none;
box-shadow: none;
}
.demo-block .demo-block-source {
border-bottom: 1px solid #ebedf0;
padding: 20px 24px 20px;
color: #444;
position: relative;
margin-bottom: -1px;
}
.demo-block .demo-block-meta {
position: relative;
padding: 12px 50px 12px 20px;
border-radius: 0 0 2px 2px;
-webkit-transition: background-color 0.4s;
transition: background-color 0.4s;
width: 100%;
-webkit-box-sizing: border-box;
box-sizing: border-box;
font-size: 14px;
color: #444;
font-size: 14px;
line-height: 2;
border-radius: 0;
border-bottom: 1px dashed #ebedf0;
margin-bottom: -1px;
}
.demo-block .demo-block-meta code {
color: #444;
background-color: #e6effb;
margin: 0 4px;
display: inline-block;
padding: 3px 7px;
border-radius: 3px;
height: 18px;
line-height: 18px;
font-family: Menlo, Monaco, Consolas, Courier, monospace;
font-size: 14px;
}
.demo-block .demo-block-code {
background-color: #f7f7f7;
font-size: 0;
}
.demo-block .demo-block-code code {
background-color: #f7f7f7;
font-family: Consolas, Menlo, Courier, monospace;
border: none;
display: block;
font-size: 14px;
padding: 16px 32px;
}
.demo-block .demo-block-code pre {
margin: 0;
padding: 0;
}
.sh-checkbox {
color: #444;
font-weight: 500;
font-size: 14px;
position: relative;
cursor: pointer;
display: inline-block;
white-space: nowrap;
user-select: none;
}
</style>
引入并且全局注冊(cè)
import DemoBlock from './demo-block/demo-block.vue';
Vue.component('demo-block', DemoBlock);
使用highlight.js高亮
import 'highlight.js/styles/color-brewer.css';
定義router
import Vue from 'vue';
import VueRouter from 'vue-router';
Vue.use(VueRouter);
const router = new VueRouter({
routes: [
{
path: '/button',
name: 'button',
title: 'Button 按鈕',
component: r =>
require.ensure([], () => r(require('ui/docs/button.md')))
}
]
});
export default router;
button.md
## Button 按鈕
常用的操作按鈕
### 基礎(chǔ)用法
按鈕的基礎(chǔ)用法
:::demo 通過`type`、`width`屬性設(shè)置不同類型的按鈕
```html
<template>
<div>
<dv-button>默認(rèn)按鈕</dv-button>
<dv-button type="success">成功按鈕</dv-button>
<dv-button type="warning">警告按鈕</dv-button>
<dv-button type="danger">危險(xiǎn)按鈕</dv-button>
</div>
<div>
<dv-button width="100px">默認(rèn)按鈕</dv-button>
<dv-button type="success" width="100px">成功按鈕</dv-button>
<dv-button type="warning" width="100px">警告按鈕</dv-button>
<dv-button type="danger" width="100px">危險(xiǎn)按鈕</dv-button>
</div>
</template>
\``` (去除這個(gè)斜杠)
:::
### Attributes
| 參數(shù) | 說明 | 類型 | 可選值 | 默認(rèn)值 |
|--------|-------- |---------- |------------- |-------- |
| type | 類型 | string | success / warning / danger / |— |
| name | name屬性 | string | — | — |
| id | id屬性 | string | — | — |
| width | 按鈕寬度 | string | — | 100% |
效果圖

image.png
button.md在github上的展示效果

image.png