-
-
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.
I've taken this thing and built a NuGet package that sets it up as a build target. Every build you will automatically get your .md file regenerated.
https://github.com/Pxtl/XmlCommentMarkDownGenerator
Patches and insults welcome.