public override string ToString() { var mb = new MarkdownBuilder(); mb.HeaderWithCode(2, Beautifier.BeautifyType(type, false)); mb.AppendLine(); var desc = commentLookup[type.FullName].FirstOrDefault(x => x.MemberType == MemberType.Type)?.Summary ?? ""; if (desc != "") { mb.AppendLine(desc); } { 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.AppendLine($"public {stat}{abst}{classOrStructOrEnumOrInterface} {Beautifier.BeautifyType(type, true)}"); 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.AppendLine(" : " + 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); } return(mb.ToString()); }
// put dll & xml on same diretory. private static void Main(string[] args) { //output path for documentation var dest = "md"; //namespace regex var namespaceMatch = "*.Controllers"; //class regex var classMatch = ".*Controller"; //dll path which will be documented var dllPath = @"C:\example\example.dll"; var assembly = Assembly.LoadFrom(dllPath); var commentsLookup = MarkdownGenerator.GetCommentsLookup(assembly); var referencedModelContainer = new ReferencedModelContainer(commentsLookup); var types = MarkdownGenerator.Load(assembly, namespaceMatch, classMatch, referencedModelContainer, commentsLookup); // Home Markdown Builder var homeBuilder = new MarkdownBuilder(); homeBuilder.Header(1, "References"); homeBuilder.AppendLine(); foreach (var g in types.GroupBy(x => x.Namespace).OrderBy(x => x.Key)) { if (!Directory.Exists(dest)) { Directory.CreateDirectory(dest); } homeBuilder.HeaderWithLink(2, g.Key, g.Key); homeBuilder.AppendLine(); var mb = new MarkdownBuilder(); mb.Header(1, "Usage Documentation"); mb.Header(2, "Controllers and Actions"); foreach (var item in g.OrderBy(x => x.Name)) { homeBuilder.ListLink(MarkdownBuilder.MarkdownCodeQuote(item.BeautifyName), g.Key + "#" + item.BeautifyName.Replace("<", "").Replace(">", "").Replace(",", "").Replace(" ", "-").ToLower()); mb.Append(item.ToString()); } mb.Header(2, "Referenced Types"); mb.Append(referencedModelContainer.ToString()); var result = Markdig.Markdown.Normalize(mb.ToString()); File.WriteAllText(Path.Combine(dest, g.Key + ".md"), result); homeBuilder.AppendLine(); } // Gen Home File.WriteAllText(Path.Combine(dest, "Home.md"), homeBuilder.ToString()); }
public override string ToString() { var mb = new MarkdownBuilder(); var isController = _type.Name.EndsWith("Controller"); mb.Header(isController ? 3 : 4, _markdownableTypeName.AsHeader()); mb.AppendLine(); var desc = _commentLookup[_type.FullName].FirstOrDefault(x => x.MemberType == MemberType.Type)?.Summary ?? ""; if (desc != "") { mb.AppendLine(desc); } mb.AppendLine(); if (isController) { foreach (var method in GetMethods()) { var methodInfo = _beautifier.ToMarkdownMethodInfo(method, _type, _type.Name.Substring(0, _type.Name.Length - "Controller".Length)); mb.AppendLine(methodInfo); } } else 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 => new MarkdownableTypeName(x.FieldType).AsLink(), x => x.Name, x => x.Name); BuildTable(mb, "Properties", GetProperties(), _commentLookup[_type.FullName], x => new MarkdownableTypeName(x.PropertyType).AsLink(), x => x.Name, x => x.Name); } return(mb.ToString()); }
private string GenericAsLink() { var typeName = Regex.Replace(_genericType.Name, @"`.+$", ""); var md = new MarkdownBuilder(); if (_isCursorLink) { var link = $@"{typeName}{LtChar}{string.Join(",", _args.Select(c => c.Name))}{GtChar}"; md.CursorLink(link); } else { md.Append(typeName); md.Append(LtChar); md.Append(string.Join(",", _args.Select(c => new MarkdownableTypeName(c).AsLink()))); md.Append(GtChar); } return(md.ToString()); }
private static void GenerateMarkdown(string target, string destination) { Console.WriteLine($"Generating markdown in location: {destination}"); var types = MarkdownGenerator.Load(target, string.Empty); // Home Markdown Builder var homeBuilder = new MarkdownBuilder(); homeBuilder.Header(1, "References"); homeBuilder.AppendLine(); foreach (var g in types.GroupBy(x => x.Namespace).OrderBy(x => x.Key)) { if (!Directory.Exists(destination)) { Directory.CreateDirectory(destination); } homeBuilder.HeaderWithLink(2, g.Key, g.Key); homeBuilder.AppendLine(); var sb = new StringBuilder(); foreach (var item in g.OrderBy(x => x.Name)) { homeBuilder.ListLink(MarkdownBuilder.MarkdownCodeQuote(item.BeautifyName), g.Key + "#" + item.BeautifyName.Replace("<", "").Replace(">", "").Replace(",", "").Replace(" ", "-").ToLower()); sb.Append(item.ToString()); } File.WriteAllText(Path.Combine(destination, g.Key + ".md"), sb.ToString()); homeBuilder.AppendLine(); } // Gen Home File.WriteAllText(Path.Combine(destination, "Home.md"), homeBuilder.ToString()); }
public string ToMarkdownMethodInfo(MethodInfo methodInfo, Type type, string controller) { var isExtension = methodInfo.GetCustomAttributes <System.Runtime.CompilerServices.ExtensionAttribute>(false).Any(); var seq = methodInfo.GetParameters().Select(x => { var suffix = x.HasDefaultValue ? (" = " + (x.DefaultValue ?? $"null")) : ""; _referencedModelContainer.AddType(x.ParameterType); return($"{new MarkdownableTypeName(x.ParameterType).AsLink()} {x.Name}{suffix}"); }); var mb = new MarkdownBuilder(); var coreAttributes = methodInfo.GetCustomAttributes <ProducesResponseTypeAttribute>(); var swaggerAttributes = methodInfo.GetCustomAttributes <SwaggerResponseAttribute>(); //TODO get this from route also mb.Header(4, $"{controller}/{methodInfo.Name}"); mb.AppendLine($"- {methodInfo.Name}({(isExtension ? "this " : "")}{string.Join(", ", seq)})").AppendLine(); var documentation = _commentLookup[type.FullName] .FirstOrDefault(c => c.MemberType == MemberType.Method && c.MemberName == methodInfo.Name) ?.Summary; if (documentation != null) { mb.AppendLine(documentation); mb.AppendLine(); } var headers = new[] { "StatusCode", "ReturnType", "Description" }; var actionDescriptions = new List <string[]>(); if (coreAttributes.Any()) { foreach (var attribute in coreAttributes) { actionDescriptions.Add(new[] { attribute.StatusCode.ToString(), new MarkdownableTypeName(attribute.Type).AsLink(), "" }); if (attribute.Type != null) { _referencedModelContainer.AddType(attribute.Type); } } } else if (swaggerAttributes.Any()) { foreach (var attribute in swaggerAttributes) { actionDescriptions.Add(new[] { attribute.StatusCode.ToString(), new MarkdownableTypeName(attribute.Type).AsLink(), attribute.Description }); if (attribute.Type != null) { _referencedModelContainer.AddType(attribute.Type); } } } mb.Table(headers, actionDescriptions); return(mb.ToString()); }
public override string ToString() { MarkdownBuilder mb = new MarkdownBuilder(); mb.HeaderWithCode(1, Beautifier.BeautifyType(type)); mb.AppendLine(); string desc = commentLookup[type.FullName].FirstOrDefault(x => x.MemberType == MemberType.Type)?.Summary ?? ""; if (desc != "") { mb.AppendLine(desc); } { StringBuilder sb = new StringBuilder(); string stat = type.IsAbstract && type.IsSealed ? "static " : ""; string abst = type.IsAbstract && !type.IsInterface && !type.IsSealed ? "abstract " : ""; string classOrStructOrEnumOrInterface = type.IsInterface ? "interface" : type.IsEnum ? "enum" : type.IsValueType ? "struct" : "class"; sb.AppendLine( $"public {stat}{abst}{classOrStructOrEnumOrInterface} {Beautifier.BeautifyType(type, true)}"); string 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.AppendLine(" : " + impl); } mb.Code("csharp", sb.ToString()); } mb.AppendLine(); if (type.IsEnum) { Type 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, x => x.Value.ToString(), x => x.Name, x => x.Name, (info, comment) => true); } else { BuildTable( mb, "Constructors", GetConstructors(type), x => x.Name, x => "#ctor", Beautifier.ToMarkdownConstructorInfo, (info, comment) => { ParameterInfo[] param = info.GetParameters(); return(param.Length == comment.Parameters.Count && param.All( p => { return comment.Parameters.ContainsKey(p.Name); })); }); BuildTable( mb, "Fields", GetFields(type), x => Beautifier.BeautifyType(x.FieldType), x => x.Name, x => x.Name, (info, comment) => true); BuildTable( mb, "Properties", GetProperties(type), x => Beautifier.BeautifyType(x.PropertyType), x => x.Name, x => x.Name, (info, comment) => true); BuildTable( mb, "Events", GetEvents(type), x => Beautifier.BeautifyType(x.EventHandlerType), x => x.Name, x => x.Name, (info, comment) => true); BuildTable( mb, "Methods", GetMethods(type), x => Beautifier.BeautifyType(x.ReturnType), x => x.Name, Beautifier.ToMarkdownMethodInfo, (info, comment) => { ParameterInfo[] param = info.GetParameters(); return(param.Length == comment.Parameters.Count && param.All( p => { return comment.Parameters.ContainsKey(p.Name); })); }); BuildTable( mb, "Static Fields", GetStaticFields(type), x => Beautifier.BeautifyType(x.FieldType), x => x.Name, x => x.Name, (info, comment) => true); BuildTable( mb, "Static Properties", GetStaticProperties(type), x => Beautifier.BeautifyType(x.PropertyType), x => x.Name, x => x.Name, (info, comment) => true); BuildTable( mb, "Static Methods", GetStaticMethods(type), x => Beautifier.BeautifyType(x.ReturnType), x => x.Name, Beautifier.ToMarkdownMethodInfo, (info, comment) => { ParameterInfo[] param = info.GetParameters(); return(param.Length == comment.Parameters.Count && param.All( p => { return comment.Parameters.ContainsKey(p.Name); })); }); BuildTable( mb, "Static Events", GetStaticEvents(type), x => Beautifier.BeautifyType(x.EventHandlerType), x => x.Name, x => x.Name, (info, comment) => true); } return(mb.ToString()); }
// 0 = dll src path, 1 = dest root private static void Main(string[] args) { // put dll & xml on same diretory. string target = string.Empty; string dest = "md"; string namespaceMatch = string.Empty; switch (args.Length) { case 1: target = args[0]; break; case 2: target = args[0]; dest = args[1]; break; case 3: target = args[0]; dest = args[1]; namespaceMatch = args[2]; break; } AppDomain.CurrentDomain.AssemblyResolve += (s, a) => { string archSpecificPath = Path.Combine( Directory.GetParent(target).FullName, Environment.Is64BitProcess ? "x64" : "x86", a.Name.Split(new[] { ',' }, 2)[0] + ".dll"); return(File.Exists(archSpecificPath) ? Assembly.LoadFile(archSpecificPath) : null); }; MarkdownableType[] types = MarkdownGenerator.Load(target, namespaceMatch); // Home Markdown Builder MarkdownBuilder homeBuilder = new MarkdownBuilder(); homeBuilder.Header(1, "References"); homeBuilder.AppendLine(); MarkdownBuilder sidebarBuilder = new MarkdownBuilder(); foreach (IGrouping <string, MarkdownableType> g in types.GroupBy(x => x.Namespace).OrderBy(x => x.Key)) { if (!Directory.Exists(dest)) { Directory.CreateDirectory(dest); } homeBuilder.HeaderWithLink(2, g.Key, g.Key); homeBuilder.AppendLine(); sidebarBuilder.HeaderWithLink(5, g.Key, g.Key); sidebarBuilder.AppendLine(); StringBuilder sb = new StringBuilder(); foreach (MarkdownableType item in g.OrderBy(x => x.Name)) { homeBuilder.ListLink( MarkdownBuilder.MarkdownCodeQuote(item.BeautifyName), g.Key + "#" + item.BeautifyName.Replace("<", "") .Replace(">", "") .Replace(",", "") .Replace(" ", "-") .ToLower()); sidebarBuilder.ListLink( MarkdownBuilder.MarkdownCodeQuote(item.BeautifyName), g.Key + "#" + item.BeautifyName.Replace("<", "") .Replace(">", "") .Replace(",", "") .Replace(" ", "-") .ToLower()); sb.Append(item); } File.WriteAllText(Path.Combine(dest, g.Key + ".md"), sb.ToString()); homeBuilder.AppendLine(); sidebarBuilder.AppendLine(); } // Gen Home File.WriteAllText(Path.Combine(dest, "Home.md"), homeBuilder.ToString()); // Gen sidebar File.WriteAllText(Path.Combine(dest, "_Sidebar.md"), sidebarBuilder.ToString()); File.WriteAllText( Path.Combine(dest, "_Footer.md"), $@"*** #### auto generated wiki!<br/>all changes can be removed within next update _Copyright (c) {DateTime.Now.Year} exomia_ "); }