Programming

Ruby で自分のための問題を解決していく話 (個人の Wiki を esa に移行した話) : 続き

  • ARTICLES
Ruby で自分のための問題を解決していく話 (個人の Wiki を esa に移行した話) の続き。前回は文章とコードでの説明ばかりになってしまったので全体的にやっていることを図にしてみた。 PukiWikiをesaへ移行する流れ 作戦としては、 一連の PukiWiki のファイルはローカルに置いて失敗があれば最初からやりなおせるようにする esa の記事作成以外は繰り返し実行可能にする Markdown の変換で PukiWiki と esa の仕様の差分を吸収できるようにがんばる 最終結果を esa 上で確認し、意図しない表示になっているものは Markdown の変換からやりなおして差分が出た記事について esa へ更新をかける という流れで、実行制限のある esa の API 呼び出しを最小限にしつつ、Wiki 内のページリンクなど PukiWiki 資産を最大限に活かせる形を考えた。実際はここまで全部最初から考えてやったわけではなくて、やりながらやっぱり Wiki 内のページへのリンクも有効にしたいなとか #ls もただ機能をつぶすのじゃなくて活用したいなとか考えては実装し、そして再度手順を実行し、という繰り返しだったのでやりなおせる構成にしたのは正解だった。 ここからは esa への新規投稿による記事 URI 確定と、二度目に Wiki 内リンクを解消した更新をかける流れを説明し、最後に繰り返し修正と更新を繰り返す中でどんな PukiWiki の仕様で引っかかったかとその対処を説明する。 esa への新規投稿で記事 URI を確定させる ページ名を日本語でもつけていることもあり、WikiName による Wiki 内のページのリンク機能を前提として書いている文章はさほどないが、[[Page name]] と囲むことでページ名を指定してのリンクは多用しているのでこれは活かしたい。 実際は記事の URI を確定させたいというだけなのだけど、esa 上に記事をつくるしかその手段がないので全記事を投稿して記事番号を採番してもらい、URI を確定させる。

Ruby で自分のための問題を解決していく話 (個人の Wiki を esa に移行した話)

  • ARTICLES
はじめに 遅くても 2008 年ごろから使っている個人の Wiki があって、調べたことや頻繁に探すことをメモしたりして使ってきた。当時職場で使っていたのが PukiWiki で使い慣れていたという理由だけで使い始めた PukiWiki をそろそろさすがに別のものにしたいなと感じていたので esa に移行をした。そのときに考えたことやこうやって移行をしたという記録。移行対象となった PukiWiki のバージョンは 1.5.0 のため、以後の各仕様は v1.5.0 のものになっている。 最初に考えたこと まずなにはなくとも PukiWiki 記法を Markdown にする必要がある。それから自分の用途としてダウンロードした各種スライドを添付していて、中にはすでに WWW 上では見つけられないものもあるので添付ファイルを完全に移行したい。そこまでどうにかできればあとは互換性のない移行をあきらめることでどうにかなるだろう。 と、まあ、あまり細かいことは考えずに始めた。 PukiWiki 記法を解釈して Markdown に変換する 検索すると正規表現を使ってごりごりと変換していくサンプルはいくつか見つかったのだが、自分でこれを修正しながら互換性を上げていく土台としてはきついなというものが多かった。そこで、パーサジェネレータを使ってみたかったという興味もあり、Parslet で PEG スタイルのパーサを書いてみることにした。 Parslet のパース結果はツリーで Array として返され、Hash が入ってる。Hash は Symbol と Parslet::Slice でできてる。Parslet::Slice は出自の位置をもった String みたいなもの。to_s をすると文字列を取り出せる。 {:toc=>"#contents"@0} #=> [Symbol, :toc] [Parslet::Slice, "#contents"@0] 実装進めるにあたっては、他の実装を参考にするのが一番イメージがつかみやすかった。 https://github.com/kschiess/parslet/tree/master/example frsyuki さんの MessagePack パーサの実装 できあがった実装が pukiwiki2md として公開されている。この Gem を使うと、Parslet に則って、Parser#parse でパースし、その結果を Transform#apply で Markdown へと変換することができる。