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

Google spreadsheets で Medium 目次作成支援

More than 5 years have passed since last update.

今年に入ってから 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.gsgetNoteTocHTML 関数を、タイトル・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.gsCC0 で提供しています)

クラスは以下の通り

  • NoteToc : 目次情報クラス
  • YearOfToc : 目次情報「年」クラス
  • MonthOfToc : 目次情報「月」クラス
  • DayOfToc : 目次情報「日」クラス
  • TitleOfToc : 目次情報「タイトル」クラス

各目次クラスは以下のような has a(包含)関係になっている。

NoteToc ◇― YearOfToc ◇― MonthOfToc ◇― DayOfToc ◇― TitleOfToc

各クラスを入れ子にすることで年・月・日ごとの整理を容易にしている。

spiegel-im-spiegel
職業エンジニアは無期休業中。
https://baldanders.info/
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
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  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
ユーザーは見つかりませんでした