Help us understand the problem. What is going on with this article?

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

More than 3 years have passed since last update.

はじめに

皆さん、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 の方法少し変更
hokkun_dayo
Java, Kotlin 開発者。Web 界隈に生息。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away