Octopress易筋经,目录表ToC

| Comments

卷一,介绍在Octopress中添加 Table of Contents (ToC) 的方法。

维护长博客的时候,如果加上一个目录表 (Table of Contents),会令读者对文章结构有一个清晰的把握。基于Octopress的博客系统,有两种常见的创建目录表的方式:基于 kramdown1 的实现,以及基于 jQuery 插件的实现。前者基本上不需要配置,仅要求把默认的 Markdown parser 改为 kramdown 即可。后者则需要对系统进行相对较多的修改。

方式一:利用kramdown内嵌的ToC功能

kramdown 是一款由Ruby实现的Markdown解析器。它扩展的标准Markdown语言,添加了很多语法,其中一个就是内置了ToC的实现。这让在基于Jekyll/Octopress的博客系统中插入ToC变得简单而灵活,但是不幸的是,它的目录结构和层次需要在_config.yml中指定,也就是说,这些设定是全站的,你无法在某一篇Blog中使用不同于全站的ToC结构。

实现

这种方式的配置很简单,仅需要在你的_config.yml文件中,将默认的 Markdown parser 改为 kramdown,也即,

markdown: kramdown

在kramdown中,默认的目录树层次是从h1h6,你可以用下的设定将这个层次改为从h1h3

kramdown:
    toc_levels: 1..3

插入ToC也很简单,几乎在你的文章任何地方,加入下面的代码,在相应的部分kramdown就会帮你生成并插入一个ToC,

* Put anything here
{:toc}

余下的事情就是给你的ToC润色,需要修改的样式是ul#markdown-toc

Demo

右侧透明背景的ToC即是利用kramdown实现的。由于我定义了toc_levels: 1..3,所以低于h3的标题并未出现在表中。

方式二:利用jQuery的ToC插件

这种方式实现起来稍微复杂一些,好处是可以根据需要调整ToC的层次结构。当然,它也有局限性,例如,就我的实现而言,ToC的位置是固定浮动与整篇正文之上的,也就是说它会出现在文章的最开头处。

实现

闲话少叙,下面介绍实现过程。(这里应用的方法主要参照的是Brian Clapper的博客 2 )。

  • jQuery插件支持

    按照jQuery网站的提示配置你的系统,并且下载Table of Contents jQuery Plugin,将相应的JS文件放到source/javascripts目录。

    source/_includes/custom/after_footer.html中添加

1
2
3
4
5
6
// !!! Load jQuery before this
<script type="text/javascript">
    jQuery.noConflict();
</script>
<script src="/javascripts/jquery.scrollTo.min.js" type="text/javascript"></script>
<script src="/javascripts/jquery.tableofcontents.min.js" type="text/javascript"></script>
  • 创建JavaScript文件,例如,tocgenerator.js,使其包含下面的代码,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function generateTOC(insertBefore, heading, startLv) {
    var container = jQuery("<div id='tocBlock'></div>");
    var div = jQuery("<ul id='toc'></ul>");
    var content = jQuery(insertBefore).first();

    if (heading !== undefined && heading !== null) {
        container.append('<span class="tocHeading">' + heading + '</span>');
    }

    if (startLv === undefined) { startLv = 1; }

    div.tableOfContents(content, { startLevel: startLv });
    container.append(div);
    container.insertBefore(insertBefore);
}
  • 载入创建的JS文件(source/_includes/custom/after_footer.html
1
<script src="/javascripts/tocgenerator.js" type="text/javascript"></script>
  • 创建ToC模块,依然在source/_includes/custom/after_footer.html中,添加,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{% if page.toc == true %}
  {% if page.tocstartlv %}
    <script type="text/javascript">
    jQuery(document).ready(function() {
      // Put a TOC right before the entry content.
      generateTOC('.entry-content', 'Contents', {{ page.tocstartlv }});
    });
    </script>
  {% else %}
    <script type="text/javascript">
    jQuery(document).ready(function() {
      // Put a TOC right before the entry content.
      generateTOC('.entry-content', 'Contents');
    });
    </script>
  {% endif %}
{% endif %}
  • 插入ToC

    方式一不同,第二种方法插入ToC需要在文章的开始的Liquid标签出用两个新标签toctocstartlv来控制是否显示ToC以及ToC starting level。例如,本文采用了如下设定,

      toc: true
      tocstartlv: 2
    

Demo

生成的ToC出现在文章开始处,为区别于方式一,它采用了浅蓝色的背景。可以看到,由于起始的ToC level是2,它给出从h2h4的所有目录项。另一方面,由kramdown产生的ToC由于设置的原因,仅能显示h2h3这两层的目录项。

测试部分

H3

H4

H5