原文博客地址:傳送門。
隨着網上利用Jekyll+Github Pages搭建個人靜態博客的帖子越來越多,按照教程自己動手搭一個基於Github賬戶的博客已完全成爲一個五分鐘速成課程的內容了。網上也隨處可見優美的博客主題,且能完全即插即用。但對於一些想要更深入定製化的博主,本文主要集合自己折騰的經驗介紹下如何給Jekyll博客添加目錄(即Table of Content)以及定製化目錄顯示的ScrollSpy效果。
如下圖所示,生成ScrollSpy效果的目錄結構主要有三個部分。
1 目錄生成插件選擇
Jekyll官網上的plugins目錄下便列出了很多有用的插件,其中關於目錄生成的jekyll-toc-generator便是官方推薦的。但對於在Github上建站的同學應該知道,Github禁止了很多plugins的自動build,儘管也正在增加一些插件白名單,但貌似這個插件是不能通過源碼提交給Github pages自動build的。因此對於不想通過設定.nojekyll 本地build,然後push整個靜態代碼到Github上的同學,可能一些純javascript的插件便是首選。
1-a 純JS版本
本文所用的便是純javascript版的toc插件jekyll-table-of-contents.
其README也很詳細,照着一步步配即可。
* 在待添加插件的模板中首先加入jquery.js
的依賴,然後是把該toc.js
放在其後。
<script src="/javascripts/jquery-2.1.4.min.js" type="text/javascript"></script>
<script src="/javascripts/toc.js" type="text/javascript"></script>
- 在需要顯示目錄結構的地方加上如下div。
<div id="toc"></div>
-
把toc.js調用函數放在最後(如
</body>
之前)即可。
<script type="text/javascript">
$(document).ready(function() {
$('#toc').toc();
}); </script>
2 Markdown實現版本
Toc插件生成目錄的原理便是藉助markdown爲每個header生成一個唯一的id,然後Toc便會尋找這樣的header id逐一的構造相應的錨鏈接,並顯示即可。
常見的Markdown實現如rdiscount,kramdown,redcarpet。不同的版本,需要在_config.yml
文件中進行相應的配置。如對於rdiscount,配置如下:
markdown: rdiscount
rdiscount:
extensions:
- generate_toc
值得說明的是,我發現rdiscount對每個header會生成相同的id,便導致了Toc插件生成的所有目錄都被定向到同一個錨鏈接。在網上收了下有一些issues談到這方面的問題,如:
1. https://github.com/jekyll/jekyll/issues/110
2. https://github.com/jekyll/jekyll/issues/471
3. https://github.com/ghiculescu/jekyll-table-of-contents/issues/16
所以如果有同學遇到類似的情況,可以用其他的markdown版本,如redcarpet.
對於redcarpet,配置如下:
markdown: redcarpet
redcarpet:
extensions: [with_toc_data]
用redcarpet時同樣值得注意的是,對於使用<!--more-->串來做摘要分割符的會發現redcarpet並不能根據其來準確的截取相應的摘要串。原因便是redcarpet會對一些字符如<,>
進行轉義,變成相應的<,>
。
2-a 錨鏈接縮進問題
當你爲網頁設置了一個固定位置的導航欄(具有確定的高度),然後你爲其他頁面內容生成了錨鏈接(如本文提到的目錄結構)。當你點擊錨鏈接時,頁面會跳轉到相應的錨鏈接位置,且該錨鏈接的起始點會縮進到最上方,而部分被導航欄遮住。如下表左表所示:
點擊:http://foo.com/#bar
錯誤 (but the common behavior): 正確:
+---------------------------------+ +---------------------------------+
| BAR///////////////////// header | | //////////////////////// header |
+---------------------------------+ +---------------------------------+
| Here is the rest of the Text | | BAR |
| ... | | |
| ... | | Here is the rest of the Text |
| ... | | ... |
+---------------------------------+ +---------------------------------+
而你希望的行爲則是如右表所示的。對此,可以在toc腳本生成header時爲其添加一個div的class,
<h1><a class="anchor" name="barlink">Bar</a></h1>
然後在css中設置起式樣爲:
/* 具體padding高度可以根據你導航欄的高度來設定 */
.anchor{padding-top: 50px;}
3 爲目錄顯示添加scrollspy效果
scrollspy效果即導航欄或目錄會隨着頁面的滑動位置自動顯示當前所在的段落所屬的導航條目。其主要是基於著名的bootstrap來實現的。W3Cschool上有一個設置scrollSpy的簡單教程。但其主要是針對手動設置header id的情況。針對通過toc.js自動生成header id的配置如下:
-
添加bootstrap式樣頭和腳本
<link rel="stylesheet" href="/stylesheets/bootstrap.min.css">
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
- 在你想要操作的頁面範圍內(通常是)內設置滾動事件的響應目標(可以是id或是class,此處我們用toc表示目錄),如下:
<body data-spy="scroll" data-target=".toc" data-offset="20">
- 設置你的toc div:
<div class="toc">
/* 你的scrollSpy目錄結構將要顯示在這裏 */
</div>
-
在你的toc.js腳本中添加bootstrap中的`nav nav-pills nav-stacked`類:
/* 把 html = settings.title + " <" + settings.listType + ">" 變成如下 */
html = settings.title + " <" + settings.listType + " class = 'nav nav-pills nav-stacked'>";
So long, and Thanks for all the fish.
參考
[1]. jekyll-table-of-contents.
[2]. positionfixed-page-header-and-anchors.
[3]. W3cScholl.
[4]. Implementing
ScrollSpy