Vue2实现markdown语法支持,代码高亮,显示行号,复制功能

涉及组件:vue-markdownhighlight.jshighlight-line-numbersclipboard

完成功能:将数据以markdown格式渲染 ,代码部分高亮 ,代码显示行号 ,代码可一键复制

1.依赖安装
// 安装vue-markdown依赖
npm install vue-markdown
// 安装高亮
npm install highlight.js
// 安装代码行显示
npm install hightlight-line-numbers.js
// 安装复制组件
npm install clipboard --save 
2.highligh

①highlight-plugin.js插件

import Vue from 'vue';
import Hljs from 'highlight.js'
import 'highlight.js/styles/stackoverflow-dark.css' // 样式文件

let Highlight = {};
Highlight.install = function(Vue, options) {
    Vue.directive('highligh', function(el) {
        let blocks = el.querySelectorAll('pre code');
        blocks.forEach((block, index) => {
            /** 代码高亮 */
            Hljs.highlightBlock(block);
            /** 手动添加一个hljs类名,防止不支持的语言背景变空白 */
            block.classList.add('hljs');
        })
    })
}

export default Highlight;

②main.js

// 引入使代码行高亮的插件
import Highlight from "./plugins/highlight-plugin"
// 引入vue-markdown
import VueMarkdown from "vue-markdown"
import Vue from "vue";

// 将vue-markdown注册为全局组件
Vue.component("vue-markdown",  VueMarkdown)
Vue.use(Highlight);
3.使用指令

在需要支持markdown语法的组件中使用即可,文章以search.vue为例

其中source属性为md语法的内容,将内容传进组件会自动转换为html并显示在页面,此时已经实现页面支持md语法,且代码块高亮也支持,效果如下。接下来将实现代码行号显示语言显示复制代码

<template>
	<vue-markdown :source="item.content" v-highlight>
    </vue-markdown>
</template>
<script>
    
</script>

在这里插入图片描述

4.行号显示

highlight-plugin.js插件下将highlight-line-numbers引入,并新增一行代码将行号显示。

import Vue from 'vue';
import Hljs from 'highlight.js'
import 'highlight.js/styles/stackoverflow-dark.css' // 样式文件
import 'highlight-line-numbers'

let Highlight = {};
Highlight.install = function(Vue, options) {
    Vue.directive('highligh', function(el) {
        let blocks = el.querySelectorAll('pre code');
        blocks.forEach((block, index) => {
            /** 代码高亮 */
            Hljs.highlightBlock(block);
            /** 手动添加一个hljs类名,防止不支持的语言背景变空白 */
            block.classList.add('hljs');
            /** 显示行号 **/
            Hljs.lineNumbersBlock(block);
        })
    })
}

export default Highlight;

但是页面并没有出现对应的行号显示,且控制台显示highligh not...的错误,因为highlight-line-numbers默认自动执行,因此,需要对该代码进行修改。

  1. 将highlight-line-numbers.js里的代码全选复制

  2. 新建文件,修改如下

   function lineNumberInit(hljs, w, d) {
       // jshint multistr:true
   
      xxxx原代码内容
   
   export { lineNumberInit }
if (hljs) {
 hljs.initLineNumbersOnLoad = initLineNumbersOnLoad;
 hljs.lineNumbersBlock = lineNumbersBlock;
 hljs.lineNumbersValue = lineNumbersValue;

 addStyles();
} else {
 w.console.error("highlight.js not detected!");
}

  1. highlight-plugin.js文件下引入该文件,并修改代码
// highlight.js
import Vue from 'vue'
import Hljs from 'highlight.js'
import 'highlight.js/styles/stackoverflow-dark.css'
import { lineNumberInit } from "../utils/highlight-line-numbers.js";
lineNumberInit(Hljs, window, window.document);

let Highlight = {}
Highlight.install = function (Vue, options) {
    Vue.directive('highlight', function (el) {
        let blocks = el.querySelectorAll('pre code');
        blocks.forEach((block, index) => {
            /** 代码高亮 */
            Hljs.highlightBlock(block);
            /** 手动添加一个hljs类名,防止不支持的语言背景变空白 */
            block.classList.add('hljs');
            /** 从这开始是设置行号 */
            Hljs.lineNumbersBlock(block);
        })
    })
}
export default Highlight

此时,代码块成功实现行号显示。

5.copy

search.vue中引入clipboard实现复制功能。

要实现代码语言显示复制功能的前置条件,必须要有对应的元素进行展示。此处,选择操作DOM元素的方式在代码块元素pre之前创建对应的元素进行展示。

代码如下:

<template>
	<vue-markdown :source="item.content" v-highlight v-copy>
    </vue-markdown>
</template>
<script>
import Clipboard from "clipboard";
export default {
    created() {
        // 在 created 钩子函数中定义全局变量 clipboard
    	let clipboard = new Clipboard(".copy-btn");
    	clipboard.on("success", e => {
      		this.$message(messageCreate("success", "复制成功"));
      		e.clearSelection();
    	});
    	clipboard.on("error", e => {
      		this.$message(messageCreate("error", "复制失败"));
    	});
	},
      directives: {
          inserted(el) {
        	let blocks = el.querySelectorAll("pre");
        	blocks.forEach(block => {
          		let code = block.querySelector("code");
          		let div = document.createElement("div");
          		let span = document.createElement("span");
          		span.innerHTML = getLanguage(code.className);
          		div.appendChild(span);
          		div.classList.add("btn-copy");
          		let button = document.createElement("button");
          		button.setAttribute("data-clipboard-text", code.innerText);
          		button.innerText = "复制";
          		div.appendChild(button);
          		button.classList.add("copy-btn");
          		block.parentNode.insertBefore(div, block);
        });
      }
      }
}    
</script>
最终效果

此时,已经成功实现了代码的高亮、行号、语言、复制代码功能。
在这里插入图片描述

GitHub 加速计划 / vu / vue
108
18
下载
vuejs/vue: 是一个用于构建用户界面的 JavaScript 框架,具有简洁的语法和丰富的组件库,可以用于开发单页面应用程序和多页面应用程序。
最近提交(Master分支:2 个月前 )
9e887079 [skip ci] 1 年前
73486cb5 * chore: fix link broken Signed-off-by: snoppy <michaleli@foxmail.com> * Update packages/template-compiler/README.md [skip ci] --------- Signed-off-by: snoppy <michaleli@foxmail.com> Co-authored-by: Eduardo San Martin Morote <posva@users.noreply.github.com> 1 年前
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐