2 using System.Globalization;
6 using System.Xml.XPath;
11 public class WikiStyleDocConverter
13 public static void Main (string [] args)
15 if (args.Length < 1) {
16 Console.Error.WriteLine ("usage: wiki2ecma sourcefile [--full]");
20 bool full = args.Length > 1 && args [1] == "--full";
23 using (Stream s = File.OpenRead (args [0])) {
24 isXml = (s.ReadByte () == '<');
29 XmlDocument doc = new XmlDocument ();
31 XmlNode node = doc.SelectSingleNode ("//text");
32 text = node.InnerText;
34 StreamReader sr = new StreamReader (args [0],
36 text = sr.ReadToEnd ();
39 // Pass the input Wiki-like content as the .ctor()
41 WikiStyleDocConverter p = new WikiStyleDocConverter (text);
44 result = p.ParseEntireDoc ();
46 result = p.ParseContent ();
48 XmlTextWriter xw = new XmlTextWriter (Console.Out);
49 xw.Formatting = Formatting.Indented;
57 string current_member;
59 public WikiStyleDocConverter (string source)
61 source = TransformElements (source);
63 lines = source.Split ('\n');
64 doc = new XmlDocument ();
65 doc.AppendChild (doc.CreateElement ("root"));
68 private string TransformElements (string source)
70 XPathDocument doc = new XPathDocument (
71 new StringReader ("<root>" + source + "</root>"));
72 XslTransform tr = new XslTransform ();
73 tr.Load ("wiki2ecmahelper.xsl");
74 XmlReader reader = tr.Transform (doc, null, (XmlResolver) null);
75 reader.Read (); // should consume <root> start tag
77 return reader.ReadInnerXml ();
80 public XmlNode ParseContent ()
82 ProcessContent (doc.DocumentElement);
83 return doc.DocumentElement;
86 public XmlNode ParseEntireDoc ()
88 XmlElement el = doc.DocumentElement;
90 while (lineno < lines.Length) {
91 string line = lines [lineno].Trim ();
92 if (line.Length == 0) {
98 case "=== Summary ===":
99 node = ProcessTaggedContent (EditTarget.Summary);
100 el.AppendChild (node);
102 case "=== Remarks ===":
103 node = ProcessTaggedContent (EditTarget.Remarks);
104 el.AppendChild (node);
106 case "=== Parameters ===":
107 ProcessList (el, "param", "name");
109 case "=== Exceptions ===":
110 ProcessList (el, "exception", "type");
113 if (StrUtil.StartsWith (line, "==")) {
114 current_member = line.Substring (
115 3, line.Length - 6).Trim ();
116 el = doc.CreateElement ("Member");
117 el.SetAttribute ("MemberName", current_member);
118 doc.DocumentElement.AppendChild (el);
122 throw MarkupError ("Unexpected line format: " + line);
125 return doc.DocumentElement;
128 void ProcessList (XmlNode parent, string elemName, string defAttr)
131 for (; lineno < lines.Length; lineno++) {
132 string line = lines [lineno];
133 if (line.Length == 0)
137 int idx = line.IndexOf (':');
138 XmlElement el = doc.CreateElement (elemName);
139 parent.AppendChild (el);
140 el.SetAttribute (defAttr, line.Substring (1, idx - 1));
141 ProcessSimpleLine (el, line, idx + 1);
145 XmlNode ProcessTaggedContent (string target)
147 XmlElement el = doc.CreateElement (target);
153 void ProcessContent (XmlNode container)
155 while (lineno < lines.Length) {
156 string line = lines [lineno];
157 if (line.Length == 0) {
166 ProcessTable (container);
169 XmlElement el = doc.CreateElement ("block");
170 el.SetAttribute ("subset", "none");
171 el.SetAttribute ("type", "note");
172 container.AppendChild (el);
173 ProcessSimple (el, true);
176 el = doc.CreateElement ("para");
177 container.AppendChild (el);
178 ProcessSimple (el, false);
184 void ProcessTable (XmlNode container)
187 XmlElement list = doc.CreateElement ("list");
188 container.AppendChild (list);
189 list.SetAttribute ("type", "table");
190 XmlElement tline = null;
191 for (; lineno < lines.Length; lineno++) {
192 string line = lines [lineno];
198 if (line.Length == 0)
201 tline = doc.CreateElement ("item");
206 tline = doc.CreateElement ("listheader");
207 int endTerm = line.IndexOf ('!', 1);
208 int beginDesc = endTerm < 0 ? -1 : line.IndexOf ('!', endTerm + 1);
210 throw MarkupError ("list table header has incorrect markup : " + line);
211 XmlElement term = doc.CreateElement ("term");
212 term.InnerText = line.Substring (1, endTerm - 1);
213 tline.AppendChild (term);
214 XmlElement desc = doc.CreateElement ("description");
215 desc.InnerText = line.Substring (beginDesc + 1);
216 tline.AppendChild (desc);
217 list.AppendChild (tline);
221 throw MarkupError ("Specify '|-' to begin new table line");
222 endTerm = line.IndexOf ('|', 1);
224 throw MarkupError ("Missing list table separator '|'");
225 beginDesc = endTerm < 0 ? -1 : line.IndexOf ('|', endTerm + 1);
226 term = doc.CreateElement ("term");
227 term.InnerText = line.Substring (1, endTerm - 1);
228 tline.AppendChild (term);
229 desc = doc.CreateElement ("description");
230 ProcessSimpleLine (desc, line, beginDesc + 1);
231 tline.AppendChild (desc);
232 list.AppendChild (tline);
237 // there is already "return" statement above.
238 throw MarkupError ("End of list table is missing");
241 void ProcessSimple (XmlNode container, bool allowColon)
243 for (;lineno < lines.Length; lineno++) {
244 string line = lines [lineno];
245 if (line.Length == 0) {
246 if (lineno + 1 < lines.Length &&
247 lines [lineno + 1] == String.Empty) {
260 ProcessSimpleLine (container, line, 1);
263 ProcessSimpleLine (container, line, 0);
269 void ProcessSimpleLine (XmlNode container, string line, int from)
272 while ((idx = line.IndexOf ('[', from)) >= 0) {
273 if (idx + 1 < line.Length && line [idx + 1] == '[')
275 container, line, idx, from);
277 from = ProcessParamRef (
278 container, line, idx, from);
280 if (from != line.Length)
281 container.AppendChild (doc.CreateTextNode (line.Substring (from) + '\n'));
284 int ProcessSee (XmlNode container, string line, int idx, int from)
286 int end = line.IndexOf ("]]", idx);
287 int sep = end < idx ? - 1: line.IndexOf ('|', idx, end - idx);
289 throw MarkupError (String.Format ("There is no matching '|' and ']' to close link at position {1} : {0}", line, idx));
291 XmlText text = doc.CreateTextNode (
292 line.Substring (from, idx - from));
293 container.AppendChild (text);
296 XmlElement el = doc.CreateElement ("see");
297 el.SetAttribute ("cref", line.Substring (
298 idx + 2, sep - idx - 2).Trim ());
299 container.AppendChild (el);
305 int ProcessParamRef (XmlNode container, string line, int idx, int from)
307 int end = line.IndexOf (']', idx);
309 throw MarkupError (String.Format ("There is no matching ']' to close link at position {1} : {0}", line, idx));
311 XmlText text = doc.CreateTextNode (
312 line.Substring (from, idx - from));
313 container.AppendChild (text);
316 XmlElement el = doc.CreateElement ("paramref");
317 el.SetAttribute ("name", line.Substring (
318 idx + 1, end - idx - 1));
319 container.AppendChild (el);
324 Exception MarkupError (string message)
326 throw new Exception (String.Format (
327 "At line {1} : {0}", message, lineno));
333 public const string Summary = "summary";
334 public const string Remarks = "remarks";
339 static CompareInfo ci = CultureInfo.CurrentCulture.CompareInfo;
341 public static bool StartsWith (string s, string target)
343 return ci.IsPrefix (s, target, CompareOptions.Ordinal);