今年に入ってから Medium で楽しく遊んでいるのだが、日記コンテンツ風に目次が欲しいと思ったり。
昨年 note で目次を作ってたのを思い出し、 Medium でも同じようにやってみることにした。
準備
目次を作成するためには RSS feed が必要である。
note では RSS を出力する機能がなくて往生した(結局諦めた)が、 Medium では公式に RSS feed が用意されている。
https://medium.com/feed/@<username>
<username>
の部分に各自のユーザ名を当てはめればよい。
私の場合は https://medium.com/feed/@spiegel となる。
この feed を Google spreadsheets を読み込ませるのだが、読み込んだ feed を処理する Google Apps Script を Gist で公開している。
以前 note 用に作ったものだが、そのまま使い回せる。
このスクリプトを [ツール] → [スクリプトエディタ...] で note-toc.gs として登録する。
feed から目次(HTML)を生成する
Spreadsheets に feed を読み込ませるには IMPORTFEED
関数を使う。
以下の記述を Spreadsheets 上の適当なセルに書けば、そのセルを起点として feed の内容が展開される。
=ImportFeed("https://medium.com/feed/@spiegel", "items", true, 40)
Title | Author | URL | Date Created | Summary |
---|---|---|---|---|
The message is: consent matters. | Der Spiegel im Spiegel | https://medium.com/@spiegel/... | Fri, 06 Feb 2015 03:30:39 GMT | ... |
... | ... | ... | ... | ... |
この状態で note-toc.gs の getNoteTocHTML
関数を、タイトル・URL・日付の列を引数として呼び出す。
=IF(OR(C2="",E2="",F2=""),"",getNoteTocHTML(C1:C41,E1:E41,F1:F41))
これは、先ほどの IMPORTFEED
関数を C1 セルにセットし、 Title
が C 列、 URL
が E 列、 Date Created
が F 列にあると仮定している。
getNoteTocHTML
関数の結果は、関数を指定したセルに以下のように表示される。
<div class='note-toc'><h2>Topics 2015</h2>
<dl>
<dt>2015年01月</dt>
<dd><ul>
<li>11日 : <a href='https://medium.com/@spiegel/windows-live-writer-movable-type-308d5eff543e'>Windows Live Writer で Movable Type へ記事をアップできるようになった</a></li>
<li>28日 : <a href='https://medium.com/@spiegel/-cf152c164602'>「我々を信用してほしい」ほど信用できない言葉はない</a></li>
<li>29日 : <a href='https://medium.com/@spiegel/ghost-glibc-gethostbyname-vulnerability-cve-2015-0235-32cd766ccb6e'>“GHOST glibc gethostbyname() vulnerability CVE-2015–0235”</a></li>
<li>30日 : <a href='https://medium.com/@spiegel/e2e-peerio-f713873d3f81'>ふむ。今どき E2E で暗号化できるだけではダメなのだが、 Peerio はどんな感じなのだろう。</a></li>
<li>31日 : <a href='https://medium.com/@spiegel/islamic-state-d3d01bea4878'>“Islamic State” は何を指しているのか</a> / <a href='https://medium.com/@spiegel/-492f8f898afc'>そもそも音楽を序列化することに意味があるの?</a> / <a href='https://medium.com/@spiegel/-b16550731255'>ロボットに知的財産権はあるか?</a></li>
</ul></dd>
<dt>2015年02月</dt>
<dd><ul>
<li>01日 : <a href='https://medium.com/@spiegel/1-flattr-65e6bebc0131'>1月の flattr</a> / <a href='https://medium.com/@spiegel/freedome-20ed0c6ba4f2'>Freedome に「日本」登場</a> / <a href='https://medium.com/@spiegel/-11469ed3a240'>ほほう</a></li>
<li>02日 : <a href='https://medium.com/@spiegel/stix-d89c37fef5f3'>脅威情報構造化記述形式 STIX</a> / <a href='https://medium.com/@spiegel/2016-85f139ee5a1c'>2016年の暦</a> / <a href='https://medium.com/@spiegel/-38efb1dc7a6e'>私は賛同も反対もしない</a> / <a href='https://medium.com/@spiegel/-297546550e2f'>『まだスマホで消耗してるの?』</a> / <a href='https://medium.com/@spiegel/-aeebe8fed2f9'>そうだ! 青空文庫に寄付すればいいんじゃん</a></li>
<li>03日 : <a href='https://medium.com/@spiegel/-74edb058e82'>ダイエットしたきゃ医者に行け!</a> / <a href='https://medium.com/@spiegel/-1ffa6fc745e4'>「一時的な安全を得るために本質的な自由を放棄する人は、自由も安全も得る資格はない」</a></li>
<li>04日 : <a href='https://medium.com/@spiegel/-4958cea6de4a'>田山歴</a> / <a href='https://medium.com/@spiegel/by-sa-4-0-gplv3-b506969d363c'>BY-SA 4.0 と GPLv3 との互換性に関する議論が始まっている</a> / <a href='https://medium.com/@spiegel/storia-d385b0351191'>「まんがライフSTORIA」感想</a></li>
<li>05日 : <a href='https://medium.com/@spiegel/-b0e87cb5f8de'>「重要インフラにおける情報セキュリティ確保に係る「安全基準等」策定指針(第4版)(案)」に関するパブリックコメント募集</a> / <a href='https://medium.com/@spiegel/-dc9c90e36011'>バンアレン帯の内帯は、無かった!?</a> / <a href='https://medium.com/@spiegel/-c5cc0bde0960'>パスワードを定期的に変更しても,えっと変わらん</a> / <a href='https://medium.com/@spiegel/boinc-github-ff449a9fbfe9'>BOINC プロジェクトが GitHub へ移行</a></li>
<li>06日 : <a href='https://medium.com/@spiegel/the-message-is-consent-matters-c42f48bd276a'>The message is: consent matters.</a></li>
</ul></dd>
</dl>
</div>
見栄えはともかく、年・月・日ごとに記事が整理されているのが分かると思う。
note-toc.gs 概要
note-toc.gs は、2つの呼び出し関数と、5つのクラスで構成されている。
関数は以下の通り
-
getNoteTocHTML
: 指定したタイトル・URL・日付の各列情報から目次用の HTML ドキュメントを出力する -
createMatrix
: 列ごとの行配列を、行ごとの列配列(連想配列)に変換する
createMatrix
について少し補足しておくと、カスタム関数の呼び出し側の引数(2次元配列)は列ごとの行配列を指定するのがふつうである。
こんな感じ。
=getNoteTocHTML(C1:C41,E1:E41,F1:F41)
しかし返値として2次元配列を返す場合は行ごとの列配列で返さなくてはならない。
//回転行列ごっこ(笑)
function rotation_matrix(){
return [["cosθ","-sinθ"],
["sinθ","cosθ" ]];
}
このため、あらかじめ呼び出し側の2次元配列の包含関係を入れ替える処理を行うと便利である。
今回は getNoteTocHTML
関数内で(日付をキーに)行単位の sort を行うため、あらかじめ createMatrix
関数で変換を行う必要があった。
noteRss.sort(
function(a,b){
if( a["Date Created"] < b["Date Created"] ) return -1;
if( a["Date Created"] > b["Date Created"] ) return 1;
return 0;
}
);
createMatrix
は汎用的に作ってるつもりなので、よかったら使ってみてください。(note-toc.gs は CC0 で提供しています)
クラスは以下の通り
-
NoteToc
: 目次情報クラス -
YearOfToc
: 目次情報「年」クラス -
MonthOfToc
: 目次情報「月」クラス -
DayOfToc
: 目次情報「日」クラス -
TitleOfToc
: 目次情報「タイトル」クラス
各目次クラスは以下のような has a(包含)関係になっている。
NoteToc ◇― YearOfToc ◇― MonthOfToc ◇― DayOfToc ◇― TitleOfToc
各クラスを入れ子にすることで年・月・日ごとの整理を容易にしている。