vue实现html代码高亮+行号

前言

因为引入了 TS,而添加行号的第三方包没有类型声明,整体功能实现了,但是TS会报错,如果这些无关紧要或者没有使用TS,可以放心阅读

工具

用法

高亮

highlight.js用法很简单,安装引入然后调用方法:

npm i highlight.js
import hljs from "highlight.js";

hljs.highlightBlock(block);

代码中的block是需要高亮的DOM元素

还需要引入highlight.js相关css

 <link
      rel="stylesheet"
      href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/styles/a11y-light.min.css"
      integrity="sha512-WDk6RzwygsN9KecRHAfm9HTN87LQjqdygDmkHSJxVkVI7ErCZ8ZWxP6T8RvBujY1n2/E4Ac+bn2ChXnp5rnnHA=="
      crossorigin="anonymous"
      referrerpolicy="no-referrer"
    />

行号

npm i highlightjs-line-numbers.js

highlightjs-line-numbers.js其实就是往highlight.js暴露的对象上挂载了一个提供行号的方法lineNumbersBlock,在运行的时候会先检测是否有highlight.js对象,所以要在highlight.js之后引入。

hljs.lineNumbersBlock(block);

但在实际使用的时候,发现就是检测不到highlight.js ?,是我用的不对吗?

实现方式

参考了CSDN中相关博客的实现,笔者也觉得将这个功能写成一个指令比较方便。

检测不到highlight.js的问题,检查highlightjs-line-numbers.js的源码后发现了一些可能是问题的问题:

(function (w, d) {
    ......
   if (w.hljs) {
        w.hljs.initLineNumbersOnLoad = initLineNumbersOnLoad;
        w.hljs.lineNumbersBlock = lineNumbersBlock;
        w.hljs.lineNumbersValue = lineNumbersValue;

        addStyles();
    } else {
        w.console.error('highlight.js not detected!');
    }
    ......
}(window, document));

在引入highlightjs的时候打印了hljs对象,发现打印的结果显示在highlight.js not detected!这段报错的后面,说明是引入顺序问题,但是我怎么引入都不对,那就改一下源码。

因为要修改highlightjs-line-numbers.js的源码,所以先copy了一份到utils中使用。

修改后的源码结构,不再自动执行,转为暴露一个方法:
在这里插入图片描述

if (hljs) {
    hljs.initLineNumbersOnLoad = initLineNumbersOnLoad;
    hljs.lineNumbersBlock = lineNumbersBlock;
    hljs.lineNumbersValue = lineNumbersValue;

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

指令代码:

// 为 highlight.js 高亮后的代码区域添加行号
import type { App, Directive, DirectiveBinding } from "vue";
import hljs from "highlight.js";
import { lineNumberInit } from "../utils/highlightjs-line-numbers.js";
lineNumberInit(hljs, window, window.document);

const highlightDirective: Directive = (el, binding) => {
  let blocks = el.querySelectorAll("pre code");
  blocks.forEach((block: any) => {
    hljs.highlightBlock(block);
    hljs.lineNumbersBlock(block);
  });
};

// 暴露注册指令的方法
export function setHighlightDirective(app: App) {
  app.directive("highlight", highlightDirective);
}

修改行号样式即可!

最终效果:
在这里插入图片描述


版权声明:本文为weixin_54858833原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。