Skip to content

Commit fdabaf0

Browse files
authored
Avoid adding CSS scope to elements in HEAD (#32709)
* Avoid adding CSS scope to elements in HEAD * Set StringComparison type for comparison
1 parent 6a119cc commit fdabaf0

File tree

3 files changed

+27
-9
lines changed

3 files changed

+27
-9
lines changed

src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorView_Layout_WithCssScope.codegen.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public class TestFiles_IntegrationTests_CodeGenerationIntegrationTest_test : glo
1818
#pragma warning disable 1998
1919
public async override global::System.Threading.Tasks.Task ExecuteAsync()
2020
{
21-
WriteLiteral("\r\n<!DOCTYPE html>\r\n<html TestCssScope lang=\"en\">\r\n<head TestCssScope>\r\n <meta TestCssScope charset=\"utf-8\" />\r\n <meta TestCssScope name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\r\n <title TestCssScope>");
21+
WriteLiteral("\r\n<!DOCTYPE html>\r\n<html lang=\"en\">\r\n<head>\r\n <meta charset=\"utf-8\" />\r\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\r\n <title>");
2222
#nullable restore
2323
#line 7 "TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml"
2424
Write(ViewData["Title"]);

src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorView_Layout_WithCssScope.ir.txt

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,29 +15,24 @@ Document -
1515
LazyIntermediateToken - (0:0,0 [2] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) - Html - \n
1616
LazyIntermediateToken - (2:1,0 [17] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) - Html - <!DOCTYPE html>\n
1717
LazyIntermediateToken - (19:2,0 [5] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) - Html - <html
18-
IntermediateToken - - Html - TestCssScope
1918
LazyIntermediateToken - (24:2,5 [10] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) - Html - lang="en"
2019
LazyIntermediateToken - (34:2,15 [1] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) - Html - >
2120
LazyIntermediateToken - (35:2,16 [2] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) - Html - \n
2221
LazyIntermediateToken - (37:3,0 [5] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) - Html - <head
23-
IntermediateToken - - Html - TestCssScope
2422
LazyIntermediateToken - (42:3,5 [1] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) - Html - >
2523
LazyIntermediateToken - (43:3,6 [6] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) - Html - \n
2624
LazyIntermediateToken - (49:4,4 [5] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) - Html - <meta
27-
IntermediateToken - - Html - TestCssScope
2825
LazyIntermediateToken - (54:4,9 [16] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) - Html - charset="utf-8"
2926
LazyIntermediateToken - (70:4,25 [1] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) - Html -
3027
LazyIntermediateToken - (71:4,26 [2] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) - Html - />
3128
LazyIntermediateToken - (73:4,28 [6] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) - Html - \n
3229
LazyIntermediateToken - (79:5,4 [5] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) - Html - <meta
33-
IntermediateToken - - Html - TestCssScope
3430
LazyIntermediateToken - (84:5,9 [16] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) - Html - name="viewport"
3531
LazyIntermediateToken - (100:5,25 [48] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) - Html - content="width=device-width, initial-scale=1.0"
3632
LazyIntermediateToken - (148:5,73 [1] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) - Html -
3733
LazyIntermediateToken - (149:5,74 [2] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) - Html - />
3834
LazyIntermediateToken - (151:5,76 [6] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) - Html - \n
3935
LazyIntermediateToken - (157:6,4 [6] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) - Html - <title
40-
IntermediateToken - - Html - TestCssScope
4136
LazyIntermediateToken - (163:6,10 [1] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) - Html - >
4237
CSharpExpression - (165:6,12 [17] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml)
4338
LazyIntermediateToken - (165:6,12 [17] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) - CSharp - ViewData["Title"]

src/Razor/Microsoft.AspNetCore.Razor.Language/src/Extensions/ViewCssScopePass.cs

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,7 @@ private void ProcessElement(HtmlContentIntermediateNode node, string cssScope)
4141
var child = node.Children[i];
4242
if (child is IntermediateToken token && token.IsHtml)
4343
{
44-
var content = token.Content;
45-
var isValidToken = content.StartsWith("<", StringComparison.Ordinal) && !content.StartsWith("</", StringComparison.Ordinal) && !content.StartsWith("<!", StringComparison.Ordinal);
46-
if (isValidToken)
44+
if (IsValidElement(token))
4745
{
4846
node.Children.Insert(i + 1, new IntermediateToken()
4947
{
@@ -55,6 +53,31 @@ private void ProcessElement(HtmlContentIntermediateNode node, string cssScope)
5553
}
5654
}
5755
}
56+
57+
bool IsValidElement(IntermediateToken token)
58+
{
59+
var content = token.Content;
60+
var isValidToken = content.StartsWith("<", StringComparison.Ordinal)
61+
&& !content.StartsWith("</", StringComparison.Ordinal)
62+
&& !content.StartsWith("<!", StringComparison.Ordinal);
63+
/// <remarks>
64+
/// We want to avoid adding the CSS scope to elements that do not appear
65+
/// within the body element of the document. When this pass executes over the
66+
/// nodes, we don't have the ability to store whether we are a descandant of a
67+
/// `head` or `body` element so it is not possible to discern whether the tag
68+
/// is valid this way. Instead, we go for a straight-forward check on the tag
69+
/// name that we are currently inspecting.
70+
/// </remarks>
71+
var isInvalidTag = content.IndexOf("head", StringComparison.OrdinalIgnoreCase) >= 0
72+
|| content.IndexOf("meta", StringComparison.OrdinalIgnoreCase) >= 0
73+
|| content.IndexOf("title", StringComparison.OrdinalIgnoreCase) >= 0
74+
|| content.IndexOf("link", StringComparison.OrdinalIgnoreCase) >= 0
75+
|| content.IndexOf("base", StringComparison.OrdinalIgnoreCase) >= 0
76+
|| content.IndexOf("script", StringComparison.OrdinalIgnoreCase) >= 0
77+
|| content.IndexOf("style", StringComparison.OrdinalIgnoreCase) >= 0
78+
|| content.IndexOf("html", StringComparison.OrdinalIgnoreCase) >= 0;
79+
return isValidToken && !isInvalidTag;
80+
}
5881
}
5982
}
6083
}

0 commit comments

Comments
 (0)