org-mode の publishing で特定のディレクトリ上のサイトマップを作成する

org-mode には publishing という機能があります。特定のディレクトリの org ファイル全てに対して変換を行ったり、変換後の HTML ファイルをアップロードするといったことができます。

この publishing では、 org-publish-project-alist の設定で :auto-sitemap を t にすると、対象ディレクトリの全ファイルへのリンクを張ったページを publish と同時に作成できます。

これを、特定のディレクトリの中のファイルに対して行いたいと考えました。例えば、毎日の日記を public_html/diary/20130905.html のような名前で diary ディレクトリにためていき、 public_html/index.html には public_html/diary/diary.html へのリンクを、 diary.html では今まで書きためた日記全てへのリンクを貼るという使い方です。

このようなサイトマップを作成するために org-publish-project-alist でどのような設定をすべきかよくわかりませんでしたし、設定できたとしても base-directory に対してのサイトマップが作成できないような気がしました。

それで色々試してみたところ、 org-publish-org-sitemap 関数に適当な project のリストを渡せば上手くいくようです。

例えば publishing で以下のような設定をしているとします。

(setq org-publish-project-alist
      '(("Homepage"
         :base-directory "~/homepage/src/"
         :recursive t
         :publishing-directory "~/homepage/html/"
         :publishing-function org-html-publish-to-html)))

ここで、~/homepage/src/diary/ というディレクトリのサイトマップを ~/homepage/src/diary/diary.org に出力したいとします。その場合、以下のような関数を実行すれば可能です。

(defun org-publish-my-sitemap ()
  (interactive)
  (org-publish-org-sitemap
   '("Diary Sitemap"
     :base-directory "~/homepage/src/diary/")
   "diary.org"))

つまり、 org-publish-org-sitemap を第一引数に diary 用のプロジェクト設定を渡して実行するのです。もちろん渡すプロジェクト設定では :Sitemap-filename などの設定も利用することが可能です。ちなみに第二引数はサイトマップとして出力するファイル名です。

この関数を publishing の際に毎回実行したければ、 preparation-function を設定すればいいでしょう。

(setq org-publish-project-alist
      '(("Homepage"
         :base-directory "~/homepage/src/"
         :recursive t
         :publishing-directory "~/homepage/html/"
         :publishing-function org-html-publish-to-html
         :preparation-function org-publish-my-sitemap)))