void BuildTable <T>(MarkdownBuilder mb, string label, T[] array, IEnumerable <XmlDocumentComment> docs, Func <T, string> type, Func <T, string> name, Func <T, string> finalName) { if (array.Any()) { mb.Header(2, label); mb.AppendLine(); string[] head = (this.type.IsEnum) ? new[] { "Value", "Name", "Summary" } : new[] { "Type", "Name", "Summary" }; IEnumerable <T> seq = array; if (!this.type.IsEnum) { seq = array.OrderBy(x => name(x)); } var data = seq.Select(item2 => { var summary = docs.FirstOrDefault(x => x.MemberName == name(item2) || x.MemberName.StartsWith(name(item2) + "`"))?.Summary ?? ""; return(new[] { MarkdownBuilder.MarkdownCodeQuote(type(item2)), finalName(item2), summary }); }); mb.Table(head, data); mb.AppendLine(); } }
public override string ToString() { var mb = new MarkdownBuilder(); mb.Header(1, Beautifier.BeautifyType(type, false).Replace("<", "<").Replace(">", ">")); mb.AppendLine(); mb.CodeQuote($"Namespace: {type.Namespace}"); mb.AppendLine(); mb.AppendLine(); var desc = commentLookup[type.FullName].FirstOrDefault(x => x.MemberType == MemberType.Type)?.Summary ?? ""; if (desc != "") { mb.AppendLine(desc); mb.AppendLine(); } { var sb = new StringBuilder(); var stat = (type.IsAbstract && type.IsSealed) ? "static " : ""; var abst = (type.IsAbstract && !type.IsInterface && !type.IsSealed) ? "abstract " : ""; var classOrStructOrEnumOrInterface = type.IsInterface ? "interface" : type.IsEnum ? "enum" : type.IsValueType ? "struct" : "class"; sb.Append($"public {stat}{abst}{classOrStructOrEnumOrInterface} {Beautifier.BeautifyType(type, false)}"); var impl = string.Join(", ", new[] { type.BaseType }.Concat(type.GetInterfaces()).Where(x => x != null && x != typeof(object) && x != typeof(ValueType)).Select(x => Beautifier.BeautifyType(x))); if (impl != "") { sb.Append($"{Environment.NewLine} : " + impl); } mb.Code("csharp", sb.ToString()); } mb.AppendLine(); if (type.IsEnum) { var underlyingEnumType = Enum.GetUnderlyingType(type); var enums = Enum.GetNames(type) .Select(x => new { Name = x, Value = (Convert.ChangeType(Enum.Parse(type, x), underlyingEnumType)) }) .OrderBy(x => x.Value) .ToArray(); BuildTable(mb, "Enum", enums, commentLookup[type.FullName], x => x.Value.ToString(), x => x.Name, x => x.Name); } else { BuildTable(mb, "Fields", GetFields(), commentLookup[type.FullName], x => Beautifier.BeautifyType(x.FieldType), x => x.Name, x => x.Name); BuildTable(mb, "Properties", GetProperties(), commentLookup[type.FullName], x => Beautifier.BeautifyType(x.PropertyType), x => x.Name, x => x.Name); BuildTable(mb, "Events", GetEvents(), commentLookup[type.FullName], x => Beautifier.BeautifyType(x.EventHandlerType), x => x.Name, x => x.Name); BuildTable(mb, "Methods", GetMethods(), commentLookup[type.FullName], x => Beautifier.BeautifyType(x.ReturnType), x => x.Name, x => Beautifier.ToMarkdownMethodInfo(x)); BuildTable(mb, "Static Fields", GetStaticFields(), commentLookup[type.FullName], x => Beautifier.BeautifyType(x.FieldType), x => x.Name, x => x.Name); BuildTable(mb, "Static Properties", GetStaticProperties(), commentLookup[type.FullName], x => Beautifier.BeautifyType(x.PropertyType), x => x.Name, x => x.Name); BuildTable(mb, "Static Methods", GetStaticMethods(), commentLookup[type.FullName], x => Beautifier.BeautifyType(x.ReturnType), x => x.Name, x => Beautifier.ToMarkdownMethodInfo(x)); BuildTable(mb, "Static Events", GetStaticEvents(), commentLookup[type.FullName], x => Beautifier.BeautifyType(x.EventHandlerType), x => x.Name, x => x.Name); } mb.AppendLine("---"); mb.AppendLine(); mb.Link(MarkdownBuilder.MarkdownCodeQuote("< Back"), "../"); mb.AppendLine(); return(mb.ToString()); }
static void Main(string[] args) { var app = new CommandLineApplication(); app.Name = "xmldoc2md"; app.VersionOption("-v|--version", () => { return(string.Format( "Version {0}", Assembly.GetEntryAssembly() .GetCustomAttribute <AssemblyInformationalVersionAttribute>() .InformationalVersion .ToString())); }); app.HelpOption("-?|-h|--help"); CommandArgument srcArg = app.Argument("src", "DLL source path"); CommandArgument outArg = app.Argument("out", "Output directory"); CommandOption namespaceMatchOption = app.Option( "--namespace-match <regex>", "Regex pattern to select namespaces", CommandOptionType.SingleValue); CommandOption indexPageNameOption = app.Option( "--index-page-name <regex>", "Name of the index page (default: \"index\")", CommandOptionType.SingleValue); app.OnExecute(() => { string src = srcArg.Value; string @out = outArg.Value; string namespaceMatch = namespaceMatchOption.Value(); string indexPageName = indexPageNameOption.HasValue() ? indexPageNameOption.Value() : "index"; var xmlDocumentation = new XmlDocumentation(src, namespaceMatch); if (!Directory.Exists(@out)) { Directory.CreateDirectory(@out); } var indexBuilder = new MarkdownBuilder(); indexBuilder.Header(1, xmlDocumentation.AssemblyName); foreach (var g in xmlDocumentation.Types.GroupBy(x => x.Namespace).OrderBy(x => x.Key)) { string subDir = Path.Combine(@out, g.Key); if (!Directory.Exists(subDir)) { Directory.CreateDirectory(subDir); } indexBuilder.AppendLine(); indexBuilder.HeaderWithCode(2, g.Key); indexBuilder.AppendLine(); foreach (var item in g.OrderBy(x => x.Name)) { string typeName = item.BeautifyName.Replace("<", "{").Replace(">", "}").Replace(",", "").Replace(" ", "-"); var sb = new StringBuilder(); indexBuilder.ListLink(MarkdownBuilder.MarkdownCodeQuote(item.BeautifyName), g.Key + "/" + typeName); sb.Append(item.ToString()); File.WriteAllText(Path.Combine(@out, g.Key, $"{typeName}.md"), sb.ToString()); } } File.WriteAllText(Path.Combine(@out, $"{indexPageName}.md"), indexBuilder.ToString()); return(0); }); try { app.Execute(args); } catch (CommandParsingException ex) { Console.WriteLine(ex.Message); } catch (Exception ex) { Console.WriteLine("Unable to execute application: {0}", ex.Message); } }