美文网首页
前端页面渲染markDown文件

前端页面渲染markDown文件

作者: 月凉心凉 | 来源:发表于2019-03-17 21:18 被阅读0次

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

    相关文章

      网友评论

          本文标题:前端页面渲染markDown文件

          本文链接:https://www.haomeiwen.com/subject/ebspmqtx.html