美文网首页
vue中引入md文件,解析为组件并实现代码高亮

vue中引入md文件,解析为组件并实现代码高亮

作者: asseek | 来源:发表于2019-11-13 13:40 被阅读0次

正在撸一个基于 element 的中后台框架,文档与开发同步进行。
文档部分涉及了markdown解析,刚开始的尝试使用现成库 vue-markdown-loader,但是代码高亮部分不好定制处理,遂放弃。
第一次尝试自已写个loader,出乎意料的简单。
markdown解析使用的是hyperdown
代码高亮通过prismjs实现;
代码高亮部分刚开始是尝试用highlight.js但是不知为何JavaScript第一行的格式化会出现异常,用prismjs则无此问题。
首先安装依赖

npm install hyperdown prismjs -D

创建loader

markdown-loader.js

const HyperDown = require('hyperdown');
const Prism = require('prismjs');

function markdownLoader(val) {
  let parser = new HyperDown();
  let html = parser.makeHtml(val);
  html = html.replace(/(?<=<pre><code[^>]*?>)[\s\S]*?(?=<\/code><\/pre>)/gi, v => {
    v = v.replace(/_&/g, ' ').replace(/&quot;/g, '"').replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&amp;/g, '&');
    return Prism.highlight(v, Prism.languages.javascript);
  });
  return (
    `<template><div class="markdown">${html}</div></template>`
  );
}

module.exports = markdownLoader;

使用

项目使用的是vue-cli 3.x,在vue.config.js添加以下配置

module.exports = {
  configureWebpack: config => {
    config.module.rules.push({
        test: /\.md$/,
        use: [
          {
            loader: 'vue-loader',
          },
          {
            loader: require.resolve('./markdown-loader'),
          },
        ],
      },
    );
  },
};

在入口文件main.js导入prismjs样式

import 'prismjs/themes/prism.css';

现在可以把.md文件当成vue组件来使用了
test.md

### Install
```
npm install e-admin --save
```
### Start  
在 `main.js` 中写入以下内容:
```
import Vue from 'vue';
import App from './App.vue';
import router from './router';

import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';

import Ea from 'e-admin';
import 'e-admin/lib/index.css';

Vue.use(ElementUI).use(Ea);

Vue.config.productionTip = false;

new Vue({
  render: h => h(App),
  router,
}).$mount('#app');
```

test.vue

<template>
  <test-md></test-md>
</template>
<script>
  import testMd from './test.md';

  export default {
    components: {testMd},
组件效果图

当然也可以作为路由组件来使用,最终实现如下预期效果


路由组件效果

扩展 slot

自撸loader的另一个好处就是自由度高,我们可以随意扩展功能,比如既然md文件被解析成vue组件,因为文档通常都伴随着实例,如果能在里面md里面插入slot在使用中我们随意在插槽中插入实例,那可太方便了,实现起来也就是一个正则的事

function markdownLoader(val) {
  let parser = new HyperDown();
  let html = parser.makeHtml(val);
  html = html.replace(/(?<=<pre><code[^>]*?>)[\s\S]*?(?=<\/code><\/pre>)/gi, v => {
    v = v.replace(/_&/g, ' ').replace(/&quot;/g, '"').replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&amp;/g, '&');
    return Prism.highlight(v, Prism.languages.javascript);
  });
  // 解析slot转换为正常标签
  html = html.replace(/&lt;slot[\s\S]*?&gt;&lt;\/slot&gt;/gi, v => {
    v = v.replace(/_&/g, ' ').replace(/&quot;/g, '"').replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&amp;/g, '&');
    return v;
  });
  return (
    `<template><div class="markdown">${html}</div></template>`
  );
}

现在我们可以在md文件里面直接写slot插槽了
test-slot.md

#扩展 slot 
###default
这里插入一个默认插槽
<slot></slot>
####footer
这里插入一个具名插槽
<slot name="footer"></slot>

在我们实例中使用这个组件试试效果

<template>
  <test-slot>
    <el-button type="primary">default</el-button>
    <template v-slot:footer>
      <el-button type="success">footer</el-button>
    </template>
  </test-slot>
</template>
<script>
  import testSlot from './test-slot.md'

  export default {
    components: {
      testSlot
    },

运行 done

test-slot.md 效果

https://github.com/akebe/e-admin

相关文章

网友评论

      本文标题:vue中引入md文件,解析为组件并实现代码高亮

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