diff --git a/XmlDocMarkdown.sln b/XmlDocMarkdown.sln index 20648967..dbb5f11e 100644 --- a/XmlDocMarkdown.sln +++ b/XmlDocMarkdown.sln @@ -37,6 +37,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharpWithNulls", "tests\FSharpWithNulls\FSharpWithNulls.fsproj", "{3CE29B0C-6CA6-4AF2-B2A8-A1DD8EDC0B39}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XmlDocMarkdown.Docusaurus", "src\XmlDocMarkdown.Docusaurus\XmlDocMarkdown.Docusaurus.csproj", "{ED68E96C-561D-4541-9607-632A33FEA07C}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -79,6 +81,10 @@ Global {3CE29B0C-6CA6-4AF2-B2A8-A1DD8EDC0B39}.Debug|Any CPU.Build.0 = Debug|Any CPU {3CE29B0C-6CA6-4AF2-B2A8-A1DD8EDC0B39}.Release|Any CPU.ActiveCfg = Release|Any CPU {3CE29B0C-6CA6-4AF2-B2A8-A1DD8EDC0B39}.Release|Any CPU.Build.0 = Release|Any CPU + {ED68E96C-561D-4541-9607-632A33FEA07C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ED68E96C-561D-4541-9607-632A33FEA07C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ED68E96C-561D-4541-9607-632A33FEA07C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ED68E96C-561D-4541-9607-632A33FEA07C}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/XmlDocMarkdown.Core/CommonArgs.cs b/src/XmlDocMarkdown.Core/CommonArgs.cs index d50f092d..e4a3db75 100644 --- a/src/XmlDocMarkdown.Core/CommonArgs.cs +++ b/src/XmlDocMarkdown.Core/CommonArgs.cs @@ -58,5 +58,7 @@ internal static class CommonArgs _ => throw new ArgsReaderException($"Invalid new line '{value}'. (Should be 'auto', 'lf', or 'crlf'.)"), }; } + + public static bool ReadUseTypeFoldersFlag(this ArgsReader args) => args.ReadFlag("type-folders"); } } diff --git a/src/XmlDocMarkdown.Core/DefaultPathBuilderFactory.cs b/src/XmlDocMarkdown.Core/DefaultPathBuilderFactory.cs new file mode 100644 index 00000000..c1bcce36 --- /dev/null +++ b/src/XmlDocMarkdown.Core/DefaultPathBuilderFactory.cs @@ -0,0 +1,6 @@ +namespace XmlDocMarkdown.Core; + +internal class DefaultPathBuilderFactory : IPathBuilderFactory +{ + public IPathBuilder Create() => new JekyllPathBuilder(); +} diff --git a/src/XmlDocMarkdown.Core/IPathBuilder.cs b/src/XmlDocMarkdown.Core/IPathBuilder.cs new file mode 100644 index 00000000..c40ef054 --- /dev/null +++ b/src/XmlDocMarkdown.Core/IPathBuilder.cs @@ -0,0 +1,13 @@ +using System.Reflection; + +namespace XmlDocMarkdown.Core; + +public interface IPathBuilder +{ + public IPathBuilder WithNamespace(string @namespace); + public IPathBuilder WithType(TypeInfo typeInfo); + public IPathBuilder WithMemberName(string name); + public IPathBuilder WithPermalinkPretty(); + public IPathBuilder WithTypeFolders(); + public string Build(); +} diff --git a/src/XmlDocMarkdown.Core/IPathBuilderFactory.cs b/src/XmlDocMarkdown.Core/IPathBuilderFactory.cs new file mode 100644 index 00000000..c250a1e3 --- /dev/null +++ b/src/XmlDocMarkdown.Core/IPathBuilderFactory.cs @@ -0,0 +1,6 @@ +namespace XmlDocMarkdown.Core; + +public interface IPathBuilderFactory +{ + public IPathBuilder Create(); +} diff --git a/src/XmlDocMarkdown.Core/JekyllPathBuilder.cs b/src/XmlDocMarkdown.Core/JekyllPathBuilder.cs new file mode 100644 index 00000000..11070ec5 --- /dev/null +++ b/src/XmlDocMarkdown.Core/JekyllPathBuilder.cs @@ -0,0 +1,79 @@ +using System.Reflection; + +namespace XmlDocMarkdown.Core; + +internal class JekyllPathBuilder : IPathBuilder +{ + private string? @namespace; + private string? typeName; + private string? memberName; + private bool hasPermalinkPretty; + private bool useTypeFolders; + + public IPathBuilder WithNamespace(string @namespace) + { + this.@namespace = @namespace; + return this; + } + + public IPathBuilder WithType(TypeInfo typeInfo) + { + typeName = typeInfo.Name; + return this; + } + + public IPathBuilder WithMemberName(string name) + { + memberName = name; + return this; + } + + public IPathBuilder WithPermalinkPretty() + { + hasPermalinkPretty = true; + return this; + } + + public IPathBuilder WithTypeFolders() + { + useTypeFolders = true; + return this; + } + + public string Build() + { + var relative = GetPermalink(typeName!); + var safeRelative = GetSafeName(relative); + + if (hasPermalinkPretty) + safeRelative += "Type.md"; + var path = $"{GetNamespaceUriName(@namespace)}/{safeRelative}"; + if (memberName is not null) + path += $"/{memberName}"; + else if (useTypeFolders) + path += $"/{safeRelative}"; + return $"{path}.md"; + } + + private string GetPermalink(string path) + { + if (hasPermalinkPretty) + { + // permalinks paths cannot end in .md + var pos = path.LastIndexOf('.'); + if (pos > 0) + path = path.Substring(0, pos); + } + return path.Replace("\\", "/"); + } + + private string GetSafeName(string name) + { + if (hasPermalinkPretty) + return name.Replace(".", ""); // Jekyll can't handle dots in file name. + return name; + } + + private static string GetNamespaceUriName(string? namespaceName) + => namespaceName ?? "global"; +} diff --git a/src/XmlDocMarkdown.Core/MarkdownGenerator.cs b/src/XmlDocMarkdown.Core/MarkdownGenerator.cs index 5154b727..7f19bc0b 100644 --- a/src/XmlDocMarkdown.Core/MarkdownGenerator.cs +++ b/src/XmlDocMarkdown.Core/MarkdownGenerator.cs @@ -1,10 +1,6 @@ -using System; -using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Globalization; -using System.IO; -using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; @@ -14,6 +10,7 @@ namespace XmlDocMarkdown.Core { internal sealed class MarkdownGenerator { + private readonly IPathBuilderFactory pathBuilderFactory; public string? NewLine { get; set; } public string? SourceCodePath { get; set; } @@ -32,6 +29,13 @@ internal sealed class MarkdownGenerator public IReadOnlyList? ExternalDocs { get; set; } + public bool UseTypeFolders { get; set; } + + public MarkdownGenerator(IPathBuilderFactory pathBuilderFactory) + { + this.pathBuilderFactory = pathBuilderFactory; + } + public IReadOnlyList GenerateOutput(Assembly assembly, XmlDocAssembly xmlDocAssembly) => DoGenerateOutput(assembly, xmlDocAssembly).ToList(); @@ -116,11 +120,19 @@ private IEnumerable DoGenerateOutput(Assembly assembly, XmlDocAssembl writer.WriteLine("| --- | --- |"); foreach (var typeInfo in typeGroup) { - var relative = GetPermalink(typeInfo.Path); - var safeRelative = GetSafeName(relative); + var builder = pathBuilderFactory + .Create() + .WithNamespace(group.Namespace) + .WithType(typeInfo.TypeInfo); + + if (UseTypeFolders) + builder.WithTypeFolders(); + if (PermalinkPretty) - safeRelative += "Type"; - var rel = MakeRelative(context.PageLocation, $"{GetNamespaceUriName(group.Namespace)}/{safeRelative}"); + builder.WithPermalinkPretty(); + + var rel = builder.Build(); + var typeText = GetShortSignatureMarkdown(typeInfo.ShortSignature, rel); var summaryText = GetShortSummaryMarkdown(xmlDocAssembly, typeInfo.TypeInfo, context); writer.WriteLine($"| {typeText} | {summaryText} |"); @@ -159,11 +171,19 @@ private IEnumerable DoGenerateOutput(Assembly assembly, XmlDocAssembl writer.WriteLine("| --- | --- |"); foreach (var typeInfo in typeGroup) { - var relative = GetPermalink(typeInfo.Path); - var safeRelative = GetSafeName(relative); + var builder = + pathBuilderFactory + .Create() + .WithNamespace(group.Namespace) + .WithType(typeInfo.TypeInfo); + + if (UseTypeFolders) + builder.WithTypeFolders(); + if (PermalinkPretty) - safeRelative += "Type"; - var rel = MakeRelative(context.PageLocation, $"{GetNamespaceUriName(group.Namespace)}/{safeRelative}"); + builder.WithPermalinkPretty(); + + var rel = builder.Build(); var typeText = GetShortSignatureMarkdown(typeInfo.ShortSignature, rel); var summaryText = GetShortSummaryMarkdown(xmlDocAssembly, typeInfo.TypeInfo, context); writer.WriteLine($"| {typeText} | {summaryText} |"); @@ -179,11 +199,19 @@ private IEnumerable DoGenerateOutput(Assembly assembly, XmlDocAssembl { if (visibleTypeRecord.Namespace == group.Namespace) { - var relative = GetPermalink(visibleTypeRecord.Path); - var safeRelative = GetSafeName(relative); + var builder = pathBuilderFactory + .Create() + .WithNamespace(visibleTypeRecord.Namespace) + .WithType(visibleTypeRecord.TypeInfo); + + if (UseTypeFolders) + builder.WithTypeFolders(); + if (PermalinkPretty) - safeRelative += "Type.md"; - var typePage = $"{GetNamespaceUriName(visibleTypeRecord.Namespace)}/{safeRelative}"; + builder.WithPermalinkPretty(); + + var typePage = builder.Build(); + yield return WriteMemberPage( path: typePage, title: GetFullMemberName(visibleTypeRecord.TypeInfo), @@ -207,8 +235,15 @@ private IEnumerable DoGenerateOutput(Assembly assembly, XmlDocAssembl foreach (var memberGroup in memberGroups) { + var path = pathBuilderFactory + .Create() + .WithNamespace(visibleTypeRecord.Namespace) + .WithType(visibleTypeRecord.TypeInfo) + .WithMemberName(memberGroup.MemberUriName) + .Build(); + yield return WriteMemberPage( - path: $"{GetNamespaceUriName(visibleTypeRecord.Namespace)}/{GetTypeUriName(visibleTypeRecord.TypeInfo)}/{memberGroup.MemberUriName}.md", + path: path, parent: typePage, title: memberGroup.MemberUriName, memberGroup: memberGroup.Members, @@ -474,7 +509,8 @@ private NamedText WriteMemberPage(string path, string parent, string title, IRea { var innerMembers = innerMemberGroup.Members; var firstInnerMember = innerMembers[0]; - var memberPath = firstInnerMember is TypeInfo ? + + var memberPath = firstInnerMember is TypeInfo || UseTypeFolders ? $"{GetMemberUriName(firstInnerMember)}{extension}" : $"{GetTypeUriName(typeInfo)}/{GetMemberUriName(firstInnerMember)}{extension}"; var memberText = GetShortSignatureMarkdown(innerMemberGroup.ShortSignature, memberPath); @@ -580,7 +616,7 @@ private NamedText WriteMemberPage(string path, string parent, string title, IRea } else { - writer.WriteLine("* " + $"namespace\u00A0[{GetNamespaceName(declaringType ?? typeInfo!)}](../{(typeInfo != null ? "" : "../")}{GetAssemblyUriName((declaringType ?? typeInfo!).Assembly)}{extension})"); + writer.WriteLine("* " + $"namespace\u00A0[{GetNamespaceName(declaringType ?? typeInfo!)}](../{(typeInfo != null ? (UseTypeFolders ? "../" : "") : "../")}{GetAssemblyUriName((declaringType ?? typeInfo!).Assembly)}{extension})"); } if (typeInfo != null && declaringType == null && !string.IsNullOrEmpty(context.SourceCodePath) && !string.IsNullOrEmpty(context.RootNamespace)) @@ -960,12 +996,12 @@ private string GetPropertyGetSet(PropertyInfo propertyInfo) var setVisibility = setMethod == null ? XmlDocVisibilityLevel.Private : GetMethodVisibility(setMethod); if (getMethod != null && (setMethod == null || IsMorePrivateThan(setVisibility, Visibility))) - return " { get; }"; + return " \\{ get; }"; if (getMethod == null || IsMorePrivateThan(getVisibility, Visibility)) - return " { set; }"; + return " \\{ set; }"; if (getVisibility == setVisibility) - return " { get; set; }"; + return " \\{ get; set; }"; if (IsMorePrivateThan(getVisibility, setVisibility)) return $" {{ {GetAccessModifier(getMethod)} get; set; }}"; return $" {{ get; {GetAccessModifier(setMethod!)} set; }}"; @@ -2067,21 +2103,21 @@ private string WrapMarkdownRefLink(string text, MemberInfo? memberInfo, Markdown if (context.MemberInfo != null) { if (typeInfo != null) - path = $"{GetNamespaceUriName(typeInfo.Namespace)}/{GetSafeTypeUriName(typeInfo)}{extension}"; + path = $"{GetNamespaceUriName(typeInfo.Namespace)}/{GetSafeTypeUriName(typeInfo)}{(UseTypeFolders ? "/" + GetSafeTypeUriName(typeInfo) : "")}{extension}"; else path = $"{GetNamespaceUriName(memberInfo.DeclaringType?.Namespace)}/{GetTypeUriName(memberInfo.DeclaringType.GetTypeInfo())}/{GetMemberUriName(memberInfo)}{extension}"; } else if (context.TypeInfo != null) { if (typeInfo != null) - path = $"{GetNamespaceUriName(typeInfo.Namespace)}/{GetSafeTypeUriName(typeInfo)}{extension}"; + path = $"{GetNamespaceUriName(typeInfo.Namespace)}/{GetSafeTypeUriName(typeInfo)}{(UseTypeFolders ? "/" + GetSafeTypeUriName(typeInfo) : "")}{extension}"; else path = $"{GetNamespaceUriName(memberInfo.DeclaringType?.Namespace)}/{GetTypeUriName(memberInfo.DeclaringType.GetTypeInfo())}/{GetMemberUriName(memberInfo)}{extension}"; } else { if (typeInfo != null) - path = $"{GetNamespaceUriName(typeInfo.Namespace)}/{GetSafeTypeUriName(typeInfo)}{extension}"; + path = $"{GetNamespaceUriName(typeInfo.Namespace)}/{GetSafeTypeUriName(typeInfo)}{(UseTypeFolders ? "/" + GetSafeTypeUriName(typeInfo) : "")}{extension}"; else path = $"{GetNamespaceUriName(memberInfo.DeclaringType?.Namespace)}/{GetTypeUriName(memberInfo.DeclaringType.GetTypeInfo())}/{GetMemberUriName(memberInfo)}{extension}"; } diff --git a/src/XmlDocMarkdown.Core/XmlDocMarkdownApp.cs b/src/XmlDocMarkdown.Core/XmlDocMarkdownApp.cs index 5541a2cd..f4d4597c 100644 --- a/src/XmlDocMarkdown.Core/XmlDocMarkdownApp.cs +++ b/src/XmlDocMarkdown.Core/XmlDocMarkdownApp.cs @@ -14,8 +14,9 @@ public sealed class XmlDocMarkdownApp /// Run the command-line application. /// /// The command-line arguments. + /// The factory to create a Path Builder. /// The exit code. - public static int Run(IReadOnlyList args) + public static int Run(IReadOnlyList args, IPathBuilderFactory? pathBuilderFactory = null) { try { @@ -44,6 +45,7 @@ public static int Run(IReadOnlyList args) GenerateToc = argsReader.ReadTocFlag(), TocPrefix = argsReader.ReadTocPrefix(), NamespacePages = argsReader.ReadNamespacePagesFlag(), + UseTypeFolders = argsReader.ReadUseTypeFoldersFlag(), }; var externalDocs = new List(); @@ -67,7 +69,7 @@ public static int Run(IReadOnlyList args) argsReader.VerifyComplete(); - var result = XmlDocMarkdownGenerator.Generate(input, outputPath, settings); + var result = XmlDocMarkdownGenerator.Generate(input, outputPath, settings, pathBuilderFactory); foreach (var message in result.Messages) Console.WriteLine(message); @@ -143,6 +145,8 @@ private static void WriteUsage(TextWriter textWriter) textWriter.WriteLine(" File containing table of contents in .yml format."); textWriter.WriteLine(" --newline (auto|lf|crlf)"); textWriter.WriteLine(" The newline used in the output (default auto)."); + textWriter.WriteLine(" --type-folders"); + textWriter.WriteLine(" Type markdown will be inside the same folder has it's members."); } } } diff --git a/src/XmlDocMarkdown.Core/XmlDocMarkdownGenerator.cs b/src/XmlDocMarkdown.Core/XmlDocMarkdownGenerator.cs index 9dce0647..6c1b73a4 100644 --- a/src/XmlDocMarkdown.Core/XmlDocMarkdownGenerator.cs +++ b/src/XmlDocMarkdown.Core/XmlDocMarkdownGenerator.cs @@ -18,13 +18,16 @@ public static class XmlDocMarkdownGenerator /// The input assembly. /// The output directory. /// The settings. + /// The factory to create a Path Builder. /// The names of files that were added, changed, or removed. - public static XmlDocMarkdownResult Generate(string inputPath, string outputPath, XmlDocMarkdownSettings? settings) + public static XmlDocMarkdownResult Generate( + string inputPath, string outputPath, XmlDocMarkdownSettings? settings, + IPathBuilderFactory? pathBuilderFactory = null) { if (inputPath == null) throw new ArgumentNullException(nameof(inputPath)); - return Generate(new XmlDocInput { AssemblyPath = inputPath }, outputPath, settings); + return Generate(new XmlDocInput { AssemblyPath = inputPath }, outputPath, settings, pathBuilderFactory); } /// @@ -33,8 +36,11 @@ public static XmlDocMarkdownResult Generate(string inputPath, string outputPath, /// The input. /// The output directory. /// The settings. + /// The factory to create a Path Builder. /// The names of files that were added, changed, or removed. - public static XmlDocMarkdownResult Generate(XmlDocInput input, string outputPath, XmlDocMarkdownSettings? settings) + public static XmlDocMarkdownResult Generate( + XmlDocInput input, string outputPath, XmlDocMarkdownSettings? settings, + IPathBuilderFactory? pathBuilderFactory = null) { if (input == null) throw new ArgumentNullException(nameof(input)); @@ -45,7 +51,7 @@ public static XmlDocMarkdownResult Generate(XmlDocInput input, string outputPath settings ??= new XmlDocMarkdownSettings(); - var generator = new MarkdownGenerator + var generator = new MarkdownGenerator(pathBuilderFactory ?? new DefaultPathBuilderFactory()) { SourceCodePath = settings.SourceCodePath, RootNamespace = settings.RootNamespace, @@ -55,6 +61,7 @@ public static XmlDocMarkdownResult Generate(XmlDocInput input, string outputPath ExternalDocs = settings.ExternalDocs, NamespacePages = settings.NamespacePages, FrontMatter = settings.FrontMatter, + UseTypeFolders = settings.UseTypeFolders, }; if (settings.NewLine != null) generator.NewLine = settings.NewLine; diff --git a/src/XmlDocMarkdown.Core/XmlDocMarkdownSettings.cs b/src/XmlDocMarkdown.Core/XmlDocMarkdownSettings.cs index 57e5ed4a..a5cf20fb 100644 --- a/src/XmlDocMarkdown.Core/XmlDocMarkdownSettings.cs +++ b/src/XmlDocMarkdown.Core/XmlDocMarkdownSettings.cs @@ -90,5 +90,10 @@ public class XmlDocMarkdownSettings /// Configures external documentation. /// public IReadOnlyList? ExternalDocs { get; set; } + + /// + /// Specify if types should be on the same folder has it's members. + /// + public bool UseTypeFolders { get; set; } } } diff --git a/src/XmlDocMarkdown.Docusaurus/DocusaurusPathBuilder.cs b/src/XmlDocMarkdown.Docusaurus/DocusaurusPathBuilder.cs new file mode 100644 index 00000000..c31292f0 --- /dev/null +++ b/src/XmlDocMarkdown.Docusaurus/DocusaurusPathBuilder.cs @@ -0,0 +1,81 @@ +using System.Reflection; +using XmlDocMarkdown.Core; + +namespace XmlDocMarkdown.Docusaurus; + +internal sealed class DocusaurusPathBuilder : IPathBuilder +{ + private string? @namespace; + private string? typeName; + private string? memberName; + private bool hasPermalinkPretty; + private bool useTypeFolders; + + public IPathBuilder WithNamespace(string @namespace) + { + this.@namespace = @namespace; + return this; + } + + public IPathBuilder WithType(TypeInfo typeInfo) + { + typeName = typeInfo.Name; + return this; + } + + public IPathBuilder WithMemberName(string name) + { + memberName = name; + return this; + } + + public IPathBuilder WithPermalinkPretty() + { + hasPermalinkPretty = true; + return this; + } + + public IPathBuilder WithTypeFolders() + { + useTypeFolders = true; + return this; + } + + public string Build() + { + var relative = GetPermalink(typeName!); + var safeRelative = GetSafeName(relative); + + if (hasPermalinkPretty) + safeRelative += "Type.md"; + + var path = $"{GetNamespaceUriName(@namespace)}/{safeRelative}"; + if (memberName is not null) + path += $"/{memberName}"; + else if (useTypeFolders) + path += $"/{safeRelative}"; + return $"{path}.md".Replace("`", "-", StringComparison.OrdinalIgnoreCase); + } + + private string GetPermalink(string path) + { + if (hasPermalinkPretty) + { + // permalinks paths cannot end in .md + var pos = path.LastIndexOf('.'); + if (pos > 0) + path = path.Substring(0, pos); + } + return path.Replace("\\", "/", StringComparison.OrdinalIgnoreCase); + } + + private string GetSafeName(string name) + { + if (hasPermalinkPretty) + return name.Replace(".", "", StringComparison.OrdinalIgnoreCase); + return name; + } + + private static string GetNamespaceUriName(string? namespaceName) + => namespaceName ?? "global"; +} diff --git a/src/XmlDocMarkdown.Docusaurus/PathBuilderFactory.cs b/src/XmlDocMarkdown.Docusaurus/PathBuilderFactory.cs new file mode 100644 index 00000000..69bc2585 --- /dev/null +++ b/src/XmlDocMarkdown.Docusaurus/PathBuilderFactory.cs @@ -0,0 +1,8 @@ +using XmlDocMarkdown.Core; + +namespace XmlDocMarkdown.Docusaurus; + +internal sealed class PathBuilderFactory : IPathBuilderFactory +{ + public IPathBuilder Create() => new DocusaurusPathBuilder(); +} diff --git a/src/XmlDocMarkdown.Docusaurus/Program.cs b/src/XmlDocMarkdown.Docusaurus/Program.cs new file mode 100644 index 00000000..a1f76fa5 --- /dev/null +++ b/src/XmlDocMarkdown.Docusaurus/Program.cs @@ -0,0 +1,4 @@ +using XmlDocMarkdown.Core; +using XmlDocMarkdown.Docusaurus; + +return XmlDocMarkdownApp.Run(args, new PathBuilderFactory()); diff --git a/src/XmlDocMarkdown.Docusaurus/XmlDocMarkdown.Docusaurus.csproj b/src/XmlDocMarkdown.Docusaurus/XmlDocMarkdown.Docusaurus.csproj new file mode 100644 index 00000000..c5c2dacd --- /dev/null +++ b/src/XmlDocMarkdown.Docusaurus/XmlDocMarkdown.Docusaurus.csproj @@ -0,0 +1,21 @@ + + + + Exe + net6.0;net5.0;net8.0;netcoreapp3.1 + A .NET tool that generates Markdown from .NET XML documentation comments compatible with Docusaurus. + .NET XML documentation comments Markdown Docusaurus + true + true + xmldocmd-docusaurus + Major + enable + enable + true + + + + + + + diff --git a/src/xmldocmd/Program.cs b/src/xmldocmd/Program.cs index 893a7dfe..de499509 100644 --- a/src/xmldocmd/Program.cs +++ b/src/xmldocmd/Program.cs @@ -1,3 +1,4 @@ +using XmlDocMarkdown; using XmlDocMarkdown.Core; return XmlDocMarkdownApp.Run(args);