Skip to content

Commit adcd415

Browse files
committed
Blazor streaming markers (<!--bl:…-->, <!--/bl:…--> and <!--bab39c12-73f9-4e04-b6b9-76cb2b324662-->) are no longer removed
1 parent 52ae45e commit adcd415

File tree

7 files changed

+193
-33
lines changed

7 files changed

+193
-33
lines changed

src/WebMarkupMin.Core/GenericHtmlMinifier.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -700,12 +700,12 @@ private void CommentHandler(MarkupParsingContext context, string commentText)
700700
// Processing of end Knockout containerless comment
701701
processedCommentText = "/ko";
702702
}
703-
else if (KnockoutHelpers.IsBeginContainerlessComment(commentText))
703+
else if (KnockoutHelpers.IsStartContainerlessComment(commentText))
704704
{
705705
// Processing of begin Knockout containerless comment
706706
string koExpression = string.Empty;
707707

708-
KnockoutHelpers.ParseBeginContainerlessComment(commentText,
708+
KnockoutHelpers.ParseStartContainerlessComment(commentText,
709709
(localContext, expression) =>
710710
{
711711
SourceCodeNodeCoordinates expressionCoordinates = localContext.NodeCoordinates;

src/WebMarkupMin.Core/Helpers/BlazorHelpers.cs

Lines changed: 81 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,27 +18,42 @@ internal static class BlazorHelpers
1818
/// <summary>
1919
/// Blazor component marker prefix
2020
/// </summary>
21-
const string COMPONENT_MARKER_PREFIX = "Blazor:";
21+
const string COMPONENT_MARKER_PREFIX = MARKER_PREFIX_COMMON_PART + ":";
2222

2323
/// <summary>
2424
/// Blazor server persisted state marker prefix
2525
/// </summary>
26-
const string SERVER_STATE_MARKER_PREFIX = "Blazor-Server-Component-State:";
26+
const string SERVER_STATE_MARKER_PREFIX = MARKER_PREFIX_COMMON_PART + "-Server-Component-State:";
2727

2828
/// <summary>
2929
/// Blazor WebAssembly persisted state marker prefix
3030
/// </summary>
31-
const string WEBASSEMBLY_STATE_MARKER_PREFIX = "Blazor-WebAssembly-Component-State:";
31+
const string WEBASSEMBLY_STATE_MARKER_PREFIX = MARKER_PREFIX_COMMON_PART + "-WebAssembly-Component-State:";
3232

3333
/// <summary>
3434
/// Blazor web initializer marker prefix
3535
/// </summary>
36-
const string WEB_INITIALIZER_MARKER_PREFIX = "Blazor-Web-Initializers:";
36+
const string WEB_INITIALIZER_MARKER_PREFIX = MARKER_PREFIX_COMMON_PART + "-Web-Initializers:";
3737

3838
/// <summary>
39-
/// List of Blazor marker prefixes
39+
/// Blazor streaming boundary marker prefix common part
4040
/// </summary>
41-
private static readonly string[] _markerPrefixes = new string[]
41+
const string STREAMING_BOUNDARY_MARKER_PREFIX_COMMON_PART = "bl:";
42+
43+
/// <summary>
44+
/// Blazor start streaming boundary marker prefix
45+
/// </summary>
46+
const string START_STREAMING_BOUNDARY_MARKER_PREFIX = STREAMING_BOUNDARY_MARKER_PREFIX_COMMON_PART;
47+
48+
/// <summary>
49+
/// Blazor end streaming boundary marker prefix
50+
/// </summary>
51+
const string END_STREAMING_BOUNDARY_MARKER_PREFIX = "/" + STREAMING_BOUNDARY_MARKER_PREFIX_COMMON_PART;
52+
53+
/// <summary>
54+
/// List of Blazor ordinary marker prefixes
55+
/// </summary>
56+
private static readonly string[] _ordinaryMarkerPrefixes = new string[]
4257
{
4358
COMPONENT_MARKER_PREFIX,
4459
SERVER_STATE_MARKER_PREFIX,
@@ -58,6 +73,13 @@ internal static class BlazorHelpers
5873
private static readonly Regex _base64EncodedDataRegex = new Regex(@"[a-zA-Z0-9+/=]+$",
5974
TargetFrameworkShortcuts.PerformanceRegexOptions);
6075

76+
/// <summary>
77+
/// Regular expression for working with the Globally Unique Identifier (GUID)
78+
/// </summary>
79+
private static readonly Regex _guidRegex = new Regex(
80+
@"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
81+
TargetFrameworkShortcuts.PerformanceRegexOptions);
82+
6183

6284
/// <summary>
6385
/// Checks whether the comment is the Blazor marker
@@ -66,6 +88,21 @@ internal static class BlazorHelpers
6688
/// <returns>Result of check (<c>true</c> - is marker;
6789
/// <c>false</c> - is not marker)</returns>
6890
public static bool IsMarker(string commentText)
91+
{
92+
return IsOrdinaryMarker(commentText)
93+
|| IsStartStreamingBoundaryMarker(commentText)
94+
|| IsEndStreamingBoundaryMarker(commentText)
95+
|| IsStreamingFramingMarker(commentText)
96+
;
97+
}
98+
99+
/// <summary>
100+
/// Checks whether the comment is the Blazor ordinary marker
101+
/// </summary>
102+
/// <param name="commentText">Comment text</param>
103+
/// <returns>Result of check (<c>true</c> - is ordinary marker;
104+
/// <c>false</c> - is not ordinary marker)</returns>
105+
private static bool IsOrdinaryMarker(string commentText)
69106
{
70107
int commentTextLength = commentText.Length;
71108
if (commentTextLength == 0)
@@ -89,7 +126,7 @@ public static bool IsMarker(string commentText)
89126
return false;
90127
}
91128

92-
foreach (string prefix in _markerPrefixes)
129+
foreach (string prefix in _ordinaryMarkerPrefixes)
93130
{
94131
if (commentText.CustomStartsWith(prefix, firstNonWhitespaceCharPosition, StringComparison.Ordinal))
95132
{
@@ -119,5 +156,42 @@ public static bool IsMarker(string commentText)
119156

120157
return false;
121158
}
159+
160+
/// <summary>
161+
/// Checks whether the comment is the Blazor start streaming boundary marker
162+
/// </summary>
163+
/// <param name="commentText">Comment text</param>
164+
/// <returns>Result of check (<c>true</c> - is start streaming boundary marker;
165+
/// <c>false</c> - is not start streaming boundary marker)</returns>
166+
private static bool IsStartStreamingBoundaryMarker(string commentText)
167+
{
168+
return commentText.StartsWith(START_STREAMING_BOUNDARY_MARKER_PREFIX, StringComparison.Ordinal)
169+
&& commentText.Length > START_STREAMING_BOUNDARY_MARKER_PREFIX.Length
170+
;
171+
}
172+
173+
/// <summary>
174+
/// Checks whether the comment is the Blazor end streaming boundary marker
175+
/// </summary>
176+
/// <param name="commentText">Comment text</param>
177+
/// <returns>Result of check (<c>true</c> - is end streaming boundary marker;
178+
/// <c>false</c> - is not end streaming boundary marker)</returns>
179+
private static bool IsEndStreamingBoundaryMarker(string commentText)
180+
{
181+
return commentText.StartsWith(END_STREAMING_BOUNDARY_MARKER_PREFIX, StringComparison.Ordinal)
182+
&& commentText.Length > END_STREAMING_BOUNDARY_MARKER_PREFIX.Length
183+
;
184+
}
185+
186+
/// <summary>
187+
/// Checks whether the comment is the Blazor streaming framing marker
188+
/// </summary>
189+
/// <param name="commentText">Comment text</param>
190+
/// <returns>Result of check (<c>true</c> - is streaming framing marker;
191+
/// <c>false</c> - is not streaming framing marker)</returns>
192+
private static bool IsStreamingFramingMarker(string commentText)
193+
{
194+
return _guidRegex.IsMatch(commentText);
195+
}
122196
}
123197
}

src/WebMarkupMin.Core/Helpers/KnockoutHelpers.cs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ internal static class KnockoutHelpers
1717
const string KO_CONTAINERLESS_COMMENT_PREFIX = "ko";
1818

1919
/// <summary>
20-
/// Regular expression for working with the Knockout begin containerless comment
20+
/// Regular expression for working with the Knockout start containerless comment
2121
/// </summary>
22-
private static readonly Regex _koBeginContainerlessCommentRegex =
22+
private static readonly Regex _koStartContainerlessCommentRegex =
2323
new Regex(@"^\s*" + KO_CONTAINERLESS_COMMENT_PREFIX + @"(?:\s+(?<expression>[\s\S]+))?\s*$",
2424
TargetFrameworkShortcuts.PerformanceRegexOptions);
2525

@@ -32,30 +32,30 @@ internal static class KnockoutHelpers
3232

3333

3434
/// <summary>
35-
/// Checks whether the comment is the Knockout begin containerless comment
35+
/// Checks whether the comment is the Knockout start containerless comment
3636
/// </summary>
3737
/// <param name="commentText">Comment text</param>
38-
/// <returns>Result of check (<c>true</c> - is begin containerless comment;
39-
/// <c>false</c> - is not begin containerless comment)</returns>
40-
public static bool IsBeginContainerlessComment(string commentText)
38+
/// <returns>Result of check (<c>true</c> - is start containerless comment;
39+
/// <c>false</c> - is not start containerless comment)</returns>
40+
public static bool IsStartContainerlessComment(string commentText)
4141
{
4242
if (commentText.IndexOf(KO_CONTAINERLESS_COMMENT_PREFIX, StringComparison.Ordinal) == -1)
4343
{
4444
return false;
4545
}
4646

47-
return _koBeginContainerlessCommentRegex.IsMatch(commentText);
47+
return _koStartContainerlessCommentRegex.IsMatch(commentText);
4848
}
4949

5050
/// <summary>
51-
/// Parses a Knockout begin containerless comment
51+
/// Parses a Knockout start containerless comment
5252
/// </summary>
5353
/// <param name="commentText">Comment text</param>
5454
/// <param name="expressionHandler">Binding expression handler</param>
55-
public static void ParseBeginContainerlessComment(string commentText,
55+
public static void ParseStartContainerlessComment(string commentText,
5656
ExpressionDelegate expressionHandler)
5757
{
58-
Match match = _koBeginContainerlessCommentRegex.Match(commentText);
58+
Match match = _koStartContainerlessCommentRegex.Match(commentText);
5959
if (match.Success)
6060
{
6161
var innerContext = new InnerMarkupParsingContext(commentText);

src/WebMarkupMin.Core/Helpers/ReactHelpers.cs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ internal static class ReactHelpers
1616
const string REACT_DOM_COMPONENT_PREFIX = "react-";
1717

1818
/// <summary>
19-
/// Regular expression for working with the React begin DOM component comment
19+
/// Regular expression for working with the React start DOM component comment
2020
/// </summary>
21-
private static readonly Regex _reactBeginDomComponentCommentRegex = new Regex(
21+
private static readonly Regex _reactStartDomComponentCommentRegex = new Regex(
2222
@"^ " + REACT_DOM_COMPONENT_PREFIX + @"[a-z]+\: \d+ $",
2323
TargetFrameworkShortcuts.PerformanceRegexOptions);
2424

@@ -31,14 +31,14 @@ internal static class ReactHelpers
3131

3232

3333
/// <summary>
34-
/// Checks whether the comment is the React begin DOM component comment
34+
/// Checks whether the comment is the React start DOM component comment
3535
/// </summary>
3636
/// <param name="commentText">Comment text</param>
37-
/// <returns>Result of check (<c>true</c> - is begin DOM component comment;
38-
/// <c>false</c> - is not begin DOM component comment)</returns>
39-
public static bool IsBeginDomComponentComment(string commentText)
37+
/// <returns>Result of check (<c>true</c> - is start DOM component comment;
38+
/// <c>false</c> - is not start DOM component comment)</returns>
39+
private static bool IsStartDomComponentComment(string commentText)
4040
{
41-
return _reactBeginDomComponentCommentRegex.IsMatch(commentText);
41+
return _reactStartDomComponentCommentRegex.IsMatch(commentText);
4242
}
4343

4444
/// <summary>
@@ -47,7 +47,7 @@ public static bool IsBeginDomComponentComment(string commentText)
4747
/// <param name="commentText">Comment text</param>
4848
/// <returns>Result of check (<c>true</c> - is end DOM component comment;
4949
/// <c>false</c> - is not end DOM component comment)</returns>
50-
public static bool IsEndDomComponentComment(string commentText)
50+
private static bool IsEndDomComponentComment(string commentText)
5151
{
5252
return _reactEndDomComponentCommentRegex.IsMatch(commentText);
5353
}
@@ -65,7 +65,7 @@ public static bool IsDomComponentComment(string commentText)
6565
return false;
6666
}
6767

68-
return IsBeginDomComponentComment(commentText)
68+
return IsStartDomComponentComment(commentText)
6969
|| IsEndDomComponentComment(commentText)
7070
;
7171
}

src/WebMarkupMin.Core/WebMarkupMin.Core.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<PropertyGroup>
44
<Product>Web Markup Minifier: Core</Product>
5-
<VersionPrefix>2.16.1</VersionPrefix>
5+
<VersionPrefix>2.16.2</VersionPrefix>
66
<TargetFrameworks>net40-client;net45;netstandard1.3;netstandard2.0;netstandard2.1</TargetFrameworks>
77
<NetStandardImplicitPackageVersion Condition=" '$(TargetFramework)' == 'netstandard1.3' ">1.6.0</NetStandardImplicitPackageVersion>
88
<OutputType>Library</OutputType>
@@ -26,7 +26,7 @@ Minification of markup produces by removing extra whitespaces, comments and redu
2626

2727
Also supports minification of views of popular JavaScript template engines: KnockoutJS, Kendo UI MVVM and AngularJS 1.X.</Description>
2828
<PackageTags>$(PackageCommonTags);XML;Performance;Optimization;Compression</PackageTags>
29-
<PackageReleaseNotes>New Blazor markers (`&lt;!--Blazor-Server-Component-State:…--&gt;`, `&lt;!--Blazor-WebAssembly-Component-State:…--&gt;` and `&lt;!--Blazor-Web-Initializers:…--&gt;`) are no longer removed.</PackageReleaseNotes>
29+
<PackageReleaseNotes>Blazor streaming markers (`&lt;!--bl:…--&gt;`, `&lt;!--/bl:…--&gt;` and `&lt;!--bab39c12-73f9-4e04-b6b9-76cb2b324662--&gt;`) are no longer removed.</PackageReleaseNotes>
3030
</PropertyGroup>
3131

3232
<ItemGroup>

src/WebMarkupMin.Core/readme.txt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,8 @@
4646
=============
4747
RELEASE NOTES
4848
=============
49-
New Blazor markers (`<!--Blazor-Server-Component-State:…-->`,
50-
`<!--Blazor-WebAssembly-Component-State:…-->` and
51-
`<!--Blazor-Web-Initializers:…-->`) are no longer removed.
49+
Blazor streaming markers (`<!--bl:…-->`, `<!--/bl:…-->` and
50+
`<!--bab39c12-73f9-4e04-b6b9-76cb2b324662-->`) are no longer removed.
5251

5352
=============
5453
DOCUMENTATION

test/WebMarkupMin.Tests/Html/Blazor/Minification/ProcessingMarkersTests.cs

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,93 @@ public void ProcessingWebInitializerMarkers()
154154
Assert.Equal(input, output);
155155
}
156156

157+
[Fact]
158+
public void ProcessingStreamingBoundaryMarkers()
159+
{
160+
// Arrange
161+
const string input = "<main b-j65y7q72mt>\r\n" +
162+
" <article class=\"content px-4\" b-j65y7q72mt>" +
163+
"<!--bl:13--><!--bl:17--><!--bl:18--><!--/bl:18--><!--/bl:17-->\r\n\r\n" +
164+
" <h1>Weather</h1>\r\n\r\n" +
165+
" <p>This component demonstrates showing data.</p>\r\n" +
166+
" <p><em>Loading...</em></p><!--/bl:13-->\r\n" +
167+
" </article>\r\n" +
168+
"</main>"
169+
;
170+
171+
// Act
172+
string output = _removingHtmlCommentsMinifier.Minify(input).MinifiedContent;
173+
174+
// Assert
175+
Assert.Equal(input, output);
176+
}
177+
178+
[Fact]
179+
public void ProcessingStreamingFramingMarkers()
180+
{
181+
// Arrange
182+
const string input = "<!--bab39c12-73f9-4e04-b6b9-76cb2b324662--><blazor-ssr>\n" +
183+
" <template blazor-component-id=\"19\" enhanced-nav=\"true\">\n" +
184+
" <title>Weather</title>\n" +
185+
" </template>\n" +
186+
" <template blazor-component-id=\"13\" enhanced-nav=\"true\">" +
187+
"<!--bl:17--><!--bl:18--><!--/bl:18--><!--/bl:17-->\n\n" +
188+
" <h1>Weather</h1>\n\n" +
189+
" <p>This component demonstrates showing data.</p>\n" +
190+
" <table class=\"table\">\n" +
191+
" <thead>\n" +
192+
" <tr>\n" +
193+
" <th>Date</th>\n" +
194+
" <th>Temp. (C)</th>\n" +
195+
" <th>Temp. (F)</th>\n" +
196+
" <th>Summary</th>\n" +
197+
" </tr>\n" +
198+
" </thead>\n" +
199+
" <tbody>\n" +
200+
" <tr>\n" +
201+
" <td>25.06.2024</td>\n" +
202+
" <td>2</td>\n" +
203+
" <td>35</td>\n" +
204+
" <td>Warm</td>\n" +
205+
" </tr>\n" +
206+
" <tr>\n" +
207+
" <td>26.06.2024</td>\n" +
208+
" <td>26</td>\n" +
209+
" <td>78</td>\n" +
210+
" <td>Cool</td>\n" +
211+
" </tr>\n" +
212+
" <tr>\n" +
213+
" <td>27.06.2024</td>\n" +
214+
" <td>8</td>\n" +
215+
" <td>46</td>\n" +
216+
" <td>Hot</td>\n" +
217+
" </tr>\n" +
218+
" <tr>\n" +
219+
" <td>28.06.2024</td>\n" +
220+
" <td>39</td>\n" +
221+
" <td>102</td>\n" +
222+
" <td>Scorching</td>\n" +
223+
" </tr>\n" +
224+
" <tr>\n" +
225+
" <td>29.06.2024</td>\n" +
226+
" <td>46</td>\n" +
227+
" <td>114</td>\n" +
228+
" <td>Bracing</td>\n" +
229+
" </tr>\n" +
230+
" </tbody>\n" +
231+
" </table>\n" +
232+
" </template>\n" +
233+
" <blazor-ssr-end></blazor-ssr-end>\n" +
234+
"</blazor-ssr><!--bab39c12-73f9-4e04-b6b9-76cb2b324662-->"
235+
;
236+
237+
// Act
238+
string output = _removingHtmlCommentsMinifier.Minify(input).MinifiedContent;
239+
240+
// Assert
241+
Assert.Equal(input, output);
242+
}
243+
157244
#region IDisposable implementation
158245

159246
public void Dispose()

0 commit comments

Comments
 (0)