LoginSignup
17
16

More than 5 years have passed since last update.

GitHub の Markdown に TOC (目次) を付けるブックマークレット (vanilla JS 編)

Last updated at Posted at 2017-05-09

はじめに

皆さん、GitHub で Markdown 読む機会、意外と多いですよね。長い README とか、目次が欲しくなってきます。
そで、kobake@github さんによる GitHub の Markdown に TOC (目次) を付けるブックマークレット という記事を以前見つけてありがたく利用していたのですが、どうやら最近 GitHub の各ページから jQuery にアクセスできなくなったようでした。なので、こちらのブックマークレットを vanilla JS で書き直してみました。何か問題・ご意見・ご指摘等があればコメントお願いします!

Bookmarklet

a. 適当なページをブックマークします
b. URL を以下に変更(コピペ)します

bookmarklet
javascript:(function(){var e=(function(){/*.toc{border: 1px solid #aaa;padding: 4px 12px;margin-bottom: 12px;position: relative;padding-top: 30px;}.toc-title{display: inline-block;width: auto;background-color: #ccc;position: absolute;left: 0px;top: 0px;font-size: 8pt;padding: 2px 4px;padding-right: 8px;color: #666;}.toc-h{font-size: 11pt;}.toc-h1{}.toc-h2{margin-left: 20px;}.toc-h3{margin-left: 40px;}*/}).toString().match(/[^]*\/\*([^]*)\*\/\}$/)[1];var f=document.createElement('style');f.classList.add("toc-style");f.innerHTML='\n'+e+'\n';document.head.appendChild(f);var g=document.createElement('div');g.classList.add('toc');var i=document.createElement('div');i.classList.add('toc-title');i.innerHTML='TOC';g.appendChild(i);var j=document.querySelectorAll('.markdown-body')[0];j.insertBefore(g,j.firstChild);document.querySelectorAll('.markdown-body h1, .markdown-body h2, .markdown-body h3').forEach(function(a){var b=a.tagName.toLowerCase();var c=document.createElement("div");c.classList.add("toc-h");c.classList.add("toc-"+b);var d=document.createElement("a");c.appendChild(d);d.innerHTML="- "+a.childNodes[1].textContent;d.href=a.querySelectorAll('a')[0].href;g.appendChild(c)})})();

c. お好みの GitHub の markdown でブックマークを開きます(実行します)
d. ご覧あれ(例は facebook/react の README)

github-toc.gif

圧縮前コード

javascript: (function() {
    var style = (function () {/*
        .toc{
            border: 1px solid #aaa;
            padding: 4px 12px;
            margin-bottom: 12px;
            position: relative;
            padding-top: 30px;
        }
        .toc-title{
            display: inline-block;
            width: auto;
            background-color: #ccc;
            position: absolute;
            left: 0px;
            top: 0px;
            font-size: 8pt;
            padding: 2px 4px;
            padding-right: 8px;
            color: #666;
        }
        .toc-h{
            font-size: 11pt;
        }
        .toc-h1{
        }
        .toc-h2{
            margin-left: 20px;
        }
        .toc-h3{
            margin-left: 40px;
        }
    */}).toString().match(/[^]*\/\*([^]*)\*\/\}$/)[1];

    var styleEl = document.createElement('style');
    styleEl.classList.add('toc-style');
    styleEl.innerHTML = '\n' + style + '\n';
    document.head.appendChild(styleEl);

    var tocDiv = document.createElement('div');
    tocDiv.classList.add('toc');
    var tocTitleDiv = document.createElement('div');
    tocTitleDiv.classList.add('toc-title');
    tocTitleDiv.innerHTML = 'TOC';
    tocDiv.appendChild(tocTitleDiv);

    var markdownBody = document.querySelector('.markdown-body');
    markdownBody.insertBefore(tocDiv, markdownBody.firstChild);

    Array.prototype.forEach.call(document.querySelectorAll('.markdown-body h1, .markdown-body h2, .markdown-body h3'), function(node){
        // level
        var tagName = node.tagName.toLowerCase();

        // link div
        var linkDiv = document.createElement('div');
        linkDiv.classList.add('toc-h');
        linkDiv.classList.add('toc-' + tagName);

        // link
        var aEl = document.createElement('a');
        aEl.innerHTML = '- ' + node.childNodes[1].textContent;
        aEl.href = node.querySelector('a').href;
        linkDiv.appendChild(aEl);

        // append
        tocDiv.appendChild(linkDiv);
    });
})();

備考

  • style はkobake@githubさんのものを流用させていただきました。問題あればコメントお願いします。
  • aEl.innerHTML = "- " + node.childNodes[1].textContent の部分を調整すれば各見出しの見た目をいじれます。
  • querySelectorAll は比較的新しいですが、IE8以上で動くと思います(確認はしてない)
  • 動作確認は Chrome だけ行ってます。
  • 今後また GitHub 上の構造変化がある可能性もありますので、その際はまたコメント等でお知らせください。

TODO

  • jQuery の remove の部分は条件分岐面倒だったのでスキップしてる。必要なら書く。
  • 圧縮前コードを GitHub or Gist に移動します

history

  • querySelectorAll である必要がない部分を querySelector に変更した
  • quotation の種類を統一した
  • Array.prototype.forEach
  • Minify の方法少し変更
17
16
5

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
16