改善代码块折叠和选中功能

温馨提醒
总结摘要
重写了 Hugo NexT 主题中有关于代码块渲染的所有代码,修复了拷贝代码内容时末尾出现换行和其他问题,同时也增加了代码块的折叠和展开功能,让阅读的体验变得更好。

对于技术类的分享文章而言,或多或少会需要使用到代码块的功能,Hugo NexT主题中默认也是支持代码块的展示,只不过无法支持代码块进行折叠和展开的操作,且在代码选中时的样式与背景也不太容易区分,同时也还发现其他的一些小问题,那么此刻便是把它们全都整合到一起进行优化。最后几乎都可以说是完全的重构,想了解的具体其原由请看下文。

本以为只是需要给代码块增加个点击事件监听,然后进行相应的展开或折叠操作,但发现定位这个代码块的元素有些问题,原因是受限于之前实现代码块渲染功能时,使用的是内嵌入的样式来支持的,而Hugo生成的代码又是比较的混乱,导致在不同的使用场景下代码块的生成元素有差异,无法发现其中的规律来进行定位。

通过不断的测试验证,只好是放弃原来内嵌的模式,使用扩展方式(即 生成代码高亮的CSS样式 )进行对代码块的实现代码进行全部重写。从CSS样式的调整,到JavaScript动作的支持,虽然过程有些的痛苦,但是成效还是很比较明显的,代码也变得更加优雅起来,比如下面这段实现增加代码块头部的代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
let chromaDiv = document.querySelectorAll('div.highlight div.chroma');
if (chromaDiv.length === 0) return;

chromaDiv.forEach(element => {
  
  ......

  // Add code header show
  var ch = document.createElement('div');
  ch.classList.add('code-header');
  ch.classList.add(lang);
  ch.insertAdjacentHTML('afterbegin', 
    '<span class="code-lang"></span><span class="collapse-btn"></span>');
  ch.addEventListener('click', function () {       
    element.classList.toggle('hidden-code');       
    ch.querySelector('.collapse-btn').classList.toggle('collapse');
  }, false);

  element.parentNode.insertBefore(ch, element);
});
信息

至于代码选中的区分,只需要是调整来原来css中::selection和文字的颜色即可。

另外为了更好的兼容在不同浏览器进行代码拷贝,新引入了 clipboard.js 库重写代码拷贝的功能。原以为引入这个库后也可以同步解决拷贝代码时末尾出现换行的🐛,只是最后发现还是得靠自己来解决才行。这里使用的是将Dom元素中的textContent变量来代替默认的innerText,同时增加去除空格的处理。

警告

发现了很多网站的代码复制都会在末尾出现换行,这个还是有一定的风险的,特别是对于在系统终端下执行命令,万一复制的代码是有缺陷的话,而这个换行又会让复制的代码直接运行,很有可能会带来不可预知的风险,大家还是要对代码复制引起重视的。

对于用户来说这部分代码块的优化是透明无感的,使用时只需把原来全局配置中的highlight参数设置调整为如下的配置即可:

1
2
3
4
5
6
7
8
highlight:
  anchorLineNos: true
  codeFences: true
  guessSyntax: true
  # 切记这三项是一定要配置的
  lineNos: true
  lineNumbersInTable: true
  noClasses: false

嗯嗯,现在就点击下上面的代码块头部和内容拷贝,切身体验下优化的效果吧。😄