前端頁面渲染markDown檔案
阿新 • • 發佈:2019-02-06
在我們開發vue元件的過程中,希望把markdown文件寫的外掛使用說明,也展現到頁面中。那麼具體怎麼做呢?
1、安裝vue-markdown-loader
npm install vue-markdown-loader --save
npm install markdown-it-container --save
2、為webpack配置loader
{
test: /\.md$/,
loader: 'vue-markdown-loader',
options: vueMarkdown
}
3、配置options
為vue-markdown-loader
這一部分的程式碼主要是將markDown的原始碼轉換成,html程式碼。注意裡面有幾處用到了自定義的工具類,在utils.js下,後面會附帶原始碼。
這個options是被作為一個獨立的模組使用的,建議複製出來後以一個獨立的檔案儲存在build資料夾中。
const striptags = require('./strip-tag');
const vueMarkdown = {
preprocess: (MarkdownIt, source) => {
MarkdownIt.renderer.rules.table_open = function () {
return '<table class="table">'
}
MarkdownIt.renderer.rules.fence = utils.wrapCustomClass(MarkdownIt.renderer.rules.fence)
// ```code`` 給這種樣式加個class code_inline
const code_inline = MarkdownIt.renderer.rules.code_inline
MarkdownIt.renderer.rules.code_inline = function (...args){
args[0][args[1]].attrJoin('class', 'code_inline')
return code_inline(...args)
}
return source
},
use: [
[require('markdown-it-container'), 'demo', {
validate: params => params.trim().match(/^demo\s*(.*)$/),
render: function(tokens, idx) {
var m = tokens[idx].info.trim().match(/^demo\s*(.*)$/);
if (tokens[idx].nesting === 1) {
var desc = tokens[idx + 2].content;
const html = utils.convertHtml(striptags(tokens[idx + 1].content, 'script'))
// 移除描述,防止被新增到程式碼塊
tokens[idx + 2].children = [];
return `<demo-block>
<div slot="desc">${html}</div>
<div slot="highlight">`;
}
return '</div></demo-block>\n';
}
}],
[require('markdown-it-container'), 'tip'],
/* or */
[require('markdown-it-container'), 'warning']
]
};
exports.vueMarkdown = vueMarkdown;
在這段程式碼頂部,我們引入了striptags
。這個模組是用來解析示例程式碼的。strip-tag的具體內容。
const cheerio = require('cheerio')
//cheerio是nodejs的抓取頁面模組,為伺服器特別定製的,快速、靈活、實施的jQuery核心實現。適合各種Web爬蟲程式。
module.exports = (str, tags) => {
const $ = cheerio.load(str, { decodeEntities: false })
if (!tags || tags.length === 0) {
return str
}
tags = !Array.isArray(tags) ? [tags] : tags
let len = tags.length
while (len--) {
$(tags[len]).remove()
}
return $.html()
}
在webpack的build目錄下的utils.js中新增下面的兩個方法
/**
* 增加 hljs 的 classname
*/
exports.wrapCustomClass = function (render) {
return function (...args) {
return render(...args)
.replace('<code class="', '<code class="hljs ')
.replace('<code>', '<code class="hljs">')
}
};
/**
* Format HTML string
*/
exports.convertHtml = function (str) {
return str.replace(/(&#x)(\w{4});/gi, $0 => String.fromCharCode(parseInt(encodeURIComponent($0).replace(/(%26%23x)(\w{4})(%3B)/g, '$2'), 16)))
};
4、配置展示mark-down文件的vue頁面
準備一個名叫demo-block的vue檔案,放在你喜歡的地方。然後註冊全域性元件。
注意,在註冊全域性元件時,一定是叫demo-block。
import demoBlock from './components/demo-block.vue';
Vue.component('demo-block', demoBlock);
demo-block.vue檔案的原始碼。
<template>
<div
class="demo-block"
:class="[{ 'hover': hovering }]"
@mouseenter="hovering = true"
@mouseleave="hovering = false">
<slot name="source"></slot>
<div class="meta" ref="meta">
<div class="description" v-if="$slots.default">
<slot></slot>
</div>
<slot name="highlight"></slot>
</div>
</div>
</template>
<script type="text/babel">
export default {
data () {
return {
hovering: false,
}
},
}
</script>
5、設定路由
大家會發現,每一個markddow文件對應一個路由,所以我們切換markDown的時候,其實是切換的是子路由頁面。
import Vue from 'vue';
import Router from 'vue-router';
import loadMap from '@/components/loadMap.vue';
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'loadMap',
component: loadMap,
redirect:{ name : 'home' },
children: [
{
path: '/home',
name: 'home',
component: r => require.ensure([], () => r(require('../docs/readme.md')))
},
{
path: '/test',
name: 'test',
component: r => require.ensure([], () => r(require('../docs/hello.md')))
}
]
}
]
})
6、編寫一個模板文件
@這是我們展示的說明文件
**三維測量 measure**
### 基本用法
* @param type 測量型別
* line 直線測量
* area 面積測量
* vertical 垂直測量
* horizontal 水平測量
-----
@這部分是頁面上可以互動的程式碼
<div class="measure-ct">
<button @click="measure('line')">直線測量</button>
<button @click="measure('area')">面積測量</button>
<button @click="measure('vertical')">垂直測量</button>
<button @click="measure('horizontal')">水平測量</button>
<button @click="measureCancel">清除測量結果</button>
</div>
<br>
::: demo
@這部分是我們展示的示例程式碼
```shell
import {cw5} from 'cw3d/index.js';
cw5.measure.measureMent(type)
```
```html
<template>
<div>
<div class="measure-ct">
<button @click="measure('line')">直線測量</button>
<button @click="measure('area')">面積測量</button>
<button @click="measure('vertical')">垂直測量</button>
<button @click="measure('horizontal')">水平測量</button>
<button @click="measureCancel">取消測量模式</button>
</div>
</div>
</template>
<script>
import {cw5} from 'cw3d/index.js';
export default {
name: 'measure',
methods: {
measure(type){
cw5.measure.measureMent(type)
},
measureCancel(){
cw5.measure.measureCancel()
}
}
}
</script>
```
:::
7、優化樣式—-引入文件模組的css檔案
這個css檔案有兩個版本,一個lass、一個css。通常css引入就可以。
可以在任意需要css渲染的檔案中,引入這個css檔案。
<style>
@import "../assets/docs.css";
.example-block{
display: flex;
}
</style>
要引入的docs.css檔案。
body, h1, h2, h3, h4, h5, h6, hr, p, blockquote, dl, dt, dd, ul, ol, li, pre, form, fieldset, legend, button, input, textarea, th, td,
iframe {
margin: 0;
padding: 0;
border: 0;
vertical-align: baseline;
}
body {
font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', SimSun, sans-serif;
font-weight: 400;
-webkit-font-smoothing: antialiased;
background-color: #f8f8f8;
}
a {
color: #4078c0;
text-decoration: none;
}
button, input, select,
textarea {
font-family: inherit;
font-size: inherit;
line-height: inherit;
color: inherit;
}
ul, ol {
list-style: none;
}
code.hljs {
line-height: 1.5;
font-family: Source Code Pro, Menlo, Monaco, Consolas, Courier, monospace;
font-size: 12px;
padding: 20px;
background-color: #2a3138;
border: solid 1px #E5E5E5;
margin-bottom: 25px;
border-radius: 4px;
-webkit-font-smoothing: auto;
}
.clearfix::before {
display: table;
content: "";
}
.clearfix::after {
display: table;
content: "";
clear: both;
}
.main-content {
width: 50%;
margin: 50px 20px 40px;
border: 1px solid #f2f2f2;
}
.main-content .page-tip {
position: absolute;
left: 50%;
top: 60px;
transform: translatex(-50%);
height: 60px;
line-height: 60px;
font-size: 24px;
color: #0067ed;
}
.page-container {
background-color: #fff;
position: relative;
display: flex;
width: 100%;
overflow: hidden;
}
.page-content {
box-sizing: border-box;
flex: 1;
}
.page-content section {
padding: 0 40px;
}
.page-content section > h1,
.page-content section > h2,
.page-content section > h3,
.page-content section > h4,
.page-content section > h5,
.page-content section > h6 {
color: #333;
line-height: 1.5;
margin: 20px 0;
font-weight: normal;
}
.page-content section > h1:hover a,
.page-content section > h2:hover a,
.page-content section > h3:hover a,
.page-content section > h4:hover a,
.page-content section > h5:hover a,
.page-content section > h6:hover a {
opacity: .4;
}
.page-content section > h1 a,
.page-content section > h2 a,
.page-content section > h3 a,
.page-content section > h4 a,
.page-content section > h5 a,
.page-content section > h6 a {
float: left;
margin-left: -20px;
opacity: 0;
cursor: pointer;
}
.page-content section > h1 a:hover,
.page-content section > h2 a:hover,
.page-content section > h3 a:hover,
.page-content section > h4 a:hover,
.page-content section > h5 a:hover,
.page-content section > h6 a:hover {
opacity: .4;
}
.page-content section > h1 {
font-size: 34px;
}
.page-content section > h2 {
font-size: 28px;
}
.page-content section > h3 {
font-size: 22px;
}
.page-content section > h4 {
font-size: 18px;
}
.page-content section > h5 {
font-size: 16px;
}
.page-content section > h6 {
font-size: 14px;
color: #666;
}
.page-content section > p {
font-size: 14px;
line-height: 20px;
color: #666;
margin: 14px 0;
}
.page-content section > p a {
color: #38f;
}
.page-content section > ul li,
.page-content section > ol li {
color: #666;
font-size: 14px;
line-height: 20px;
margin: 10px 0 10px 20px;
padding-left: 20px;
position: relative;
}
.page-content section > ul li a,
.page-content section > ol li a {
color: #38f;
}
.page-content section > ul li::before,
.page-content section > ol li::before {
content: '';
position: absolute;
width: 8px;
height: 8px;
box-sizing: border-box;
border: 2px solid #999;
border-radius: 50%;
top: 6px;
left: 0;
}
.page-content section > ul li li,
.page-content section > ol li li {
margin-left: 0;
}
.page-content p > code,
.page-content .table code,
.page-content li > code {
background-color: #F2F2F2;
display: inline-block;
border: 1px solid #E5E5E5;
border-radius: 3px;
padding: 1px 3px;
color: #333;
margin: 0 2px;
}
.table {
border-collapse: collapse;
width: 100%;
background-color: #fff;
color: #333;
font-size: 14px;
margin-bottom: 45px;
}
.table th {
text-align: left;
border: 1px solid #E5E5E5;
background-color: #F2F2F2;
padding: 10px;
}
.table th:first-child {
padding-left: 10px;
}
.table td {
border: 1px solid #E5E5E5;
padding: 10px;
}
.l {
float: left;
}
.r {
float: right;
}
.gray {
color: #999;
}
.placeholder {
font-size: 14px;
color: #cccccc;
}
.vui-intro {
text-align: center;
}
.vui-intro__logo img {
margin: 0 auto;
}
.vui-intro__title {
font-size: 45px;
line-height: 60px;
font-weight: 400;
font-family: monospace;
}
.vui-intro__subtitle {
font-size: 15px;
color: #455a64;
}