Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Doc comment <code> block is not rendered correctly #10390

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 38 additions & 1 deletion samples/seed/dotnet/project/Project/Inheritdoc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,4 +108,41 @@ public class Class2 : Class1<bool>
public override bool TestMethod1(bool parm1, int parm2) => false;
}
}
}

// Issue #9736 #9495 #9754
public class Issue9736
{
public interface IJsonApiOptions
{
/// <summary>
/// Whether to use relative links for all resources. <c>false</c> by default.
/// </summary>
/// <example>
/// <code><![CDATA[
/// options.UseRelativeLinks = true;
/// ]]></code>
/// <code><![CDATA[
/// {
/// "type": "articles",
/// "id": "4309",
/// "relationships": {
/// "author": {
/// "links": {
/// "self": "/api/shopping/articles/4309/relationships/author",
/// "related": "/api/shopping/articles/4309/author"
/// }
/// }
/// }
/// }
/// ]]></code>
/// </example>
bool UseRelativeLinks { get; }
}

public sealed class JsonApiOptions : IJsonApiOptions
{
/// <inheritdoc />
public bool UseRelativeLinks { get; set; }
}
}
}
7 changes: 2 additions & 5 deletions src/Docfx.Dotnet/Parsers/XmlComment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,6 @@ public static XmlComment Parse(string xml, XmlCommentParserContext context = nul
}
try
{
// Format xml with indentation.
// It's needed to fix issue (https://github.com/dotnet/docfx/issues/9736)
xml = XElement.Parse(xml).ToString(SaveOptions.None);

return new XmlComment(xml, context ?? new());
}
catch (XmlException)
Expand Down Expand Up @@ -170,7 +166,8 @@ private void ResolveCode(XDocument doc, XmlCommentParserContext context)

code.SetAttributeValue("class", $"lang-{lang}");

if (node.PreviousNode is null)
if (node.PreviousNode is null
|| node.PreviousNode is XText xText && xText.Value == $"\n{indent}")
{
// Xml writer formats <pre><code> with unintended identation
// when there is no preceeding text node.
Expand Down
56 changes: 50 additions & 6 deletions test/Docfx.Dotnet.Tests/XmlCommentUnitTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ public static void ParaNewLine()
Assert.Equal(
"""
a
<p>b</p><p>c</p>
<p>b</p>
<p>c</p>
""",
XmlComment.Parse("""
<summary>
Expand Down Expand Up @@ -390,13 +391,14 @@ Classes in assemblies are by definition complete.
<a href="https://example.org">example</a>
<p>This is <code class="paramref">ref</code> a sample of exception node</p>
<ul><li>
<pre><code class="lang-c#">public class XmlElement
: XmlLinkedNode</code></pre>
<ol><li>
word inside list-&gt;listItem-&gt;list-&gt;listItem-&gt;para.&gt;

<pre><code class="lang-c#">public class XmlElement
: XmlLinkedNode</code></pre>
<ol><li>
word inside list->listItem->list->listItem->para.>
the second line.
</li><li>item2 in numbered list</li></ol>
</li><li>item2 in bullet list</li><li>
</li><li>item2 in bullet list</li><li>
loose text <i>not</i> wrapped in description
</li></ul>
""", remarks, ignoreLineEndingDifferences: true);
Expand Down Expand Up @@ -519,6 +521,7 @@ public void Issue9495()
Assert.Equal(
"""
<pre><code class="lang-csharp">options.UseRelativeLinks = true;</code></pre>

<pre><code class="lang-csharp">{
"type": "articles",
"id": "4309",
Expand All @@ -533,4 +536,45 @@ public void Issue9495()
}</code></pre>
""", comment.Examples[0], ignoreLineEndingDifferences: true);
}

[Fact]
public void Issue10385()
{
var comment = XmlComment.Parse(
"""
<remarks>
<para>
Paragraph.
</para>
<code lang="cs">
public sealed class Issue10385
{
public int AAA {get;set;}

public int BBB {get;set;}

public int CCC {get;set;}
}
</code>
</remarks>
""");
Assert.Equal(
"""
<p>
Paragraph.
</p>

<pre><code class="lang-csharp">public sealed class Issue10385
{
public int AAA {get;set;}

public int BBB {get;set;}

public int CCC {get;set;}
}</code></pre>
""", comment.Remarks, ignoreLineEndingDifferences: true);
}



}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"items": [
{
"name": "Namespace",
"name": "Namespaces",
"items": [
{
"name": "MyExample",
Expand All @@ -11,7 +11,7 @@
"type": "Namespace",
"items": [
{
"name": "Class",
"name": "Classes",
"items": [
{
"name": "ExampleClass",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"content": "{\"items\":[{\"name\":\"Namespace\",\"items\":[{\"name\":\"MyExample\",\"href\":\"MyExample.html\",\"topicHref\":\"MyExample.html\",\"topicUid\":\"MyExample\",\"type\":\"Namespace\",\"items\":[{\"name\":\"Class\",\"items\":[{\"name\":\"ExampleClass\",\"href\":\"MyExample.ExampleClass.html\",\"topicHref\":\"MyExample.ExampleClass.html\",\"topicUid\":\"MyExample.ExampleClass\",\"type\":\"Class\",\"items\":[{\"name\":\"Constructors\",\"items\":[{\"name\":\"ExampleClass\",\"href\":\"MyExample.ExampleClass.-ctor.html\",\"topicHref\":\"MyExample.ExampleClass.-ctor.html\",\"topicUid\":\"MyExample.ExampleClass.#ctor*\",\"type\":\"Constructor\",\"fullName\":\"MyExample.ExampleClass.ExampleClass\",\"nameWithType\":\"ExampleClass.ExampleClass\",\"isEii\":false,\"tocHref\":null,\"level\":7,\"items\":[],\"leaf\":true}],\"topicHref\":null,\"tocHref\":null,\"level\":6,\"leaf\":false},{\"name\":\"Properties\",\"items\":[{\"name\":\"MyProperty\",\"href\":\"MyExample.ExampleClass.MyProperty.html\",\"topicHref\":\"MyExample.ExampleClass.MyProperty.html\",\"topicUid\":\"MyExample.ExampleClass.MyProperty*\",\"type\":\"Property\",\"fullName\":\"MyExample.ExampleClass.MyProperty\",\"nameWithType\":\"ExampleClass.MyProperty\",\"isEii\":false,\"tocHref\":null,\"level\":7,\"items\":[],\"leaf\":true}],\"topicHref\":null,\"tocHref\":null,\"level\":6,\"leaf\":false},{\"name\":\"Methods\",\"items\":[{\"name\":\"MyMethod\",\"href\":\"MyExample.ExampleClass.MyMethod.html\",\"topicHref\":\"MyExample.ExampleClass.MyMethod.html\",\"topicUid\":\"MyExample.ExampleClass.MyMethod*\",\"type\":\"Method\",\"fullName\":\"MyExample.ExampleClass.MyMethod\",\"nameWithType\":\"ExampleClass.MyMethod\",\"isEii\":false,\"tocHref\":null,\"level\":7,\"items\":[],\"leaf\":true}],\"topicHref\":null,\"tocHref\":null,\"level\":6,\"leaf\":false},{\"name\":\"Events\",\"items\":[{\"name\":\"MyEvent\",\"href\":\"MyExample.ExampleClass.MyEvent.html\",\"topicHref\":\"MyExample.ExampleClass.MyEvent.html\",\"topicUid\":\"MyExample.ExampleClass.MyEvent\",\"type\":\"Event\",\"fullName\":\"MyExample.ExampleClass.MyEvent\",\"nameWithType\":\"ExampleClass.MyEvent\",\"isEii\":false,\"tocHref\":null,\"level\":7,\"items\":[],\"leaf\":true}],\"topicHref\":null,\"tocHref\":null,\"level\":6,\"leaf\":false}],\"tocHref\":null,\"level\":5,\"leaf\":false}],\"topicHref\":null,\"tocHref\":null,\"level\":4,\"leaf\":false}],\"tocHref\":null,\"level\":3,\"leaf\":false}],\"topicHref\":null,\"tocHref\":null,\"level\":2,\"leaf\":false}],\"memberLayout\":\"SeparatePages\",\"topicHref\":null,\"tocHref\":null,\"name\":null,\"level\":1,\"leaf\":false}"
"content": "{\"items\":[{\"name\":\"Namespaces\",\"items\":[{\"name\":\"MyExample\",\"href\":\"MyExample.html\",\"topicHref\":\"MyExample.html\",\"topicUid\":\"MyExample\",\"type\":\"Namespace\",\"items\":[{\"name\":\"Classes\",\"items\":[{\"name\":\"ExampleClass\",\"href\":\"MyExample.ExampleClass.html\",\"topicHref\":\"MyExample.ExampleClass.html\",\"topicUid\":\"MyExample.ExampleClass\",\"type\":\"Class\",\"items\":[{\"name\":\"Constructors\",\"items\":[{\"name\":\"ExampleClass\",\"href\":\"MyExample.ExampleClass.-ctor.html\",\"topicHref\":\"MyExample.ExampleClass.-ctor.html\",\"topicUid\":\"MyExample.ExampleClass.#ctor*\",\"type\":\"Constructor\",\"fullName\":\"MyExample.ExampleClass.ExampleClass\",\"nameWithType\":\"ExampleClass.ExampleClass\",\"isEii\":false,\"tocHref\":null,\"level\":7,\"items\":[],\"leaf\":true}],\"topicHref\":null,\"tocHref\":null,\"level\":6,\"leaf\":false},{\"name\":\"Properties\",\"items\":[{\"name\":\"MyProperty\",\"href\":\"MyExample.ExampleClass.MyProperty.html\",\"topicHref\":\"MyExample.ExampleClass.MyProperty.html\",\"topicUid\":\"MyExample.ExampleClass.MyProperty*\",\"type\":\"Property\",\"fullName\":\"MyExample.ExampleClass.MyProperty\",\"nameWithType\":\"ExampleClass.MyProperty\",\"isEii\":false,\"tocHref\":null,\"level\":7,\"items\":[],\"leaf\":true}],\"topicHref\":null,\"tocHref\":null,\"level\":6,\"leaf\":false},{\"name\":\"Methods\",\"items\":[{\"name\":\"MyMethod\",\"href\":\"MyExample.ExampleClass.MyMethod.html\",\"topicHref\":\"MyExample.ExampleClass.MyMethod.html\",\"topicUid\":\"MyExample.ExampleClass.MyMethod*\",\"type\":\"Method\",\"fullName\":\"MyExample.ExampleClass.MyMethod\",\"nameWithType\":\"ExampleClass.MyMethod\",\"isEii\":false,\"tocHref\":null,\"level\":7,\"items\":[],\"leaf\":true}],\"topicHref\":null,\"tocHref\":null,\"level\":6,\"leaf\":false},{\"name\":\"Events\",\"items\":[{\"name\":\"MyEvent\",\"href\":\"MyExample.ExampleClass.MyEvent.html\",\"topicHref\":\"MyExample.ExampleClass.MyEvent.html\",\"topicUid\":\"MyExample.ExampleClass.MyEvent\",\"type\":\"Event\",\"fullName\":\"MyExample.ExampleClass.MyEvent\",\"nameWithType\":\"ExampleClass.MyEvent\",\"isEii\":false,\"tocHref\":null,\"level\":7,\"items\":[],\"leaf\":true}],\"topicHref\":null,\"tocHref\":null,\"level\":6,\"leaf\":false}],\"tocHref\":null,\"level\":5,\"leaf\":false}],\"topicHref\":null,\"tocHref\":null,\"level\":4,\"leaf\":false}],\"tocHref\":null,\"level\":3,\"leaf\":false}],\"topicHref\":null,\"tocHref\":null,\"level\":2,\"leaf\":false}],\"memberLayout\":\"SeparatePages\",\"topicHref\":null,\"tocHref\":null,\"name\":null,\"level\":1,\"leaf\":false}"
}
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@

{"items":[{"name":"Namespace","items":[{"name":"MyExample","href":"MyExample.html","topicHref":"MyExample.html","topicUid":"MyExample","type":"Namespace","items":[{"name":"Class","items":[{"name":"ExampleClass","href":"MyExample.ExampleClass.html","topicHref":"MyExample.ExampleClass.html","topicUid":"MyExample.ExampleClass","type":"Class","items":[{"name":"Constructors","items":[{"name":"ExampleClass","href":"MyExample.ExampleClass.-ctor.html","topicHref":"MyExample.ExampleClass.-ctor.html","topicUid":"MyExample.ExampleClass.#ctor*","type":"Constructor","fullName":"MyExample.ExampleClass.ExampleClass","nameWithType":"ExampleClass.ExampleClass","isEii":false,"tocHref":null,"level":7,"items":[],"leaf":true}],"topicHref":null,"tocHref":null,"level":6,"leaf":false},{"name":"Properties","items":[{"name":"MyProperty","href":"MyExample.ExampleClass.MyProperty.html","topicHref":"MyExample.ExampleClass.MyProperty.html","topicUid":"MyExample.ExampleClass.MyProperty*","type":"Property","fullName":"MyExample.ExampleClass.MyProperty","nameWithType":"ExampleClass.MyProperty","isEii":false,"tocHref":null,"level":7,"items":[],"leaf":true}],"topicHref":null,"tocHref":null,"level":6,"leaf":false},{"name":"Methods","items":[{"name":"MyMethod","href":"MyExample.ExampleClass.MyMethod.html","topicHref":"MyExample.ExampleClass.MyMethod.html","topicUid":"MyExample.ExampleClass.MyMethod*","type":"Method","fullName":"MyExample.ExampleClass.MyMethod","nameWithType":"ExampleClass.MyMethod","isEii":false,"tocHref":null,"level":7,"items":[],"leaf":true}],"topicHref":null,"tocHref":null,"level":6,"leaf":false},{"name":"Events","items":[{"name":"MyEvent","href":"MyExample.ExampleClass.MyEvent.html","topicHref":"MyExample.ExampleClass.MyEvent.html","topicUid":"MyExample.ExampleClass.MyEvent","type":"Event","fullName":"MyExample.ExampleClass.MyEvent","nameWithType":"ExampleClass.MyEvent","isEii":false,"tocHref":null,"level":7,"items":[],"leaf":true}],"topicHref":null,"tocHref":null,"level":6,"leaf":false}],"tocHref":null,"level":5,"leaf":false}],"topicHref":null,"tocHref":null,"level":4,"leaf":false}],"tocHref":null,"level":3,"leaf":false}],"topicHref":null,"tocHref":null,"level":2,"leaf":false}],"memberLayout":"SeparatePages","topicHref":null,"tocHref":null,"name":null,"level":1,"leaf":false}
{"items":[{"name":"Namespaces","items":[{"name":"MyExample","href":"MyExample.html","topicHref":"MyExample.html","topicUid":"MyExample","type":"Namespace","items":[{"name":"Classes","items":[{"name":"ExampleClass","href":"MyExample.ExampleClass.html","topicHref":"MyExample.ExampleClass.html","topicUid":"MyExample.ExampleClass","type":"Class","items":[{"name":"Constructors","items":[{"name":"ExampleClass","href":"MyExample.ExampleClass.-ctor.html","topicHref":"MyExample.ExampleClass.-ctor.html","topicUid":"MyExample.ExampleClass.#ctor*","type":"Constructor","fullName":"MyExample.ExampleClass.ExampleClass","nameWithType":"ExampleClass.ExampleClass","isEii":false,"tocHref":null,"level":7,"items":[],"leaf":true}],"topicHref":null,"tocHref":null,"level":6,"leaf":false},{"name":"Properties","items":[{"name":"MyProperty","href":"MyExample.ExampleClass.MyProperty.html","topicHref":"MyExample.ExampleClass.MyProperty.html","topicUid":"MyExample.ExampleClass.MyProperty*","type":"Property","fullName":"MyExample.ExampleClass.MyProperty","nameWithType":"ExampleClass.MyProperty","isEii":false,"tocHref":null,"level":7,"items":[],"leaf":true}],"topicHref":null,"tocHref":null,"level":6,"leaf":false},{"name":"Methods","items":[{"name":"MyMethod","href":"MyExample.ExampleClass.MyMethod.html","topicHref":"MyExample.ExampleClass.MyMethod.html","topicUid":"MyExample.ExampleClass.MyMethod*","type":"Method","fullName":"MyExample.ExampleClass.MyMethod","nameWithType":"ExampleClass.MyMethod","isEii":false,"tocHref":null,"level":7,"items":[],"leaf":true}],"topicHref":null,"tocHref":null,"level":6,"leaf":false},{"name":"Events","items":[{"name":"MyEvent","href":"MyExample.ExampleClass.MyEvent.html","topicHref":"MyExample.ExampleClass.MyEvent.html","topicUid":"MyExample.ExampleClass.MyEvent","type":"Event","fullName":"MyExample.ExampleClass.MyEvent","nameWithType":"ExampleClass.MyEvent","isEii":false,"tocHref":null,"level":7,"items":[],"leaf":true}],"topicHref":null,"tocHref":null,"level":6,"leaf":false}],"tocHref":null,"level":5,"leaf":false}],"topicHref":null,"tocHref":null,"level":4,"leaf":false}],"tocHref":null,"level":3,"leaf":false}],"topicHref":null,"tocHref":null,"level":2,"leaf":false}],"memberLayout":"SeparatePages","topicHref":null,"tocHref":null,"name":null,"level":1,"leaf":false}
Loading