fangpsh's blog

Pelican 文章生成目录

最近翻译了一篇 Google风格编程指南,发现章节一多,没有目录非常不友好。文章是用Markdown 写成的,手写html 代码加目录太不方便了。
Pelican 有一个生成目录的插件:extract_toc,试用了一下,发现使用三个反引号标注的代码块乱掉了,这个插件似乎调用的pandoc,而pandoc 支持的markdown 语法不包含试用三个反引号标注代码块,所以悲剧了。

改变思路,在文章页面使用JavaScript 解析DOM 树,生成目录表格。
Google 了下,Stackoverflow 看到一问题:
Is there a JavaScript solution to generating a “table of contents” for a page?
参考答案直接拿来用:

toc.js

window.onload = function () {
    var toc = "";
    var level = 0;

    document.getElementById("article-content").innerHTML =
        document.getElementById("article-content").innerHTML.replace(
            /<h([\d])>([^<]+)<\/h([\d])>/gi,
            function (str, openLevel, titleText, closeLevel) {
                if (openLevel != closeLevel) {
                    return str;
                }

                if (openLevel > level) {
                    toc += (new Array(openLevel - level + 1)).join("<ul>");
                } else if (openLevel < level) {
                    toc += (new Array(level - openLevel + 1)).join("</ul>");
                }

                level = parseInt(openLevel);

                var anchor = titleText.replace(/ /g, "_");
                    toc += "<li><a href=\"#" + anchor + "\">" + titleText
                        + "</a></li>";

                    return "<h" + openLevel + "><a name=\"" + anchor + "\">"
                        + titleText + "</a></h" + closeLevel + ">";
            }
        );

    if (level) {
        toc += (new Array(level + 1)).join("</ul>");
    }

    document.getElementById("toc").innerHTML += toc;
};

修改pelican 主题 的base.html 之类模板文件的,引入这个JavaScript 文件:

<script src="{{ SITEURL }}/theme/static/js/toc.js" type="text/javascript"></script>

修改pelican 主题的生成文章的html 模板,加一个div,另外还需要给文章内容的div 加一个id="contents"

<div id="toc">
</div>

<div id="article-content" class="entry-content">
{{ article.content }}
  </div><!-- /.entry-content -->
...

大功告成,效果如下:
pelican_toc