前言
因为引入了 TS,而添加行号的第三方包没有类型声明,整体功能实现了,但是TS会报错,如果这些无关紧要或者没有使用TS,可以放心阅读
工具
highlight.js 实现高亮 GitHub - highlightjs/highlight.js: JavaScript syntax highlighter with language auto-detection and zero dependencies.
highlightjs-line-numbers.js为高亮后的代码添加行号 GitHub - wcoder/highlightjs-line-numbers.js: Line numbering plugin for Highlight.js
用法
高亮
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);
}
修改行号样式即可!
最终效果: