为MarkdownPad2的HTML输出也增加目录

By | 2014/03/06

越来越喜欢Markdown了,清爽的写作让人欲罢不能。说白了哇,程序员都是懒货,所有能让自己偷懒的发明都是好发明,现在流行的语言、工具,其本质,都是可以让程序员偷懒的产物。比如脚本语言,可以10行代替编译语言的100行,至于速度,反正现在计算机快的很;比如IDE,只要点点鼠标,所有的编译连接调试都能迅速完成,当然会风靡全球。Markdown也是应懒汉需求发明的伟大作品,可以用一点点无伤大雅的符号,代替繁杂的<h1>,<table>等标记,或者移动鼠标点选几号字体,插入表格之类低效操作的,懒人当然喜欢啦!

有很多免费的Markdown写作工具,在线的也非常多,不过大多是国外的,国内的网络环境实在让人心疼。当然也有离线的,借助node-webkit,好多不错的工具应运而生,但我试用下来,还是MarkdownPad2比较好使,可惜不是免费的,好在不注册也能用,功能也足够。我喜欢它的导出HTML和PDF的功能,PDF导出是很多免费工具所不具备的,而且MarkdownPad2导出PDF的时候可以选择导出大纲,就是PDF的目录啦,导航非常方便,本质上来说,也就是把h1,h2,h3…之类的文字提取出来,用过Wiki系统的话,应该很熟悉。

可惜,MarkdownPad2导出的HTML文件无法自动自动提取目录,习惯了wiki系统的自动目录功能,总赶脚少了点什么,一个文档写的比较长的话,查找还是颇为不便的。我到官网上找了一下,貌似没人关心着个功能?不过有人问输出的HTML文件是否能够定制模板,作者回答说,MarkdownPad2刚刚出来的时候带了这功能的,但是他后来发现很多人仅仅是需要定制html的head部分就可以了,所以他把功能简化了,就在 选项高级自定义HTML Head 中…… 既然他提供了这个功能,确实也够了,我写了个js脚本,把这个脚本名字包含在head中,就像这样

<script type=”text/javascript” src=”outline.js”></script>

然后把这个js文件放在html的生成目录中,就能自动生成目录啦~~ 虽然比较难看……另外也可以直接写在<script>标记里面,这样也比较简单。

我用了比较偷懒的目录显示方式,比较好的是用列表嵌套列表形成层级的,不过实现起来略发明,于是我偷懒用空格的方式了…… 反正看起来也差不多,然后我这个脚本只支持现代浏览器,如果你想在IE8以及之前的浏览器中使用,那是没有任何效果的,不过,这和我又有什么关系呢? 🙂

document.addEventListener("DOMContentLoaded", function() {
    // 生成目录列表
    var outline = document.createElement("ul");
    outline.setAttribute("id", "outline-list");
    outline.style.cssText = "border: 1px solid #ccc;";
    document.body.insertBefore(outline, document.body.childNodes[0]);
    // 获取所有标题
    var headers = document.querySelectorAll('h1,h2,h3,h4,h5,h6');
    for (var i = 0; i < headers.length; i++) {
        var header = headers[i];
        var hash = _hashCode(header.textContent);
        // MarkdownPad2无法为中文header正确生成id,这里生成一个
        header.setAttribute("id", header.tagName + hash);
        // 找出它是H几,为后面前置空格准备
        var prefix = parseInt(header.tagName.replace('H', ''), 10);
        outline.appendChild(document.createElement("li"));
        var a = document.createElement("a");
        // 为目录项设置链接
        a.setAttribute("href", "#" + header.tagName + hash)
        // 目录项文本前面放置对应的空格
        a.innerHTML = new Array(prefix * 4).join('&nbsp;') + header.textContent;
        outline.lastChild.appendChild(a);
    }

});

// 类似Java的hash生成方式,为一段文字生成一段基本不会重复的数字
function _hashCode(txt) {
     var hash = 0;
     if (txt.length == 0) return hash;
     for (i = 0; i < txt.length; i++) {
          char = txt.charCodeAt(i);
          hash = ((hash<<5)-hash)+char;
          hash = hash & hash; // Convert to 32bit integer
     }
     return hash;
}

估计很小众,不会有什么人会用到。不过现在自己很看得开了,没准有人需要呢?或者没准有人需要里面的代码片段呢?还是拿出来凑凑篇数吧~~

6 thoughts on “为MarkdownPad2的HTML输出也增加目录

发表评论

您的电子邮箱地址不会被公开。