screwturn 用のシンプルな定義リストプラグイン

そのうちビルドインで実装されるらしいけど、タグで書いておくのも難だからプラグインを書いてみた。

書いたというほどではなくて、実装はテーブル記法そのままみたいなもんです。任意の属性が書けちゃうとか、エスケープする記法がないとかもそのままなので、アレなところも一緒です。

{:
: 京都府 :: 京都市
: 滋賀県
:: 大津市
:}

と書くと、

京都府
京都市
滋賀県
大津市

と表示されるプラグイン。このような整形だけの場合は、Phase1 で変換しておくと、IHost.Format() とかを使用しないでも定義名に各種記法が使えたり、レンダリング時にノーコストで展開されたりするわけですね。

以下、ソースコード

    public class DefList : IFormatterProvider
    {
        private readonly ComponentInformation info;
        private IHost host;

        // {:
        // : key
        // :: value
        // :}
        private static readonly Regex FormattingRule
            = new Regex(@"\{\:(?<list_attributes> [^\n]*)?\n(?<list_items>.+?)\n\:\}", RegexOptions.Singleline);

        public DefList()
        {
            this.info = new ComponentInformation("Definition List Formatter Plugin",
                                                 "LadyBUG", "http://d.hatena.ne.jp/ladybug/20070712");
            this.host = null;
        }

        #region IProvider メンバ

        public ComponentInformation Information
        {
            get { return this.info; }
        }

        public void Init(IHost host, string config)
        {
            this.host = host;
        }

        public void Shutdown()
        {

        }

        #endregion

        #region IFormatterProvider メンバ

        public bool PerformPhase1
        {
            get { return true; }
        }

        public bool PerformPhase2
        {
            get { return false; }
        }

        public bool PerformPhase3
        {
            get { return false; }
        }

        public string Format(string raw, ContextInformation context, FormattingPhase phase)
        {
            return DefList.FormattingRule.Replace(raw, BuildDefList);
        }

        private string BuildDefList(Match m)
        {
            StringBuilder sb = new StringBuilder();

            // <dl (list_attributes)>
            sb.Append("<dl");
            if (m.Groups["list_attributes"].Success)
                sb.Append(m.Groups["list_attributes"].Value);
            sb.Append(">\n");

            string[] items = m.Groups["list_items"].Value.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
            for (int i = 0; i < items.Length; i++)
            {
                string line = items[i].Trim();

                if (line.StartsWith(": "))
                {
                    if (line.IndexOf(" :: ") != -1)
                    {
                        sb.Append("<dt>");
                        sb.Append(line.Substring(2).Replace(" :: ", "</dt><dd>"));
                        sb.Append("</dd>\n");
                    }
                    else
                    {
                        sb.Append("<dt>");
                        sb.Append(line.Substring(2));
                        sb.Append("</dt>\n");
                    }
                }
                else if (line.StartsWith(":: "))
                {
                    sb.Append("<dd>");
                    sb.Append(line.Substring(3));
                    sb.Append("</dd>\n");
                }
            }

            // </dl>
            sb.Append("</dl>");
            return sb.ToString();
        }

        #endregion
    }