question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Markdown doesn't play nicely with .NET XML documentation

See original GitHub issue

I’ve noticed a few discrepancies in the rendering of markdown inside swashbuckle/swagger-ui.

The issue stems from the .NET xml comments and how the xml file is produced - each line is usually indented for easier human reading. The leading and trailing whitespace is trimmed, but it leaves any intermediate lines with extra leading whitespace, killing any hopes of an easy markdown conversion.

I’ve written a javascript workaround script which is added to a custom “index.html”. It attempts to calculate the leading padding remove it from each line: https://gist.github.com/davetransom/ddb755a61ad86f0e9690

Though, the xml file could possibly be massaged into a better format via an IDocumentFilter too.

I wasn’t sure if I should contribute this as a PR (it would add a .js file to the swashbuckle project), so thought I’d raise an issue for discussion first.

current: partial conversion to html Note the sentence wrapping and the code block not behaving.

markdown-current

expected:

markdown-expected

As an aside, it’s worth noting that the swagger-ui version sometimes puts a markdown class on <p> elements, which will lead to a nested <p> situation. The javascript workaround also averts that.

Issue Analytics

  • State:closed
  • Created 8 years ago
  • Comments:9 (4 by maintainers)

github_iconTop GitHub Comments

15reactions
geokapscommented, Apr 23, 2015

Building on @domaindrivendev 's custom formatting sample above, I found that you can get some pretty decent markdown support in XML Comments by using the following Formatted() method (or something similar to your liking) in your custom FormatXmlCommentProperties.cs class:

        private string Formatted(string text)
        {
            if (text == null) return null;

            // Strip out the whitespace that messes up the markdown in the xml comments,
            // but don't touch the whitespace in <code> blocks. Those get fixed below.
            string resultString = Regex.Replace(text, @"(^[ \t]+)(?![^<]*>|[^>]*<\/)", "", RegexOptions.Multiline);
            resultString = Regex.Replace(resultString, @"<code[^>]*>", "<pre>", RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Multiline);
            resultString = Regex.Replace(resultString, @"</code[^>]*>", "</pre>", RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Multiline);
            resultString = Regex.Replace(resultString, @"<!--", "", RegexOptions.Multiline);
            resultString = Regex.Replace(resultString, @"-->", "", RegexOptions.Multiline);

            try
            {
                string pattern = @"<pre\b[^>]*>(.*?)</pre>";

                foreach (Match match in Regex.Matches(resultString, pattern, RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Multiline ))
                {
                    var formattedPreBlock = FormatPreBlock(match.Value);
                    resultString = resultString.Replace(match.Value, formattedPreBlock);
                }
                return resultString;
            }
            catch
            {
                // Something went wrong so just return the original resultString
                return resultString;
            }
        }

        private string FormatPreBlock(string preBlock)
        {
            // Split the <pre> block into multiple lines
            var linesArray = preBlock.Split('\n');
            if (linesArray.Length < 2)
            {
                return preBlock;
            }
            else
            {
                // Get the 1st line after the <pre>
                string line = linesArray[1];
                int lineLength = line.Length;
                string formattedLine = line.TrimStart(' ', '\t');
                int paddingLength = lineLength - formattedLine.Length;

                // Remove the padding from all of the lines in the <pre> block
                for (int i = 1; i < linesArray.Length-1; i++)
                {
                    linesArray[i] = linesArray[i].Substring(paddingLength);
                }

                var formattedPreBlock = string.Join("", linesArray);
                return formattedPreBlock; 
            }

        }

Using this formatter you can have an Xml Comment block in your code that looks like this for example:

        /// <summary>
        /// Gets a the list of entities and their descriptions from the Entity Service.
        /// </summary>
        /// <remarks>
        /// ### REMARKS ###
        /// Use this call to retrieve a list of entities and their descriptions. This is used when setting up a new ViewSet.
        /// - Returns an array of **EntityDescription** objects.
        /// - The array is `ordered alphabetically` by the Name property.
        /// <!-- 
        /// <code>
        ///     // contrived code sample to demonstrate code block in swagger.
        ///     for (i=0; i < 5; i++)
        ///     {
        ///         doesthiswork = yesitdoes;
        ///     }
        /// </code>
        /// -->
        /// </remarks>
        /// <response code="200">OK</response>
        /// <returns>An array of EntityDescription objects.</returns>

Which will yield the following output: capture

Note that you have to comment out the <code> block as shown using the <!-- --> strategy in your XML comments or else the Visual Studio XML compiler will say that it’s badly formed and not include it in the output.

4reactions
domaindrivendevcommented, Apr 15, 2015

Unless I’m mistaken, I don’t believe there has ever been any code that converts para to p tags so not sure how this was ever working.

The currently supported tags are listed in the readme - https://github.com/domaindrivendev/Swashbuckle#including-xml-comments

Looking at the incoming issues, there is definitely a desire out there for richer support but there is also so many hours in the day and other features are higher on the list of priorities right now.

It’s worth noting however, that you can easily implement this yourself with a very simple extension point. Just wire up a custom operation filter to post process the generated Swagger document.

For example:

//SwaggerConfig.cs
c.IncludeXmlComments(GetXmlCommentsPath());
c.OperationFilter<FormatXmlCommentProperties>(); // after above line for correct execution order

//FormatXmlCommentProperties.cs
public class FormatXmlCommentProperties : IOperationFilter
{
    public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
    {
        operation.description = Formatted(operation.description);
        operation.summary = Formatted(operation.summary);
    }

    private string Formatted(string text)
    {
        if (text == null) return null;
        var stringBuilder = new StringBuilder(text);

        return stringBuilder
            .Replace("<para>", "<p>")
            .Replace("</para>", "</p>")
            .ToString();
    }
}

At some point in the future, we’ll get this built in out of the box - still puzzled as to how this was formatting better previously.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Markdown doesn't play nicely with .NET XML documentation
The issue stems from the .NET xml comments and how the xml file is produced - each line is usually indented for easier...
Read more >
c# - Using Markdown for source code documentation
They will need to be run through a Markdown processor to produce properly-formatted XML documentation files prior to working.
Read more >
Since When Did XML Comments Support Markdown??
I was taking a look at PipeWriter.cs over at .NET Source Browser and saw something I've never seen before in triple-slash comments:
Read more >
platyPS: write External Help files in Markdown
platyPS is a PowerShell module that converts PowerShell help files written as Markdown to other formats starting with MAML XML.
Read more >
Vsxmd 1.4.5
Vsxmd. AppVeyor NuGet. A MSBuild task to convert XML documentation to Markdown syntax. Support both .Net Framework and .Net Core projects.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found