1 原始 HTML 插入实现

测试图片

测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试

实现过程参考了:这里。我做了一点改造

html 的构成非常简单:

1
2
3
4
5
6
7
8
9
<div class="collapsible-wrapper">
<button type="button" class="collapsible">点击这里展开</button>
<div class="collapsible-content">

![测试图片](https://imgs.codewoody.com:5443/uploads/big/16f950240bc4d1c892e1aa68b58397df.jpg)

测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试
</div>
</div>

然后是 CSS 代码。博客模板中使用了 Stylus,因此这里展示 Stylus 形式的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
.post-content 
.wider
width: 120%
margin-left: -10%;
.collapsible-wrapper
border: 1px solid #999;
overflow: hidden;

.dark-theme &
border: 1px solid #eee;

.collapsible
background-color: #eee;
color: #444;
cursor: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;

.active, .collapsible:hover
background-color: #ccc;

.active, .collapsible:hover
background-color: #ccc;

.content
padding: 0 18px;
max-height: 0;
overflow: hidden;
transition: max-height 0.2s ease-out;

最后是 js 代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var coll = document.getElementsByClassName("collapsible");
var i;

for (i = 0; i < coll.length; i++) {
coll[i].addEventListener("click", function() {
this.classList.toggle("active");
var content = this.nextElementSibling;
if (content.style.maxHeight){
content.style.maxHeight = null;
} else {
content.style.maxHeight = content.scrollHeight + "px";
}
});
}

js 代码需要放在 body 的最后来确保前面的元素全部加载完成。

2 简化 Html 输入

上面的 js 和 css 代码都可以集成在 Hexo 的模板里面,所以就算是啰嗦一点也无所谓。但是 HTML 部分的输入还是太繁琐了。所以我进一步做了改造。输入我们只需要输入一个 div,这时可以采用 Pandoc 提供的简便输入方法:

1
2
3
:::{.foldable title="测试"}
哈哈哈
:::

其中 title 属性会成为原 Button 元素的内容。然后我们使用 js 来处理这个 div,将其展开成开头的完整 HTML 形式。注意下面的这段 js 代码需要插入在处理 collapsible 的 js 代码之前:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var foldable = document.getElementsByClassName("foldable");
var i;

for (i = 0; i < foldable.length; i++) {
let container = foldable[i];
let title = container.title;
let content = container.innerHTML
let contentElement = document.createElement("div")
contentElement.classList.add("collapsible-content")
contentElement.innerHTML = content

container.classList.add("collapsible-wrapper");
let btn = document.createElement("button")
btn.innerText = title
btn.type = "button"
btn.classList.add("collapsible")
container.innerHTML = "";
container.appendChild(btn);
container.appendChild(contentElement);
}

以下是渲染结果:

哈哈哈