[Mono-docs-list] Wiki Markup for ECMA documents.
Atsushi Eno
atsushi at ximian.com
Wed Dec 7 12:10:08 EST 2005
Hola,
> But with this code, we can start moving forward. We still need the
> inverse process Wiki to ECMA XML before this can land on SVN.
Yeah. So, here it is.
http://monkey.workarea.jp/trans/mono/index.php/TestMonodocToMediaWiki3
However, whitespace handling in the ECMA->Wiki xsl is a blocker for
practical use (it unexpectedly merges sequential <para>s), so am
really going to rewrite the code in C#.
Atsushi Eno
-------------- next part --------------
using System;
using System.Globalization;
using System.IO;
using System.Text;
using System.Xml;
namespace Monodoc
{
public class WikiStyleDocParser
{
public static void Main (string [] args)
{
if (args.Length < 1) {
Console.Error.WriteLine ("usage: wiki2ecma sourcefile [--full]");
return;
}
bool full = args.Length > 1 && args [1] == "--full";
bool isXml = false;
using (Stream s = File.OpenRead (args [0])) {
isXml = (s.ReadByte () == '<');
}
string text;
if (isXml) {
XmlDocument doc = new XmlDocument ();
doc.Load (args [0]);
XmlNode node = doc.SelectSingleNode ("//text");
text = node.InnerText;
} else {
StreamReader sr = new StreamReader (args [0],
Encoding.UTF8);
text = sr.ReadToEnd ();
}
// Pass the input Wiki-like content as the .ctor()
// parameter.
WikiStyleDocParser p = new WikiStyleDocParser (text);
XmlNode result;
if (full)
result = p.ParseEntireDoc ();
else
result = p.ParseContent ();
XmlTextWriter xw = new XmlTextWriter (Console.Out);
xw.Formatting = Formatting.Indented;
result.WriteTo (xw);
xw.Close ();
}
string [] lines;
int lineno = 1;
XmlDocument doc;
string current_member;
public WikiStyleDocParser (string source)
{
lines = source.Split ('\n');
doc = new XmlDocument ();
doc.AppendChild (doc.CreateElement ("root"));
}
public XmlNode ParseContent ()
{
ProcessContent (doc.DocumentElement);
return doc.DocumentElement;
}
public XmlNode ParseEntireDoc ()
{
XmlElement el = doc.DocumentElement;
while (lineno < lines.Length) {
string line = lines [lineno].Trim ();
if (line.Length == 0) {
lineno++;
continue;
}
XmlNode node = null;
switch (line) {
case "=== Summary ===":
node = ProcessTaggedContent (EditTarget.Summary);
el.AppendChild (node);
break;
case "=== Remarks ===":
node = ProcessTaggedContent (EditTarget.Remarks);
el.AppendChild (node);
break;
case "=== Parameters ===":
ProcessList (el, "param", "name");
break;
case "=== Exceptions ===":
ProcessList (el, "exception", "type");
break;
default:
if (StrUtil.StartsWith (line, "==")) {
current_member = line.Substring (
3, line.Length - 6).Trim ();
el = doc.CreateElement ("Member");
el.SetAttribute ("MemberName", current_member);
doc.DocumentElement.AppendChild (el);
lineno++;
break;
}
throw MarkupError ("Unexpected line format: " + line);
}
}
return doc.DocumentElement;
}
void ProcessList (XmlNode parent, string elemName, string defAttr)
{
lineno++;
for (; lineno < lines.Length; lineno++) {
string line = lines [lineno];
if (line.Length == 0)
continue;
if (line [0] != ';')
break;
int idx = line.IndexOf (':');
XmlElement el = doc.CreateElement (elemName);
parent.AppendChild (el);
el.SetAttribute (defAttr, line.Substring (1, idx - 1));
ProcessSimpleLine (el, line, idx + 1);
}
}
XmlNode ProcessTaggedContent (string target)
{
XmlElement el = doc.CreateElement (target);
lineno++;
ProcessContent (el);
return el;
}
void ProcessContent (XmlNode container)
{
while (lineno < lines.Length) {
string line = lines [lineno];
if (line.Length == 0) {
lineno++;
continue;
}
switch (line [0]) {
case '=':
return;
case '{':
ProcessTable (container);
break;
case ':':
XmlElement el = doc.CreateElement ("block");
el.SetAttribute ("subset", "none");
el.SetAttribute ("type", "note");
container.AppendChild (el);
ProcessSimple (el, true);
break;
default:
el = doc.CreateElement ("para");
container.AppendChild (el);
ProcessSimple (el, false);
break;
}
}
}
void ProcessTable (XmlNode container)
{
lineno++;
XmlElement list = doc.CreateElement ("list");
container.AppendChild (list);
list.SetAttribute ("type", "table");
XmlElement tline = null;
for (; lineno < lines.Length; lineno++) {
string line = lines [lineno];
if (line == "|}") {
lineno++;
return;
}
if (line.Length == 0)
continue;
if (line == "|-") {
tline = doc.CreateElement ("item");
continue;
}
switch (line [0]) {
case '!':
tline = doc.CreateElement ("listheader");
int endTerm = line.IndexOf ('!', 1);
int beginDesc = endTerm < 0 ? -1 : line.IndexOf ('!', endTerm + 1);
if (beginDesc < 0)
throw MarkupError ("list table header has incorrect markup : " + line);
XmlElement term = doc.CreateElement ("term");
term.InnerText = line.Substring (1, endTerm - 1);
tline.AppendChild (term);
XmlElement desc = doc.CreateElement ("description");
desc.InnerText = line.Substring (beginDesc + 1);
tline.AppendChild (desc);
list.AppendChild (tline);
break;
case '|':
if (tline == null)
throw MarkupError ("Specify '|-' to begin new table line");
endTerm = line.IndexOf ('|', 1);
beginDesc = endTerm < 0 ? -1 : line.IndexOf ('|', endTerm + 1);
term = doc.CreateElement ("term");
term.InnerText = line.Substring (1, endTerm - 1);
tline.AppendChild (term);
desc = doc.CreateElement ("description");
ProcessSimpleLine (desc, line, beginDesc + 1);
tline.AppendChild (desc);
list.AppendChild (tline);
break;
}
tline = null;
}
// there is already "return" statement above.
throw MarkupError ("End of list table is missing");
}
void ProcessSimple (XmlNode container, bool allowColon)
{
for (;lineno < lines.Length; lineno++) {
string line = lines [lineno];
if (line.Length == 0) {
if (lineno + 1 < lines.Length &&
lines [lineno + 1] == String.Empty) {
lineno++;
return;
}
continue;
}
switch (line [0]) {
case '=':
case '{':
return;
case ':':
if (!allowColon)
return;
ProcessSimpleLine (container, line, 1);
break;
default:
ProcessSimpleLine (container, line, 0);
break;
}
}
}
void ProcessSimpleLine (XmlNode container, string line, int from)
{
int idx;
while ((idx = line.IndexOf ('[', from)) >= 0) {
from = ProcessLink (
container, line, idx, from);
}
if (from != line.Length)
container.AppendChild (doc.CreateTextNode (line.Substring (from) + '\n'));
}
int ProcessLink (XmlNode container, string line, int idx, int from)
{
int end = line.IndexOf (']', idx);
if (end < idx)
throw MarkupError (String.Format ("There is no matching ']' to close link at position {1} : {0}", line, idx));
if (idx > from) {
XmlText text = doc.CreateTextNode (
line.Substring (from, idx - from));
container.AppendChild (text);
}
int sep = line.IndexOf ('|', idx, end - idx);
if (sep > 0) {
if (line [idx + 1] != '[' ||
sep < 0 || sep > end ||
end + 1 >= line.Length ||
line [end + 1] != ']')
throw MarkupError (String.Format ("Invalid reference markup at position {1} : {0}", line, idx));
// see cref
XmlElement el = doc.CreateElement ("see");
el.SetAttribute ("cref", line.Substring (
idx + 2, sep - idx - 2).Trim ());
container.AppendChild (el);
} else {
// paramref
if (line [idx + 1] != '[' ||
end + 1 >= line.Length ||
line [end + 1] != ']')
throw MarkupError (String.Format ("Invalid reference markup at position {1} : {0}", line, idx));
XmlElement el = doc.CreateElement ("paramref");
el.SetAttribute ("name", line.Substring (
idx + 2, end - idx - 2));
container.AppendChild (el);
}
end += 2;
return end;
}
Exception MarkupError (string message)
{
throw new Exception (String.Format (
"At line {1} : {0}", message, lineno));
}
}
class EditTarget
{
public const string Summary = "summary";
public const string Remarks = "remarks";
}
class StrUtil
{
static CompareInfo ci = CultureInfo.CurrentCulture.CompareInfo;
public static bool StartsWith (string s, string target)
{
return ci.IsPrefix (s, target, CompareOptions.Ordinal);
}
}
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: monodoc2mediawiki.xsl
Type: text/xml
Size: 5606 bytes
Desc: not available
Url : http://lists.ximian.com/pipermail/mono-docs-list/attachments/20051208/d7a19f20/monodoc2mediawiki.xsl
More information about the Mono-docs-list
mailing list