Markdown で好みのヘルパーを使えるようにする
執筆日時:
連日プログラミングの話になる。
WebMatrix + Markdown …… リファクタリング。 で、
Daruboard.Transform(content); は、あらかじめ登録したヘルパーを利用してテキストを整形する仕組みを呼び出している。これについては、また今度。
と書いたと思うんだけど、今日はその話。以下に /App_Code/Daruboard.cshtml
の内容を示す。
@using System.Text.RegularExpressions @using System.Reflection@functions {
private struct FormatHelper { public string Signature; public Type Type; public string Method; public object[] DefaultParams; }
private static List<FormatHelper> FormatHelpers = new List<FormatHelper>();
public static void RegisterHelper( string signature, Type type, string method_name, object[] default_params) { if (FormatHelpers.Any(f => f.Signature == signature)) { throw new Exception(string.Format( "Daruboard.RegisterHelper(): {0} has already exist.", signature)); }
MethodInfo method = type.GetMethod(method_name); if (method == null) { throw new Exception(string.Format( "Daruboard.RegisterHelper(): {0} does not have {1}().", type, method_name)); }
FormatHelpers.Add(new FormatHelper() { Signature = signature, Type = type, Method = method_name, DefaultParams = default_params }); }
public static string Transform(string text) { var r = new Regex(@" (<p>)?[[ (?<signature>[^[]|])(|(?<params>[^[]]))* ]](</p>)?", RegexOptions.Singleline | RegexOptions.IgnorePatternWhitespace | RegexOptions.Compiled );
text = r.Replace(text, m => { var s = m.Groups["signature"].Value; var p = m.Groups["params"].Value.Split('|'); var f = FormatHelpers.Find(_ => _.Signature == s);
if (f.Signature == null) { return string.Format("<a href='/{0}'>{0}</a>", s); } else { try { MethodInfo method = f.Type.GetMethod(f.Method); object[] parameter = f.DefaultParams; parameter[0] = p[0]; return method.Invoke(null, parameter).ToString(); } catch (Exception e) { return string.Format("[{0}: {1}]", e.GetType(), e.Message); } } });
return text; } }
sigunature|param1|param2… という書式を見つけたら、指定した Signature をもつヘルパーを登録済みリストから探し出し、登録時に指定した Method をリフレクションで呼び出す。ヘルパーの登録は、_AppStart.cshtml
あたりで、
Daruboard.RegisterHelper("twitter", typeof(BlackbirdPie), "GetHtml", new object[] { null, false, true, Locale.ja } );
などとと書いておく *1 。書式に Signature しかない場合は、それを URL とみなしリンクにする *2 処理を入れてある。
まぁ、これで、
[[twitter|ツイートへのURL]]
が、
@BlackbirdPie.GetHtml(ツイートへのURL)
と解釈されてレンダリングされるというわけ。
さて、ここまでやっちゃうとだんだん読み込み速度が気になってきた。というわけで、今度はキャッシュの使い方を勉強しようかなぁと思う。これまで作った Webアプリは、daruyanagi.net で実際に利用されている(11/11/13現在)。