1 // ================================================================================================
3 // MediaWikiの見出しを解析するパーサークラスソース</summary>
5 // <copyright file="MediaWikiHeadingParser.cs" company="honeplusのメモ帳">
6 // Copyright (C) 2012 Honeplus. All rights reserved.</copyright>
9 // ================================================================================================
11 namespace Honememo.Wptscs.Parsers
14 using System.Collections.Generic;
16 using Honememo.Parsers;
17 using Honememo.Utilities;
20 /// MediaWikiの見出しを解析するパーサークラスです。
22 public class MediaWikiHeadingParser : AbstractParser
27 /// このパーサーが参照する<see cref="MediaWikiParser"/>。
29 private MediaWikiParser parser;
36 /// 指定された<see cref="MediaWikiParser"/>を元に見出しを解析するためのパーサーを作成する。
38 /// <param name="parser">このパーサーが参照する<see cref="MediaWikiParser"/>。</param>
39 public MediaWikiHeadingParser(MediaWikiParser parser)
49 /// 渡されたテキストをMediaWikiの見出し(==関連項目==みたいなの)として解析する。
51 /// <param name="s">行頭からの文字列。</param>
52 /// <param name="result">解析した見出し。</param>
53 /// <returns>解析に成功した場合<c>true</c>。</returns>
55 /// 見出しは行単位で有効になるため、行頭からの文字列を渡す必要がある。
56 /// (ただし、--<==見出し== みたいな事もできるので、その場合は=の開始部分から。)
58 public override bool TryParse(string s, out IElement result)
62 if (string.IsNullOrEmpty(s))
68 // ※ 構文はWikipediaのプレビューで色々試して確認、足りなかったり間違ってたりするかも・・・
69 // TODO: Wikipediaでは <!--test-->=<!--test-->=関連項目<!--test-->==<!--test--> みたいなのでも認識するが、2012年1月現在未対応
70 // (昔は対応していたが、その過程でコメントが失われれるつくりになっており、
71 // Parser周りを整理した際に情報を取りこぼさないことを最優先としたため取り止め。)
73 for (int i = 0; i < s.Length; i++)
75 if (s[i] == MediaWikiHeading.DelimiterStart)
85 // = で始まる行ではない場合、処理対象外
91 // 始まりの = の次の文字から、行の終わりまでを解析
92 // (=={{lang\n|ja|見出し}}== みたいに何かの中にある改行はOK。Wikipediaでも認識された)
94 this.parser.TryParseToDelimiter(StringUtils.Substring(s, startCount), out element, "\r", "\n");
97 // ※ この処理だと中身の無い行(====とか)は弾かれてしまうが、どうせ処理できないので許容する
98 string substr = element.ToString().TrimEnd();
100 for (int i = substr.Length - 1; i >= 0; i--)
102 if (substr[i] == MediaWikiHeading.DelimiterEnd)
112 // = で終わる行ではない場合、処理対象外
118 // 始まりと終わり、=の少ないほうにあわせる(==test===とか用の処理)
119 int level = startCount;
120 if (startCount > endCount)
125 // 確定した見出しの階層から、見出し内部の文字列を抽出。内部要素を再帰的に探索する
126 // ※ 二重処理になってしまうが、後ろの = を取り除くと微妙にややこしいことになりそうだったので
127 // 見出しは処理件数も少なく、深い再帰もないはずなので、影響ない・・・はず
128 IElement innerElement;
129 if (!this.parser.TryParse(substr.Substring(0, substr.Length - level), out innerElement))
134 // 解析に成功した場合、結果を出力値に設定
135 result = this.MakeElement(innerElement, level, s.Substring(0, startCount + element.ToString().Length));
144 /// 見出しタグを解析した結果から、MediaWiki見出し要素を生成する。
146 /// <param name="innerElement">見出しタグ上の見出し部分の要素。</param>
147 /// <param name="level">見出しの階層。</param>
148 /// <param name="parsedString">解析した見出しタグの文字列。</param>
149 /// <returns>生成した見出し要素。</returns>
150 private MediaWikiHeading MakeElement(IElement innerElement, int level, string parsedString)
152 MediaWikiHeading heading = new MediaWikiHeading();
155 heading.ParsedString = parsedString;
158 heading.Level = level;
160 // 内部要素については、結果がリストの場合マージ、それ以外はそのままElementに代入
161 if (innerElement.GetType() == typeof(ListElement))
163 heading.AddRange((ListElement)innerElement);
167 heading.Add(innerElement);