mavon-editor markdown 编辑器配置及代码块高亮显示并添加行号

效果图

代码块效果图copy

mavon-editor markdown 编辑器

项目使用mavon-editor markdown编辑器,由于项目需要存储在数据库中的是md文件,所以需要通过marked转译为HTML文件

引入mavon-editor

//安装
npm i mavon-editor
//引入
import mavonEditor from 'mavon-editor'
import 'mavon-editor/dist/css/index.css'
Vue.use(mavonEditor)
//使用
<template>
	<mavon-editor
	      v-model="content"
	      :placeholder="'Edit ···'"
	      ref="md"
	      @imgAdd="$imgAdd"
	      @imgDel="$imgDel"
	      @change="change"
	      :toolbars="toolbars"
	      :toolbarsBackground="'#f9f9f9'"
	      style="height: calc(100vh - 50px)"
	    />
</template>
//参数
toolbars: {
        bold: true, // 粗体
        italic: true, // 斜体
        header: true, // 标题
        underline: true, // 下划线
        strikethrough: true, // 中划线
        mark: true, // 标记
        superscript: true, // 上角标
        subscript: true, // 下角标
        quote: true, // 引用
        ol: true, // 有序列表
        ul: true, // 无序列表
        link: true, // 链接
        imagelink: true, // 图片链接
        code: true, // code
        table: true, // 表格
        fullscreen: false, // 全屏编辑
        readmodel: false, // 沉浸式阅读
        htmlcode: true, // 展示html源码
        help: true, // 帮助
        /* 1.3.5 */
        undo: true, // 上一步
        redo: true, // 下一步
        trash: true, // 清空
        save: false, // 保存(触发events中的save事件)
        /* 1.4.2 */
        navigation: true, // 导航目录
        /* 2.1.8 */
        alignleft: true, // 左对齐
        aligncenter: true, // 居中
        alignright: true, // 右对齐
        /* 2.2.1 */
        subfield: true, // 单双栏模式
        preview: false // 预览
      }
//methods
methods: {
    $imgAdd (pos, $file) {
      // 第一步.将图片上传到服务器.
      var formdata = new FormData()
      formdata.append('image', $file)
      this.img_file[pos] = $file
      this.$http({
        url: '/api/edit/uploadimg',
        method: 'post',
        data: formdata,
        headers: { 'Content-Type': 'multipart/form-data' }
      }).then((res) => {
        let _res = res.data
        // 第二步.将返回的url替换到文本原位置![...](0) -> ![...](url)
        this.$refs.md.$img2Url(pos, _res.url)
      })
    },
    $imgDel (pos) {
      delete this.img_file[pos]
    },
    change (value, render) {
      this.html = render
    },
    // 提交
    submit () {
      console.log(this.content)
      console.log(this.html)
    }
  }

注:该编辑器支持代码块高亮,可通过codeStyle自定义配置,本项目为了灵活运用,使用的是自定义的代码样式
具体参数请参考mavon-editor官方文档

导入文件
数据库存储数据为md文件,所以需要转译为html文件

安装

npm install marked

转译

import marked from 'marked'             //引入
//通过marked()转译
this.article.html = marked(this.article.content)

代码块高亮显示

引入

npm install highlight.js

配置
新建hljs.js,注册全局指令

import Vue from 'vue'
import hljs from 'highlight.js'
import 'highlight.js/styles/googlecode.css' // 样式文件
Vue.directive('highlight', function (el) {
  let blocks = el.querySelectorAll('pre code')
  blocks.forEach((block) => {
    hljs.highlightBlock(block)
  })
})

main.js引入hljs.js

import './plugins/hljs'

组件中使用

<div class="markdown-body" v-html="article.content" v-highlight></div>

mavon-editor 编辑器需要单独导入css文件

import 'mavon-editor/dist/markdown/github-markdown.min.css'

问题(按需使用):这样使用会在页面渲染的时候会出现高亮效果,但是这导致的问题是,切换路由的时候代码高亮会消失。之所以产生这种现象,这跟 hljs.initHighlightingOnLoad()的定义有关,因为只执行一次。
可以重写 hljs.initHighlighting()方法,在组件的中是使用 hljs.highlightCode(),每次页面加载的时候都会执行渲染代码的逻辑

//在main.js中  
import 'highlight.js/styles/googlecode.css'
import hljs from 'highlight.js'
hljs.highlightCode = function () { 
	//自定义highlightCode方法,将只执行一次的逻辑去掉
	let blocks = document.querySelectorAll('pre code');
	[].forEach.call(blocks, hljs.highlightBlock);
};
//在组件中
export default {
  mounted(){
     hljs.highlightCode()
  }    
}

代码块添加行号
新建mavon.js


import $ from 'jquery'
import Vue from 'vue'
export const addCodeBtn = _ => {
	//markdown代码存放在pre code 标签对中
  $('pre code').each(function () {
    let lines = $(this).text().split('\n').length - 1
    //添加有序列表
    let $numbering = $('<ol/>').addClass('pre-numbering')
    //添加复制按钮,此处使用的是element-ui icon 图标
    let $copy = $('<i title="copy"/>').addClass('el-icon-document-copy code-copy')
    $(this)
      .parent()
      .addClass('code')
      .append($numbering)
      .append($copy)
    for (let i = 0; i <= lines; i++) {
      $numbering.append($('<li/>'))
    }
  })
  //监听复制按钮点击事件
  $('pre.code i.code-copy').click(e => {
    let text = $(e.target).siblings('code').text()
    let element = $('<textarea>' + text + '</textarea>')
    $('body').append(element)
    element[0].select()
    document.execCommand('Copy')
    element.remove()
    //这里是自定义的消息通知组件
    Vue.prototype.$notice.success({
      msg: '代码复制成功'
    })
  })
}

在css文件中设置样式

pre.code {
    position: relative;
    border-radius: 3px;
    border: 1px solid #C3CCD0;
    overflow: hidden;
    padding-left: 60px!important;
    code {
        line-height: 30px!important;
    }
    ol.pre-numbering {
        position: absolute;
        top: 0;
        left: 5px;
        line-height: 30px;
        padding: 16px 0;
        list-style-type:none;
        counter-reset:sectioncounter;
        margin-bottom: 0;
        li{
            margin-top: 0!important;
            &:before{
                content:counter(sectioncounter) "";
                counter-increment:sectioncounter;
                display: inline-block;
                width: 40px;
                text-align: center;
                border-right: solid 1px rgba(0, 0, 0, 0.53);
            }
        }
    }
    i.code-copy{
        position: absolute;
        top:0;
        right: 0;
        background-color: #464d5e;
        padding: 3px;
        margin: 3px 3px 0 0;
        font-size: 11px;
        border-radius: inherit;
        color: #f1f1f1;
        cursor: pointer;
        display: none;
    }
    &:hover i.code-copy{
        display: block;
    }
}

last
在组件中引入

import { addCodeBtn } from '../assets/js/mavon'
this.$nextTick(_ => {
  addCodeBtn()
})

ok最后,踩坑不易,点个赞吧 ^ _ ^

发布了25 篇原创文章 · 获赞 4 · 访问量 123万+

猜你喜欢

转载自blog.csdn.net/weixin_45266125/article/details/103457165