在我们开发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;
}
Logo

前往低代码交流专区

更多推荐