Skip to content

Commit 2826dd9

Browse files
authored
Humanize multi line code tag (#3239)
Trim text at the end and add newline if text containing `<code>\r\n` and/or `\r\n</code>` combinations.
1 parent 5ecbb3b commit 2826dd9

File tree

5 files changed

+136
-2
lines changed

5 files changed

+136
-2
lines changed

src/Swashbuckle.AspNetCore.SwaggerGen/XmlComments/XmlCommentsTextHelper.cs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Linq;
33
using System.Net;
4+
using System.Text;
45
using System.Text.RegularExpressions;
56

67
namespace Swashbuckle.AspNetCore.SwaggerGen
@@ -10,7 +11,7 @@ public static partial class XmlCommentsTextHelper
1011
public static string Humanize(string text)
1112
{
1213
if (text == null)
13-
throw new ArgumentNullException("text");
14+
throw new ArgumentNullException(nameof(text));
1415

1516
//Call DecodeXml at last to avoid entities like &lt and &gt to break valid xml
1617

@@ -101,7 +102,24 @@ private static string HumanizeCodeTags(this string text)
101102

102103
private static string HumanizeMultilineCodeTags(this string text)
103104
{
104-
return MultilineCodeTag().Replace(text, (match) => "```" + match.Groups["display"].Value + "```");
105+
return MultilineCodeTag().Replace(text, match =>
106+
{
107+
var codeText = match.Groups["display"].Value;
108+
if (LineBreaks().IsMatch(codeText))
109+
{
110+
var builder = new StringBuilder().Append("```");
111+
if (!codeText.StartsWith("\r") && !codeText.StartsWith("\n"))
112+
{
113+
builder.AppendLine();
114+
}
115+
116+
return builder.AppendLine(codeText.TrimEnd())
117+
.Append("```")
118+
.ToString();
119+
}
120+
121+
return $"```{codeText}```";
122+
});
105123
}
106124

107125
private static string HumanizeParaTags(this string text)

test/Swashbuckle.AspNetCore.IntegrationTests/SwaggerVerifyIntegrationTest.SwaggerEndpoint_ReturnsValidSwaggerJson_DotNet6_startupType=Basic.Startup_swaggerRequestUri=v1.verified.txt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,31 @@
8787
"x-purpose": "test"
8888
}
8989
},
90+
"/products/all": {
91+
"get": {
92+
"tags": [
93+
"CrudActions"
94+
],
95+
"summary": "Get all products",
96+
"description": "```\r\n {\r\n \"Id\":1,\r\n \"Description\":\"\",\r\n \"Status\": 0,\r\n \"Status2\": 1\r\n }\r\n```",
97+
"responses": {
98+
"200": {
99+
"description": "OK",
100+
"content": {
101+
"application/json": {
102+
"schema": {
103+
"type": "array",
104+
"items": {
105+
"$ref": "#/components/schemas/Product"
106+
}
107+
}
108+
}
109+
}
110+
}
111+
},
112+
"x-purpose": "test"
113+
}
114+
},
90115
"/products/{id}": {
91116
"get": {
92117
"tags": [

test/Swashbuckle.AspNetCore.IntegrationTests/SwaggerVerifyIntegrationTest.SwaggerEndpoint_ReturnsValidSwaggerJson_startupType=Basic.Startup_swaggerRequestUri=v1.verified.txt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,31 @@
8787
"x-purpose": "test"
8888
}
8989
},
90+
"/products/all": {
91+
"get": {
92+
"tags": [
93+
"CrudActions"
94+
],
95+
"summary": "Get all products",
96+
"description": "```\r\n {\r\n \"Id\":1,\r\n \"Description\":\"\",\r\n \"Status\": 0,\r\n \"Status2\": 1\r\n }\r\n```",
97+
"responses": {
98+
"200": {
99+
"description": "OK",
100+
"content": {
101+
"application/json": {
102+
"schema": {
103+
"type": "array",
104+
"items": {
105+
"$ref": "#/components/schemas/Product"
106+
}
107+
}
108+
}
109+
}
110+
}
111+
},
112+
"x-purpose": "test"
113+
}
114+
},
90115
"/products/{id}": {
91116
"get": {
92117
"tags": [

test/Swashbuckle.AspNetCore.SwaggerGen.Test/XmlComments/XmlCommentsTextHelperTests.cs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,5 +158,54 @@ This is a paragraph.
158158

159159
Assert.Equal("\r\nThis is a paragraph. MultiLined.\r\n\r\nThis is a paragraph.", output, false, true);
160160
}
161+
162+
[Fact]
163+
public void Humanize_CodeMultiLineTag()
164+
{
165+
const string input = @"
166+
<code>
167+
{
168+
""Prop1"":1,
169+
""Prop2"":[]
170+
}
171+
</code>";
172+
173+
var output = XmlCommentsTextHelper.Humanize(input);
174+
175+
var expected = string.Join("\r\n",
176+
[
177+
"```",
178+
" {",
179+
" \"Prop1\":1,",
180+
" \"Prop2\":[]",
181+
" }",
182+
"```"
183+
]);
184+
Assert.Equal(expected, output, false, true);
185+
}
186+
187+
[Fact]
188+
public void Humanize_CodeMultiLineTag_OnSameLine()
189+
{
190+
const string input = @"
191+
<code>{
192+
""Prop1"":1,
193+
""Prop2"":[]
194+
}
195+
</code>";
196+
197+
var output = XmlCommentsTextHelper.Humanize(input);
198+
199+
var expected = string.Join("\r\n",
200+
[
201+
"```",
202+
"{",
203+
" \"Prop1\":1,",
204+
" \"Prop2\":[]",
205+
" }",
206+
"```"
207+
]);
208+
Assert.Equal(expected, output, false, true);
209+
}
161210
}
162211
}

test/WebSites/Basic/Controllers/CrudActionsController.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,23 @@ public Product Create([FromBody, Required]Product product)
3232
return product;
3333
}
3434

35+
/// <summary>Get all products</summary>
36+
/// <remarks>
37+
/// <code>
38+
/// {
39+
/// "Id":1,
40+
/// "Description":"",
41+
/// "Status": 0,
42+
/// "Status2": 1
43+
/// }
44+
/// </code>
45+
/// </remarks>
46+
[HttpGet("all")]
47+
public List<Product> GetAll()
48+
{
49+
return [];
50+
}
51+
3552
/// <summary>
3653
/// Searches the collection of products by description key words
3754
/// </summary>

0 commit comments

Comments
 (0)