-
-
Save lontivero/593fc51f1208555112e0 to your computer and use it in GitHub Desktop.
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Linq; | |
using System.Text.RegularExpressions; | |
using System.Xml; | |
using System.Xml.Linq; | |
namespace GithubWikiDoc | |
{ | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
var xml = File.ReadAllText(args[0]); | |
var doc = XDocument.Parse(xml); | |
var md = doc.Root.ToMarkDown(); | |
Console.WriteLine(md); | |
} | |
} | |
static class XmlToMarkdown | |
{ | |
internal static string ToMarkDown(this XNode e) | |
{ | |
var templates = new Dictionary<string, string> | |
{ | |
{"doc", "## {0} ##\n\n{1}\n\n"}, | |
{"type", "# {0}\n\n{1}\n\n---\n"}, | |
{"field", "##### {0}\n\n{1}\n\n---\n"}, | |
{"property", "##### {0}\n\n{1}\n\n---\n"}, | |
{"method", "##### {0}\n\n{1}\n\n---\n"}, | |
{"event", "##### {0}\n\n{1}\n\n---\n"}, | |
{"summary", "{0}\n\n"}, | |
{"remarks", "\n\n>{0}\n\n"}, | |
{"example", "_C# code_\n\n```c#\n{0}\n```\n\n"}, | |
{"seePage", "[[{1}|{0}]]"}, | |
{"seeAnchor", "[{1}]({0})"}, | |
{"param", "|Name | Description |\n|-----|------|\n|{0}: |{1}|\n" }, | |
{"exception", "[[{0}|{0}]]: {1}\n\n" }, | |
{"returns", "Returns: {0}\n\n"}, | |
{"none", ""} | |
}; | |
var d = new Func<string, XElement, string[]>((att, node) => new[] | |
{ | |
node.Attribute(att).Value, | |
node.Nodes().ToMarkDown() | |
}); | |
var methods = new Dictionary<string, Func<XElement, IEnumerable<string>>> | |
{ | |
{"doc", x=> new[]{ | |
x.Element("assembly").Element("name").Value, | |
x.Element("members").Elements("member").ToMarkDown() | |
}}, | |
{"type", x=>d("name", x)}, | |
{"field", x=> d("name", x)}, | |
{"property", x=> d("name", x)}, | |
{"method",x=>d("name", x)}, | |
{"event", x=>d("name", x)}, | |
{"summary", x=> new[]{ x.Nodes().ToMarkDown() }}, | |
{"remarks", x => new[]{x.Nodes().ToMarkDown()}}, | |
{"example", x => new[]{x.Value.ToCodeBlock()}}, | |
{"seePage", x=> d("cref", x) }, | |
{"seeAnchor", x=> { var xx = d("cref", x); xx[0] = xx[0].ToLower(); return xx; }}, | |
{"param", x => d("name", x) }, | |
{"exception", x => d("cref", x) }, | |
{"returns", x => new[]{x.Nodes().ToMarkDown()}}, | |
{"none", x => new string[0]} | |
}; | |
string name; | |
if(e.NodeType== XmlNodeType.Element) | |
{ | |
var el = (XElement) e; | |
name = el.Name.LocalName; | |
if (name == "member") | |
{ | |
switch (el.Attribute("name").Value[0]) | |
{ | |
case 'F': name = "field"; break; | |
case 'P': name = "property"; break; | |
case 'T': name = "type"; break; | |
case 'E': name = "event"; break; | |
case 'M': name = "method"; break; | |
default: name = "none"; break; | |
} | |
} | |
if(name == "see") | |
{ | |
var anchor = el.Attribute("cref").Value.StartsWith("!:#"); | |
name = anchor ? "seeAnchor" : "seePage"; | |
} | |
var vals = methods[name](el).ToArray(); | |
string str=""; | |
switch (vals.Length) | |
{ | |
case 1: str= string.Format(templates[name], vals[0]);break; | |
case 2: str= string.Format(templates[name], vals[0],vals[1]);break; | |
case 3: str= string.Format(templates[name], vals[0],vals[1],vals[2]);break; | |
case 4: str= string.Format(templates[name], vals[0], vals[1], vals[2], vals[3]);break; | |
} | |
return str; | |
} | |
if(e.NodeType==XmlNodeType.Text) | |
return Regex.Replace( ((XText)e).Value.Replace('\n', ' '), @"\s+", " "); | |
return ""; | |
} | |
internal static string ToMarkDown(this IEnumerable<XNode> es) | |
{ | |
return es.Aggregate("", (current, x) => current + x.ToMarkDown()); | |
} | |
static string ToCodeBlock(this string s) | |
{ | |
var lines = s.Split(new char[] {'\n'}, StringSplitOptions.RemoveEmptyEntries); | |
var blank = lines[0].TakeWhile(x => x == ' ').Count() - 4; | |
return string.Join("\n",lines.Select(x => new string(x.SkipWhile((y, i) => i < blank).ToArray()))); | |
} | |
} | |
} |
I've created an updated version of this code that includes the rest of the C# documentation tags and generates most of them in a 'decent" format. I could update this code (if there is a repository for it) or create a new one on GitHub.
Is anyone interested and does anyone have a good suggestion?
@bradfriedlander I'm going to be writing a tool like this for my project, so I'm interested in the updated version if it's available. 🙂
EDIT: Fixed the project link. Whoops.
@bradfriedlander I would be interested in your updated version.
Take a look at DocXml project. There is a sample markdown documentation generator in the repo.
Sample became a .net core global tool. See here mddox
Im getting KeyNotFoundException: The given key was not present in the dictionary error. What should be done to resolve this.
This has some great potential! Any chance you could add support for additional valid tags? For example, paramref and typeparam appear to be unsupported and result in exceptions. Thanks!