参与开源第一步! 第一次的Pull Request, 献给TeXt。
前言
TeXt是目前个人网站采用的Jekyll主题, 简单易用, 风格非常符合我的口味; 很大程度激发了我的”创作”热情。由于博文中经常需要贴一些代码块, 一键复制代码是一个需求#200。本文记录此次的PR, zouyu4524:copy-to-clipboard。
功能简述
- 为博文中的代码块右上角添加复制到剪贴板按钮 , 点击即可复制代码块内容;
- 类似Mathjax, 添加控制变量决定是否启用该功能;
- 博文内各个代码块独立控制, 即: 可仅为特定的代码块添加。
主要参考
clipboard.js是一款超轻量级的JS脚本, 实现复制到剪贴板功能。此次PR的代码依赖该脚本, 并且复制按钮的风格与操作逻辑也是相应参考其主页。
实现逻辑
仿照TeXt中对Mathjax支持的实现, 相应修改实现以上提到的功能。首先引入控制变量clipboard
指示是否需要开启该功能, 因为实现该功能需要加载clipboard.js
脚本。在需要该功能的前提下, 主要包括两个环节:
其中步骤1通过.scss
实现, 样式同样来源于clipboard.js, 做了适当的精简, 保留了与TeXt项目中定义的样式类不冲突的部分; 而步骤2通过Javascript实现, 查找对象的核心代码如下:
var snippets = document.querySelectorAll('pre');
[].forEach.call(snippets, function(snippet) {
if (snippet.closest('.snippet') !== null) {
snippet.firstChild.insertAdjacentHTML('beforebegin', '<button class="btn" data-clipboard-snippet><img class="clippy" height="20" src="/assets/clippy.svg" alt="Copy to clipboard"></button>');
}
});
其中document.querySelectorAll('pre')
3负责查找代码块, 然后通过closest('.snippet')
4判断找到的代码块任意父级是否为snippet
class, 如此便可在博文中控制每个代码块是否提供一键复制的功能了。即: 如果按照原来的插入代码块的方式仍然不提供一键复制功能, 而如果需要提供该功能, 可以在代码块外套上一层snippet
(目前的commit中已改为copyable
), 如下:
<div class="snippet" markdown="1">
```
def hello():
print('Hello world!')
```
{: .language-python}
</div>
集成到TeXt项目
上一节中介绍了实现此功能的两个步骤, 以下给出TeXt项目框架以及标注PR修改文件所在的路径。
TeXt项目结构
jekyll-TeXt-theme
├── _data
| ├── variable.yml
| └── ...
├── _includes
| ├── scripts
| | ├── lib
| | ├── ├── copy-to-clipboard.js
| | | └── ...
| | └── ...
| ├── clipboard.html // load external clipboard.js
| ├── copy-to-clipboard.html // determine whether to include clipboard.html and load copy-to-clipboard.js or not
| └── ...
├── _layouts
| ├── page.html
| └── ...
├── _sass
| ├── additional
| | ├── _copy-to-clipboard.scss
| | └── ...
| └── ...
├── assets
| ├── css
| | └── main.scss
| └── ...
├── _config.yml
└── ...
修改说明
variale.yml
添加了控制变量clipboard
, 默认为false
; 此外, 还添加了clipboard.js
的CDN地址;copy-to-clipboard.js
放置于_includes/scripts/lib
下, 执行查找页面中目标对象并动态创建按钮的功能;clipboard.html
与copy-to-clipboard.html
放置于_includes
下, 分别用于加载外部clipboard.js
和判断是否需要开启此功能;page.html
添加了执行copy-to-clipboard.html
的指令;_copy-to-clipboard.scss
5放置于_sass/additional
下, 指定了与功能相关组件的样式; 相应在main.scss
中引入此样式文件;clippy.svg
放置于assets
下, 脚本copy-to-clipboard.js
中动态创建的按钮图片路径指向此文件;_config.yml
中预设了clipboard
变量为false
。
Tips
<script>
默认是阻塞式的, 可以设置async
选项改为非阻塞式;- JS代码需要注意执行顺序, 例如
copy-to-clipboard.js
依赖外部clipboard.js
, 则需要先加载clipboard.js
。
总结
通过本次PR, 对TeXt项目的理解更进一步, 对Jekyll编译逻辑更加清晰, 对Liquid语法更熟悉。