最近翻译了一篇 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 -->
...
大功告成,效果如下: