前端页面渲染markDown文件
在我们开发vue组件的过程中,希望把markdown文档写的插件使用说明,也展现到页面中。那么具体怎么做呢?1、安装vue-markdown-loadernpm install vue-markdown-loader --savenpm install markdown-it-container --save2、为webpack配置loader{test...
·
在我们开发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
配置options。
这一部分的代码主要是将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;
}
更多推荐
已为社区贡献3条内容
所有评论(0)