Highlight.js 添加代码行号

2016-08-10 Jamling 更多博文 » 博客 » GitHub »

js

原文链接 https://jamling.github.io/2016/08/10/Web-highlight-js-numbering/
注:以下为加速网络访问所做的原文缓存,经过重新格式化,可能存在格式方面的问题,或偶有遗漏信息,请以原文为准。


[highlight.js]是一款功能强大的代码高亮Javascript工具,支持162程序语言,自带74种高亮样式,支持自动侦测语言类型,几乎所有的markdown都支持[highlight.js]。Hexo在[syntax-highlighting-with-highlightjs]的基础上成功实现对代码行号的添加,并且做了一些优化和改进。

注:阅读本文需要一定的前端基础知识。

加载highlight.js

使用[highlight.js]非常简单,只需引入[highlight.js]的css及js(推荐在主题模板中作为全局css和js引入,引入的位置在<head></head>之间)。

<link rel="stylesheet" href="//cdn.bootcss.com/highlight.js/9.2.0/styles/github.min.css">
<script src="//cdn.bootcss.com/highlight.js/9.2.0/highlight.min.js"></script>

[highlight.js]有许多代码风格,我在这里使用的是github风格。

然后,在文档加载完毕之后初始化(推荐在</body>之前的<script></script>中引入)

``` js hljs.js https://github.com/Jamling/hexo-theme-nova/blob/master/source/js/hljs.js#L3:L4 // highlight hljs.initHighlightingOnLoad();


如此,便可以测试及查看代码高亮结果了。

## 添加行号
添加行号的大致过程是先将代码部分按行切割,得到代码行数。然后生成一个动态的行号列表ul插入到`<code>`标签之后

```js hljs.js https://github.com/Jamling/hexo-theme-nova/blob/master/source/js/hljs.js#L51:L59
    if (ds.line_number === 'frontend') {
      console.log("show line number in front-end");
      var lines = texts.length - 1;
      var $numbering = $('<ul/>').addClass('pre-numbering');
      $(this).addClass('has-numbering').parent().append($numbering);
      for (i = 1; i <= lines; i++) {
        $numbering.append($('<li/>').text(i));
      }
    }

对于有行号的<code>标签,多了一个has-numbering的样式,行号列表ul的样式为pre-numbering。通过定义has-numberingpre-numberingcss规则来控制行号与代码块的显示及对齐。

```css nova.scss https://github.com/Jamling/hexo-theme-nova/tree/master/source/css/bs/nova.scss code.has-numbering { margin-left: 1.7em !important; /因为显示行号,所以离左边有一定的距离/ word-wrap: normal; word-break: keep-all; white-space: pre; }

.pre-numbering { position: absolute; /绝对定位/ top: 0; left: 0; width: 2.2em; /行号的宽度/ height: 100%; padding: 0.5em 0.2em 0.5em 0; /上下padding保持与一致,不然出现错位/ border-right: 1px solid #C3CCD0; border-radius: 3px 0 0 3px; background-color: #EEE; text-align: right; font-size: 1.0em; /字体大小与一致/ color: #AAA; list-style: none; }


比较重要的规则在上面的css中均有注释说明。完整CSS请参考Nova中的样式。

***注,具体的样式需根据当前主题做出适当的修改***

## 处理滚动

添加了行号,为使行号与代码行不错乱,所以要求代码块在横向允许滚动,一般来说显示行号的`<code>`标签,还需加上以下css规则。
```css
code {
    overflow-x: auto;
    overflow-y: auto;
    word-break: keep-all;
    white-space: pre;
}

支持响应式

由于在小屏幕上,尤其是手机浏览器,横向滚动并不好操作,所以,在移动设备上通过媒体查询来设置行号ul不显示,并且覆盖<code>的样式规则为允许断行。

@media (max-width: 767px) {
  .pre-numbering {
    display: none;
  }
  code.has-numbering {
    margin-left: -0.5px !important;
    word-wrap: break-world !important;
    white-space: pre-wrap !important;
  }
}

支持更多的代码语言

[highlight.js]默认支持大部分主流程序语言的高亮,但是也有小部分语言是不支持的,比如[Excel VBA基础实例教程]中贴了不少VB代码,需要额外加载[highlight.js]的VBScript.js才能高亮,则需要引入额外的高亮脚本vbscript.js即可。如下所示:

<script src="http://cdn.bootcss.com/highlight.js/9.1.0/languages/vbscript.min.js" ></script>

代码复制

对于复制这块,比较好的解决方案是引入jquery的zclip插件(https://github.com/zeroclipboard/jquery.zeroclipboard)。如果用户选择的不仅仅是代码部分,则需要加入css规则来控制行号不被选择。

.pre-numbering {
  -webkit-user-select: none; /* Chrome all / Safari all */
  -moz-user-select: none; /* Firefox all */
  -ms-user-select: none; /* IE 10+ */
  user-select: none;  /* Likely future */ 
}

参考

syntax-highlighting-with-highlightjs: http://idodev.co.uk/2013/03/syntax-highlighting-with-highlightjs/ jquery.zeroclipboard: https://github.com/zeroclipboard/jquery.zeroclipboard Hexo高级教程之代码高亮: http://www.ieclipse.cn/2016/07/18/Web/Hexo-dev-highlight/

[highlight.js]: https://highlightjs.org/ [hexo]: https://hexo.io [Nova]: http://github.com/Jamling/hexo-theme-nova [Excel VBA基础实例教程]: http://www.ieclipse.cn/2016/05/13/tech-vba-guide/ [syntax-highlighting-with-highlightjs]: http://idodev.co.uk/2013/03/syntax-highlighting-with-highlightjs/