FreeStyleWikiにpermalinkを入れるよう改造してみた
FSWikiはページ内の見出し単位で編集が可能なのですが、はてなダイアリーのような見出し単位での個別表示がありません。そこでそれをできるようにしようと思いました。
まず、FSWikiはplugin構成になっているのでpluginでできないか調べました。
どうやら個別ページ表示のほうはpluginでできます。ページを作るプラグインは、coreプラグインのEditPage.pmが参考になります。
一方、ページのほうにpermalinkページへのリンクを埋める処理ですが、こちらはフックは無いようなので、見出し個別編集へのリンクなどを埋める処理をしているlib/Wiki/HTMLParser.pmに埋め込むことにしました。
とりあえず、インラインでのpermalinkページへのリンク埋め込みを追加。
InterWikiのようにWikiNameへの対応。。。とかして無いけど投稿
以下は最新版より古い内容です。
permalinkページ表示&個別ページへのリンク埋め込みplugin
FSWikiのpluginは、pluginディレクトリにplugin名のディレクトリを作り、Install.pmを所定の書式で書けばよい構造になっています。Install.pmのinstallメソッドで、各コールバックを登録する構造になっています。コールバックが行われるポイントは、ページ内に埋め込むinlineプラグイン、メニュー、ページ表示、HTML生成時のフックなどいろいろあります。
ページを表示するコールバックはadd_handlerで、そこに登録したモジュールのdo_actionメソッドが呼び出されます。その戻り値にHTMLを出せば、ページ化してくれます。
permalinkページへのリンクを埋め込むプラグインは、inlineプラグインとして登録します。こちらはadd_inline_pluginで登録し、inlineメソッドが呼び出されます。
plugin/permalink/Install.pm
############################################################ # # 見出しごとに個別ページにするplugin # ############################################################ package plugin::permalink::Install; use strict; sub install { my $wiki = shift; $wiki->add_handler("PERMALINK","plugin::permalink::PermaLink"); $wiki->add_inline_plugin("plink","plugin::permalink::PermaLink","HTML"); } 1;
############################################################################### # # <p>有効化することで見出し部分をページ化できます。</p> # <p>インラインで見出し個別ページへのリンクを張ることができます。</p> # <pre> # {{plink ページ名, 見出し番号}} # </pre> # ############################################################################### package plugin::permalink::PermaLink; use strict; #============================================================================== # コンストラクタ #============================================================================== sub new { my $class = shift; my $self = {}; return bless $self,$class; } #============================================================================== # アクションの実行 #============================================================================== sub do_action { my $self = shift; my $wiki = shift; my $cgi = $wiki->get_CGI; my $page = $cgi->param("page"); my $artno = $cgi->param("artno"); my $pagename = Util::url_encode($page); my $scriptname = $wiki->config('script_name'); my $pagecontent = $wiki->get_page($page); my $content = &_read_by_part($pagecontent, $artno); my $buf = $wiki->process_wiki($content); my $subtitle = &_get_subtitle($content); if ($subtitle) { $wiki->set_title($page . "#" . $artno .": " . $subtitle); } else { $wiki->set_title($page . "#" . $artno); } my $prevno = $artno - 1; my $nextno = $artno + 1; my $prevname = &_get_subtitle_at($pagecontent, $prevno); my $nextname = &_get_subtitle_at($pagecontent, $nextno); my $prevlink = ""; if ($prevname) { $prevlink = "<a href=\"$scriptname?action=PERMALINK&page=$pagename&artno=$prevno\">$prevname</a>" . Util::escapeHTML(" << "); } my $nextlink = ""; if ($nextname) { $nextlink = Util::escapeHTML(" >> ") . "<a href=\"$scriptname?action=PERMALINK&page=$pagename&artno=$nextno\">$nextname</a>"; } my $pagelink = "<a href='$scriptname?page=$pagename'>$page</a>"; my $navi = "<div class=\"comment\"><p>[ " . $prevlink . $pagelink . $nextlink . " ]</p></div>"; $buf = $navi . $buf . $navi; return $buf; } #============================================================================== # インライン処理 #============================================================================== sub inline { my $self = shift; my $wiki = shift; my $page = Util::trim(shift); my $artno = Util::trim(shift); my $pagename = Util::url_encode($page); my $scriptname = $wiki->config('script_name'); my $content = &_read_by_part($wiki->get_page($page), $artno); my $subtitle = &_get_subtitle($content); if (!$subtitle) { my $subtitle = $artno; } my $permalink = "<a href=\"$scriptname?action=PERMALINK&page=$pagename&artno=$artno\">$page: $subtitle</a>"; return $permalink; } #============================================================================== # パート編集の場合の編集部分の取り出し copy from read_by_part in core/EditPage.pm #============================================================================== sub _read_by_part { my $page = shift; my $num = shift; my $count = 0; my $buf = ""; my $level = 0; my $flag = 0; foreach my $line (split(/\n/,$page)){ if($line=~/^(!{1,3})/){ if($flag==1 && $level<=length($1)){ last; } if($count==$num){ $flag = 1; $level = length($1); } $count++; } if($flag==1){ $buf .= $line."\n"; } } return $buf; } #============================================================================== # 見出し切り出し #============================================================================== sub _get_subtitle { my $content = shift; if ($content =~ /^!+(.*)/) { return Util::escapeHTML(Util::trim($1)); } return ""; } #============================================================================== # 特定見出し切り出し #============================================================================== sub _get_subtitle_at { my $pagecontent = shift; my $artno = shift; my $content = &_read_by_part($pagecontent, $artno); return &_get_subtitle($content); } 1;
permalinkリンクの埋め込みの修正
FSWikiはフックできる部分が多く、大抵はプラグインでフックにコールバックを登録すればよいのですが、ここはフックがなかったので、直接埋め込みました。
場所は、lib/Wiki/HTMLParser.pmの180行目くらいの個別編集リンク生成の直後に入れています。このため、個別編集モードをONにしないと、permalinkは表示されませんが。
if ($self->{wiki}->is_installed("permalink")) { my $page = $wiki->get_CGI()->param("page"); my $full = $page; my $path = $self->{wiki}->config('script_name'); if(index($page,":")!=-1){ ($path,$page) = split(/:/,$page); $path = $self->{wiki}->config('script_name')."/$path"; } my $pagename = &Util::url_encode($page); my $artno = $self->{partedit}->{$full}; # 「編集」の残りデータを再利用 my $permalink = " [<a class=\"partedit\" href=\"$path?action=PERMALINK&page=$pagename&artno=$artno\">Permalink</a>]"; $part_edit .= $permalink; }
怪しかった部分を完全に見出し編集とあわせることで、きちんと対応するようになった。