-
-
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.