昼呑記

PEAR::Text_Wikiを試してみた

2008-12-09 / Last Modified: 2009-09-04 21:57:30

このサイトで公開している日記やテキストは、Pukiwiki文法で書かれている。
テキストをHTMLに変換する際、これまではお手製の変換プログラムで変換していた。
だが、ちゃんと変換できているか、自信がなかった。
また、メンテナンスも大変だった。

そこで、PEARに公開されている「Text_Wiki」を使ってみることにした。

Text_Wikiを使うに当たって、検索する力が足りないせいか、Text_Wikiについて解説しているサイトが見つからなかった。
なので、Text_Wikiのコードを読んでみることにした。

以下に、コードを読んだ際にまとめたメモを公開する。

インストール

まず、Text_Wikiがインストールされているか確認する。

  $ pear list

インストールされていなかったら、Text_Wikiをインストールする。

  $ pear install Text_Wiki

とりあえず使ってみる。

  require_once "Text/Wiki.php";
  $wiki = new Text_Wiki();
  print $wiki->transform("+ Heading\n\nThis is a test.\nこれはテスト。", "Xhtml");

これでは、日本語が変換できない。
Googleで調べると、transform()を呼ぶ前に以下の一行を入れる必要があることがわかった。

  $wiki->setFormatConf("Xhtml", "translate", HTML_SPECIALCHARS);

これで、日本語も変換できた。

動き

最低限動かすためには、Text_Wikiクラスのオブジェクトを生成して、transform()を呼べばよい。

transform()の内部では、parse()とrender()を順番に呼んでいる。

parse()

parse()は、ルールと呼ばれる各規則に従いテキストをパースする。
ルールには、Heading、Url、Wikilinkなどがある。

ルールは、ルールごとにText_Wiki_Parseを継承したクラス(パースクラス)として書かれている。
パースクラスのファイルは、parseディレクトリに配置されており、ファイル名は、ルール名.php(例:Heading.php)である。
また、パースクラスの名前は、Text_Wiki_Parse_ルール名(例:Text_Wiki_Parse_Heading)である。

パースクラスにはクラスの外から設定できる設定値があり、Text_WikiクラスのsetParseConf($rule, $arg1, $arg2)で設定する。
$ruleがルール名、$arg1が設定値名と設定値が格納された配列となる。
$arg1を設定値名、$arg2を設定値にしてもよい。
パースクラスの上の方に、設定できる設定値名とその説明が書いてある。

Text_Wikiクラスのparse()は、Text_Wikiクラスの$rulesで指定されたルールのパースクラスを生成し、各クラスのparse()を呼ぶ。

パースクラスのparse()は、内部でpreg_replace_callback()を呼び、その返り値をText_Wikiクラスの$sourceに格納する。

内部で呼ばれるpreg_replace_callback()の引数は、次の通りである。
まず、第1引数である正規表現のパターンには、パースクラスの$regexが入る。
$regexにマッチさせたい正規表現を記述する。
第2引数のコールバック関数には、パースクラスのprocess(&$matches)が指定されている。
第3引数の正規表現を適用したい文字列には、元のテキスト(Text_Wikiクラスの$source)が入る。

parse()から呼ばれるprocess(&$matches)は、レンダーを行うためのトークンを埋め込んだテキストを返す。

render()

render($format)は、parse()でパースしたテキストを指定したフォーマット(xhtmlやlatexなど)に変換する。

フォーマットの詳細な設定は、Text_WikiクラスのsetFormatConf($format, $arg1, $arg2)で設定する。
レンダーの各ルールの詳細な設定は、Text_WikiクラスのsetRenderConf($format, $rule, $arg1, $arg2)で設定する。
$formatに適用したいフォーマット(例:Xhtml)を入れる。
$rule、$arg1、$arg2はsetParseConf()と同じである。
設定できる内容は、フォーマットクラス(例:Text_Wiki_Render_Xhtml)とレンダークラス(Text_Wiki_Render_Xhtml_Heading)の$confの説明を参照する。

カスタマイズ

レンダーは、デフォルトに任せてしまってほぼ問題ない。
レンダーのオプション設定でかなりカスタマイズできる。

パースも、デフォルトの記法を使うのであれば、このままでよい。
しかし、できればPukiwiki記法を使いたい。
なので、Text_Wikiクラスを継承し、自前のパーサーを作成することにする。

カスタマイズするに当たって、PEARにある既にカスタマイズされたパッケージが参考になる。
例えば、Text_Wiki_Creoleをインストールしてみて、コードを見てみるとよい。

  $ pear install Text_Wiki_Creole

まず、Text_Wikiクラスを継承して、新しいwikiクラスを作成する。

新しいwikiクラスのコンストラクタでは、適用したいルールの名前と、パースクラスがあるディレクトリを設定する。
適用するルールは、$rulesにルール名の配列を入れることで設定できる。
なお、ルールは$rulesに格納された配列の先頭から順番に適用される。
パースクラスがあるディレクトリは、addPath($type, $dir)で追加できる。

次に、パースクラスを作成する。

新しいパースクラスは、Text_Wiki_Parseを継承してを作る。
クラス名は、Text_Wiki_Parse_ルール名(例:Text_Wiki_Parse_Heading)とする。

パースクラスのコンストラクタで、ルールを適用したい正規表現のパターンを設定する。
正規表現のパターンは$regexに設定する。

正規表現のマッチはパースクラスのparse()で行われるが、親クラスであるText_Wiki_Parseクラスのparse()では不具合があるときだけオーバーライドする。
parse()では、preg_match_replace()を呼び、コールバック関数にprocess()を指定する。

必要に応じて、正規表現がマッチした場合に呼ばれるprocess(&$matches)をオーバーライドする。
process(&$matches)では、$matchesにトークンを埋め込んだり、$matchesを適当に変換したりし、その結果を返す。
トークンの埋め込みは、Text_WikiクラスのaddToken($rule, $option)で行う。