Pukiwiki 1.5.3も無理やりMarkdown化した
#ref(https://oncologynote.jp/img/2a74686299.png,Pukiwiki 1.5.3も無理やりMarkdown化した)
もともとpukiwiki 1.5.0を無理やりMarkdown対応したという記事がqiitaにありました。確かにタイトルにあるとおり無理やり腕力でMarkdownにしたものなのでやや強引な感じは否めませんが、非常に興味深いものです。
** 関連記事
#ogp(https://qiita.com/devneko/items/fafac4ade37c9cb3d2f4) #ogp(https://oncologynote.jp/?baa57eda56)
** イヤでもデファクトスタンダードになっているMarkdown
もともと文法のわかりやすさや機能性はpukiwiki記法のほうがMarkdownより優れていると思います。リンクも分かりやすいし、文字色などのスタイリングもpukiwiki記法の方が柔軟です。しかし、世の中はますまずMarkdown記法が使える局面が増えてきています。
Windows/Macを問わずMarkdownを書くためのアプリは増えていますし、iPadなどで文書を書く人にもMarkdown記法は使いやすい書式になっています。もはやMicrosoft OfficeのWordで書かれる文書よりもMarkdownのほうが多いのではないでしょうか。そういう時代ですから、pukiwikiもMarkdownで書ければ良いのになと思っていたのでした。何よりも、MarkdownはTyporaにせよiA writerにせよ自分の使い慣れたライティングソフトで書きやすいのが良い。
** pukiwiki-mdをまねてPukiwiki 1.5.3をpukiwiki153-md化する
そこで、pukiwiki 1.5.0で止まっていたpukiwiki-mdを無理やりMarkdown化をpukiwiki 1.5.3に応用してみることにしました。色々と試行錯誤していますが、まだ十分には動作検証はできていません。それでも、なんとかpukiwiki 1.5.3のMarkdown版として動くところまでは来ました。PHP 7.4で動作しています(1.5.3なのでPHP 8では動きません)。
> とりあえずテスト環境では動作していますが、現在動作確認中です。ご使用は自己責任で。 https://github.com/m0370/pukiwiki153_md
#ogp(https://github.com/m0370/pukiwiki153_md/releases/tag/pukiwiki1.5.3md)
** サンプル
#hoge 文章です。 FrontPageで内部リンクを張れる。 もちろんほげほげというMarkdownのリンクの書き方もできる。
##リスト
- foo
- bar
##画像を表示(Pukiwikiプラグインが使える) !ref(テスト/test.jpg)
- 改装箇所
** vendorフォルダにMarkdown parserをインストール
Markdown parserは何を使っても良いが、今回は erusev/parsedown を使用しています。
https://github.com/erusev/parsedown/wiki/
** index.phpでMarkdown parserを読み込む設定をする
index.php に <?php require('vendor/autoload.php'); ?>を加えておく必要がある。
** lib/convert_html.php
22-25行目をコメントアウトして書き換える
$body = new Body(++$contents_id); $body->parse($lines);
return $body->toString();
上記のようになっているところを、下記のように書き換える。
foreach ( $lines as &$line ) { $matches = array(); if ( preg_match('/^\!([a-zA-Z0-9_]+)(\*1*)?\]?/', $line, $matches) ) { $plugin = $matches[1]; if ( exist_plugin_convert($plugin) ) { $name = 'plugin_' . $matches[1] . '_convert'; $params = array(); if ( isset($matches[3]) ) { $params = explode(',', $matches[3]); } $line = call_user_func_array($name, $params); } else { $line = "plugin ${plugin} failed."; } } else { $line = make_link($line); //この行をコメントアウトしてmake_linkをスキップするとraw HTMLを書けるようになる一方でPukiwiki方式のリンクなどの書式が使えなくなる // ファイル読み込んだ場合に改行コードが末尾に付いていることがあるので削除 // 空白は削除しちゃだめなのでrtrim()は使ってはいけない $line = str_replace(array("\r\n","\n","\r"), "", $line); } } unset($line);
$text = implode("\n", $lines);
$parsedown = new \Parsedown(); //Parsedown→ParsedownExtraに変更しても良い $result = $parsedown ->setBreaksEnabled(true) ->text($text); // ->setBreaksEnabled(true)を付けて改行を可能にしている
return $result;
通常のMarkdownではなくMarkdownExtraにしたい場合は $parsedown = new \Parsedown(); の代わりに $parsedown = new \ParsedownExtra(); としてください。その場合はvendor/erusev/parsedownフォルダにParsedownExtra.phpのファイルも入れておく必要があります。
また、今後Pukiwiki 1.5.4が正式リリースされると思いますので、PHP 8.0の対応を見据えて下記のように書き換えておきます。
- canContain(& $obj) を全て canContain($obj) とする。約10箇所。
- {0}は全て[0]にする。3箇所。
- 181,187,915行目の#は!へ変更しなくてよいみたい。
** lib/file.php
- #freezeの2箇所を!freezeにする
- 257,258,279,280,545,610行目の#も!へ変更しなくてよいみたい(pukiwiki1.5.0.-mdでも変えずに動作しているよう)
** lib/make_link.phpの修正
123行目付近の下記の行をコメントアウトして書き換えます。
// $arr = explode("\x08", make_line_rules(htmlsc($string))); $arr = explode("\x08", make_line_rules($string));
htmlscは、htmlspecialcharsで特殊文字をHTMLエンティティに変換するための内部コードですが、HTMLエンティティに変換してしまうと正しくパースされない部分があります。 また、{0}も1箇所[0]に修正しておく。
78〜93行目のうち下記の行をコメントアウトしておく。
if ($converters === NULL) { $converters = array( 'plugin', // Inline plugins 'note', // Footnotes // 'url', // URLs // 'url_interwiki', // URLs (interwiki definition) // 'mailto', // mailto: URL schemes // 'interwikiname', // InterWikiNames // 'autoalias', // AutoAlias // 'autolink', // AutoLinks 'bracketname', // BracketNames // 'wikiname', // WikiNames // 'autoalias_a', // AutoAlias(alphabet) // 'autolink_a', // AutoLinks(alphabet) ); }
上記のautolinkやautoaliasの行をコメントを外すようにすればautolinkが効くようにできますが、Markdown parserと何らかのコンフリクトが生じるかも知れません。
** #authorの修正
下記のファイルで #author となっている部分を全て !author にする必要があります。ほかに、#freezeや#related・#unrelatedなども!freezeや!related・!unrelatedに変更します。
- lib/convert_html.php
- lib/backup.php
- lib/file.php
** 現状の問題点
- MULTILINEプラグインが正しく引数を読み込めない -- おそらくlib/convert_html.phpに書き加えた31行目付近の if ( preg_match('/^\\!([a-zA-Z0-9_]+)(\\(([^\\)\\n]*)?\\))?/', $line, $matches) ) という部分の正規表現に問題があるが、本文を1行づつ分解して順番に「プラグインを適用するのか」「markdown parserに渡すのか」を判定しているため、複数行プラグインをどのように修正すれば良いのか未解決。 -- html.inc.phpのようなMULTILINEが必須のプラグインが動作しないが、markdownはある程度はRAW HTMLが書けるので簡単なHTMLならプラグイン無しで対応できそう。
[[リンク]]という形式の内部リンクは正しく解釈されるが、[[リンクテキスト>リンクURL]]あるいは[[リンクテキスト:リンクURL]]というPukiwiki式の外部リンクは正しく反映されない。-- [リンクテキスト] (リンクURL) というMarkdown式の書き方にする必要がありましたが、lib/convert_html.phpの45行目付近に $line = preg_replace('/(.?)a-zA-Z0-9;/?:@&=+$,%#]+)( )?(".")?)/', "$1", $line); を追記することで(おそらく)解決。- 個々のプラグインまでは動作検証できていません。
- 改行を反映するかどうかはlib/convert_html.phpの55行目付近で設定変更できる。 -- $result = $parsedown->text($text); とすれば行末に半角スペース2つで改行されるオリジナルのMarkdown文法となる。 -- $result = $parsedown ->setBreaksEnabled(true) ->text($text); とすれば改行は自動で反映される。 -- その他のMarkdown parserに関する設定についてはhttps://github.com/erusev/parsedown/wiki/ のREADMEおよびtutorialに解説されている。
#ogp(https://github.com/erusev/parsedown/wiki/)
*その後の追加
その後に、さらにMarkdown式リンクをPukiwiki式リンクに変換できるよう改善を加えました(2021/12/30)。45行目に下記の一文を追記しています。
$line = preg_replace('/[(.?)]((https?://[-_.!~*'()a-zA-Z0-9;/?:@&=+$,%#]+)( )?(".")?)/', "$1", $line);
さらに、Pukwiwiki記法とMarkdown記法をチェックボックスで切り替えられるようにしました。
#ogpi(https://oncologynote.jp/?ae42d4ca0c)
**関連記事
#ogpi(https://oncologynote.jp/?1db14be1b4)
#enull{{ 今後の構想 ** lib/func.php $is_notemd() = true / false ; #notemd という空の出力をするプラグインを作る。 #notemdが本文中に記載があるページのみis_notemd = trueとなるようにする(書き方はfreezeかrelated/norelatedを参考にする)。 trueであればMarkdown記法を適用し、falseであればPukiwiki記法を適用する。 これはconvert_html.phpとmake_link.phpに作用して、if($is_notemd($page))で記法を分岐する。
md記法でも!notemdではなく#notemdをうまく処理できる仕組みにしておく必要あり。#notemdや#authorの行はparserに周る前に非表示化する。
**MarkdownとPukiwikiの両対応 可能であればedit画面にもラジオボタンを作って、クリックでtrueとfalseを切り替えられるようにする。→lib/file.phpのfunction page_writeで、例えばmdを選択していて$postdataに#notemdが無い場合は#notemdを追加する。mdではなくpkwkを選択していて#notemdがあれば、#notemdを削除する。 新規ページのみデフォルトを選択できるようにする(既存ページは#notemdの記載があるかどうかで決める) 複数行プラグインは現状ではpukiwiki方式でしか動作しない。 複数行のプラグインはfunction make_str_rulesによって管理されているので、$postdataに#notemdを追加するのは114行目の$postdata = make_str_rules($postdata);より前がよいのか後が良いのかよく考える必要あり。 #authorは内部処理のみに使われてページのedit時に表示されないように、#notemdもedit時に表示されない仕組みがあれば良い。(#authorが表示されないために、編集画面ではplugin/edit.inc.phpのfunction plugin_edit_writeなど3箇所でremove_author_infoが作動している。また書き込んだファイルの保存時にも同じようにlib/file.phpのfunction page_write 内でremove_notemd_infoやadd_author_infoが働いている。肝心のこのremove_author_infoなどの関数の動作内容もlib/file.php内に定義されている。似たようなものが作れるか?)
function remove_notemd_info($wikitext) { return preg_replace('/^\s*#notemd([^\n]*(\n|$)/m', '', $wikitext); //正規表現内要確認 }
またfunction remove_author_infoやfunction remove_author_headerなどが!authorを除去するようになっているが、これは!authorは今後は使わず#authorを取り除けるようにする必要あり。(→mdのみconvert_htmlでこれらのタグはparserに渡る前に削除する)。 **pukiwiki.ini.php markdown parseの際に無視するプラグインリストというarray()を作る。notemd、author、freezeのように本文に表示しないプラグインはここに格納しておきmarkdown parserに渡す前に取り除く。しかしこれはpukiwiki.ini.phpではなくプラグインの中にglobal変数を設定できるならそのほうが設置が簡単になる。 また、新規ページのデフォルトはpukiwiki形式なのかmarkdown形式なのかを設定する項目を作る。
}} #pcomment
更新日:2021-12-29 閲覧数:2887 views.