美文网首页
前端页面渲染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