让Chirpy主题的文章支持折叠展示代码块

(本文最先发表于Zhu's Blog,未经书面授权许可,任何个人和组织不得以任何形式转载、引用本人的任何文章。本人保留追究侵权者法律责任的权利。)

      使用Chirpy主题发表文章时,插入的代码块会全部显示出来。在代码行数比较多的情况下,读者的阅读体验会比较差。阿猪希望能实现CSDN博客那样的折叠展示效果。

      经过一番折腾,终于搞定。先上效果图:

一、代码原型 

<!DOCTYPE html>
<html lang="zh-cn">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>折叠代码块示例 - Demo of fold code blocks</title>
  <style>
    .collapsible-container {
      margin-bottom: 10px;
    }

    .collapsible-container p {
      cursor: pointer;
      margin: 0;
    }

    .collapsible-content {
      overflow-x: auto;
      overflow-y: hidden;
      margin-top: 10px;
      max-height: calc(1.5em * 5); /* 折叠时的默认高度 Default fold height*/
    }
  </style>
  <script>
    document.addEventListener("DOMContentLoaded", function () {
      let coll = document.getElementsByClassName("collapsible-container");
      let maxLines = 5; // 设置折叠显示的行数 Maximum number of lines to display without collapsing

      for (let i = 0; i < coll.length; i++) {
        let trigger = coll[i].querySelector('.collapsible-trigger');
        let content = coll[i].querySelector('.collapsible-content');
        let codeLines = content.textContent.split('\n').length;

      /*codeLines=实际行的行数*2+一行换行空行,因为chirpy主题使用了<table>标签,里边包含两列,所以js会将1行代码视为2行。下边被注释掉的代码可以查看codeLines的真实值。codeLines=real_lines*2+1wrap_blank_line,because the chirpy theme uses <table> with 2 columns,which js reguard 1 line as 2 lines. The code section below can help you see the real value of codeLines.*/
      let tempcodeLines = content.textContent.split('\n').length;
      let lineCount = document.createElement('span');
      lineCount.textContent = ' (' + tempcodeLines + ' lines)';
      coll[i].appendChild(lineCount);

        if (codeLines -3 <= maxLines) {
          trigger.style.display = 'none';
        } else {
          trigger.addEventListener("click", function () {
            this.classList.toggle("active");
            if (content.style.maxHeight) {
              content.style.maxHeight = null;
            } else {
              content.style.maxHeight = content.scrollHeight + "px";
            }
          });
        }
      }
    });
  </script>
</head>
<body>
  <p>折叠代码块示例 - Demo of fold code blocks</p>

  <div class="collapsible-container">
    <pre class="collapsible-content">
      <code>
        function helloWorld() {
          console.log("Hello, World!");
        }
        function helloWorld() {
          console.log("Hello, World!");
      </code>
    </pre>
    <p class="language-javascript collapsible-trigger">展开/收起 - Fold/Unfold</p>
  </div>
</body>
</html>

  在上边的代码中:
(1)根据代码的结构,选择一个合适的标签位置作为容器,为其添加collapsible-container类属性。建议使用collapsible-content的父层。这里使用了<pre>的父层<div>
(2)根据代码的结构,在collapsible-container的内部选择一个合适的标签作为折叠/展开的对象,为其添加collapsible-content类属性。这里使用了用作格式预处理的<pre>标签,因为它完整的包含了用于展示的代码内容。
(3)根据代码的结构,在collapsible-container的内部、collapsible-content之外,选择一个合适的标签放置点击动作。这里选择在</pre>的下方放置一个<p></p>
(4)<style>内部通过CSS控制折叠时的高度等显示效果。
(5)<script>内部通过JavaScript实现折叠/展开的动作。

二、修改Chirpy主题

  根据Chirpy主题的代码结构特征,阿猪的大致修改思路是:
(1)选择<div class="language-xxx highlighter-rouge">作为容器;
(2)选择<div class="highlight">作为折叠/展开的对象;
(3)在<div class="highlight"></div>的后边插入点击按钮;
(4)将JavaScript语句存放为单独的外部文件,在<div class="post-content">的前边插入引用语句;
(5)将CSS插入现有的css文件中。

  请谨慎修改,注意Chirpy主题的版本差异可能会导致行位置不同或代码结构不同。具体的修改过程如下,仅供参考:
1、修改"\_includes\refactor-content.html"
(1)第29行,在第2个<div>的class中增加一个collapsible-content
(2)第198行,在<div>的class中增加一个collapsible-content
(3)第199行,在<div>的class中增加一个collapsible-content
(4)第230行,在<div>的class中增加一个collapsible-content
(5)第30行,在'</code></div>之后添加入下代码:

<p class="language-javascript collapsible-trigger collapsible-trigger-css">展开/收起</p>

 (6)第26行,插入如下代码:

{% if _content contains '<div class="language-' and '<div class="post-content">'%}
  {% assign _content = _content
    | replace: '<div class="language-', '<div class="collapsible-container language-'
    | replace: '<div class="post-content">', '<script src="/assets/js/collapsible.js"></script><div class="post-content">' %}
    {% endif %}

 2、修改\assets\css\style.scss
  在文件的最下方空白处插入如下代码:

.collapsible-container {
  margin-bottom: 10px;
}

.collapsible-container p {
  cursor: pointer;
  margin: 0;
}

.collapsible-content {
  overflow-x: auto;
  overflow-y: hidden;
  margin-top: 10px;
  max-height: calc(1.6em * 5); /* Adjust this value to show more lines (n) */
}
.collapsible-trigger-css {
   color: gray; 
   text-align: center; 
   font-size: small;
}


/* Custom scrollbar style for all elements */
::-webkit-scrollbar {
  width: 5px;
}

::-webkit-scrollbar-track {
  background: transparent;
  border-radius: 10px; /* Increase border-radius for a more rounded look */
}

::-webkit-scrollbar-thumb {
  background-color: rgba(0, 0, 0, 0.3);
  border-radius: 10px; /* Increase border-radius for a more rounded look */
  border: 5px solid transparent; /* Reduce border size and use transparent color */
  background-clip: padding-box;
}

::-webkit-scrollbar-thumb:hover {
  background-color: rgba(0, 0, 0, 0.4);
}

/* Edge and other browsers scrollbar style */
html {
  scrollbar-width: thin; /* Use 'thin' instead of a fixed width */
  scrollbar-color: rgba(0, 0, 0, 0.3) transparent; /* Use 'transparent' color for scrollbar track */
}

3、创建\assets\js\collapsible.js

document.addEventListener("DOMContentLoaded", function () {
  let coll = document.getElementsByClassName("collapsible-container");
  let maxLines = 5; // 设置折叠显示的行数 Maximum number of lines to display without collapsing

  for (let i = 0; i < coll.length; i++) {
    let trigger = coll[i].querySelector('.collapsible-trigger');
    let content = coll[i].querySelector('.collapsible-content');
    let codeLines = content.textContent.split('\n').length;

    /* codeLines=实际行的行数*2+一行换行空行,因为chirpy主题使用了<table>标签,里边包含两列,所以js会将1行代码视为2行。下边被注释掉的代码可以查看codeLines的真实值。codeLines=real_lines*2+1wrap_blank_line,because the chirpy theme uses <table> with 2 columns,which js reguard 1 line as 2 lines. The code section below can help you see the real value of codeLines.
    let tempcodeLines = content.textContent.split('\n').length;
    let lineCount = document.createElement('span');
    lineCount.textContent = ' (' + tempcodeLines + ' lines)';
    coll[i].appendChild(lineCount);
    */

    if (codeLines - 6 <= maxLines) { /*根据主题的实际情况将codeLines调整为实际行数 Adjust codeLines to real lines*/
      trigger.style.display = 'none';
    } else {
      trigger.addEventListener("click", function () {
        this.classList.toggle("active");
        if (content.style.maxHeight) {
          content.style.maxHeight = null;
        } else {
          content.style.maxHeight = content.scrollHeight + "px";
        }
      });
    }
  }
});

三、一些注意事项
  经过以上修改,文章内插入的代码就可以实现折叠显示的效果了。
  以下是一些注意事项,供大家参考:
(1)直接将JavaScript代码插入html页面时,本地测试正常,但是发布到Github Pages上却不起作用;如果把JavaScript代码存放到js文件中然后再引用,却可以起作用。阿猪一直没搞明白到底是为什么,可能是因为浏览器或者Github Pages的安全机制在搞怪。
(2)CSS代码和JavaScript代码不要重复写入,否则“展开”按钮会失效。
(3)如果你想更改默认的折叠行数,需要注意JavaScript认为的行数与肉眼看到的行数之间的差异,否则可能会出现代码行数很短,但是仍然会出现“展开”按钮的情况。
  JavaScript代码使用textContent.split('\n').length来判断collapsible-content所在标签内的纯文本内容的行数。换行后的空行会占用一行,一些横向显示的嵌套标签也会分别占用一行。例如Chirpy主题使用包含两个columns的<table>显示代码,肉眼看到是一行,但是对JavaScript来说却是行列。
(4)CSS代码中对显示效果做了适当的调整,好让代码框看起来更美观。保留了横向滚动条,隐藏了纵向滚动条。使用障眼法让滚动条看起来更细更圆滑。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值