From fbe950b5ed8f9a69038095a3c0fe5f9154fa1acb Mon Sep 17 00:00:00 2001 From: Safia Abdalla Date: Fri, 14 May 2021 16:07:57 -0700 Subject: [PATCH 1/3] Avoid adding CSS scope to elements in HEAD --- .../RazorView_Layout_WithCssScope.codegen.cs | 2 +- .../RazorView_Layout_WithCssScope.ir.txt | 5 ---- .../src/Extensions/ViewCssScopePass.cs | 29 +++++++++++++++++-- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorView_Layout_WithCssScope.codegen.cs b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorView_Layout_WithCssScope.codegen.cs index 282f05793985..488d55f68690 100644 --- a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorView_Layout_WithCssScope.codegen.cs +++ b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorView_Layout_WithCssScope.codegen.cs @@ -18,7 +18,7 @@ public class TestFiles_IntegrationTests_CodeGenerationIntegrationTest_test : glo #pragma warning disable 1998 public async override global::System.Threading.Tasks.Task ExecuteAsync() { - WriteLiteral("\r\n\r\n\r\n\r\n \r\n \r\n "); + 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>"); #nullable restore #line 7 "TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml" Write(ViewData["Title"]); diff --git a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorView_Layout_WithCssScope.ir.txt b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorView_Layout_WithCssScope.ir.txt index c7db330e79b4..258748bf6e49 100644 --- a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorView_Layout_WithCssScope.ir.txt +++ b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorView_Layout_WithCssScope.ir.txt @@ -15,29 +15,24 @@ Document - LazyIntermediateToken - (0:0,0 [2] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) - Html - \n LazyIntermediateToken - (2:1,0 [17] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) - Html - <!DOCTYPE html>\n LazyIntermediateToken - (19:2,0 [5] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) - Html - <html - IntermediateToken - - Html - TestCssScope LazyIntermediateToken - (24:2,5 [10] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) - Html - lang="en" LazyIntermediateToken - (34:2,15 [1] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) - Html - > LazyIntermediateToken - (35:2,16 [2] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) - Html - \n LazyIntermediateToken - (37:3,0 [5] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) - Html - <head - IntermediateToken - - Html - TestCssScope LazyIntermediateToken - (42:3,5 [1] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) - Html - > LazyIntermediateToken - (43:3,6 [6] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) - Html - \n LazyIntermediateToken - (49:4,4 [5] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) - Html - <meta - IntermediateToken - - Html - TestCssScope LazyIntermediateToken - (54:4,9 [16] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) - Html - charset="utf-8" LazyIntermediateToken - (70:4,25 [1] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) - Html - LazyIntermediateToken - (71:4,26 [2] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) - Html - /> LazyIntermediateToken - (73:4,28 [6] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) - Html - \n LazyIntermediateToken - (79:5,4 [5] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) - Html - <meta - IntermediateToken - - Html - TestCssScope LazyIntermediateToken - (84:5,9 [16] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) - Html - name="viewport" LazyIntermediateToken - (100:5,25 [48] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) - Html - content="width=device-width, initial-scale=1.0" LazyIntermediateToken - (148:5,73 [1] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) - Html - LazyIntermediateToken - (149:5,74 [2] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) - Html - /> LazyIntermediateToken - (151:5,76 [6] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) - Html - \n LazyIntermediateToken - (157:6,4 [6] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) - Html - <title - IntermediateToken - - Html - TestCssScope LazyIntermediateToken - (163:6,10 [1] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) - Html - > CSharpExpression - (165:6,12 [17] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) LazyIntermediateToken - (165:6,12 [17] TestFiles\IntegrationTests\CodeGenerationIntegrationTest\test.cshtml) - CSharp - ViewData["Title"] diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Extensions/ViewCssScopePass.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Extensions/ViewCssScopePass.cs index ae20b386c243..3dd0fc24f521 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Extensions/ViewCssScopePass.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Extensions/ViewCssScopePass.cs @@ -41,9 +41,7 @@ private void ProcessElement(HtmlContentIntermediateNode node, string cssScope) var child = node.Children[i]; if (child is IntermediateToken token && token.IsHtml) { - var content = token.Content; - var isValidToken = content.StartsWith("<", StringComparison.Ordinal) && !content.StartsWith("</", StringComparison.Ordinal) && !content.StartsWith("<!", StringComparison.Ordinal); - if (isValidToken) + if (IsValidElement(token)) { node.Children.Insert(i + 1, new IntermediateToken() { @@ -55,6 +53,31 @@ private void ProcessElement(HtmlContentIntermediateNode node, string cssScope) } } } + + bool IsValidElement(IntermediateToken token) + { + var content = token.Content; + var isValidToken = content.StartsWith("<", StringComparison.Ordinal) + && !content.StartsWith("</", StringComparison.Ordinal) + && !content.StartsWith("<!", StringComparison.Ordinal); + /// <remarks> + /// We want to avoid adding the CSS scope to elements that do not appear + /// within the body element of the document. When this pass executes over the + /// nodes, we don't have the ability to store whether we are a descandant of a + /// `head` or `body` element so it is not possible to discern whether the tag + /// is valid this way. Instead, we go for a straight-forward check on the tag + /// name that we are currently inspecting. + /// </remarks> + var isInvalidTag = content.Contains("head") + || content.Contains("meta") + || content.Contains("title") + || content.Contains("link") + || content.Contains("base") + || content.Contains("script") + || content.Contains("style") + || content.Contains("html"); + return isValidToken && !isInvalidTag; + } } } } From 46975d61c4c4dc02114a6c7914b50a1a1ae6d472 Mon Sep 17 00:00:00 2001 From: Safia Abdalla <safia@microsoft.com> Date: Sat, 15 May 2021 11:18:14 -0700 Subject: [PATCH 2/3] Set StringComparison type for comparison --- .../src/Extensions/ViewCssScopePass.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Extensions/ViewCssScopePass.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Extensions/ViewCssScopePass.cs index 3dd0fc24f521..d3af0f5ae8c7 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Extensions/ViewCssScopePass.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Extensions/ViewCssScopePass.cs @@ -68,14 +68,14 @@ bool IsValidElement(IntermediateToken token) /// is valid this way. Instead, we go for a straight-forward check on the tag /// name that we are currently inspecting. /// </remarks> - var isInvalidTag = content.Contains("head") - || content.Contains("meta") - || content.Contains("title") - || content.Contains("link") - || content.Contains("base") - || content.Contains("script") - || content.Contains("style") - || content.Contains("html"); + var isInvalidTag = content.Contains("head", StringComparison.OrdinalIgnoreCase) + || content.Contains("meta", StringComparison.OrdinalIgnoreCase) + || content.Contains("title", StringComparison.OrdinalIgnoreCase) + || content.Contains("link", StringComparison.OrdinalIgnoreCase) + || content.Contains("base", StringComparison.OrdinalIgnoreCase) + || content.Contains("script", StringComparison.OrdinalIgnoreCase) + || content.Contains("style", StringComparison.OrdinalIgnoreCase) + || content.Contains("html", StringComparison.OrdinalIgnoreCase); return isValidToken && !isInvalidTag; } } From dcbb552f13975cbb71220b7b3e33fd4b8fe0c6bf Mon Sep 17 00:00:00 2001 From: Safia Abdalla <safia@safia.rocks> Date: Sun, 16 May 2021 19:21:00 -0700 Subject: [PATCH 3/3] Update contains check --- .../src/Extensions/ViewCssScopePass.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Extensions/ViewCssScopePass.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Extensions/ViewCssScopePass.cs index d3af0f5ae8c7..23dd233a3100 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Extensions/ViewCssScopePass.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Extensions/ViewCssScopePass.cs @@ -68,14 +68,14 @@ bool IsValidElement(IntermediateToken token) /// is valid this way. Instead, we go for a straight-forward check on the tag /// name that we are currently inspecting. /// </remarks> - var isInvalidTag = content.Contains("head", StringComparison.OrdinalIgnoreCase) - || content.Contains("meta", StringComparison.OrdinalIgnoreCase) - || content.Contains("title", StringComparison.OrdinalIgnoreCase) - || content.Contains("link", StringComparison.OrdinalIgnoreCase) - || content.Contains("base", StringComparison.OrdinalIgnoreCase) - || content.Contains("script", StringComparison.OrdinalIgnoreCase) - || content.Contains("style", StringComparison.OrdinalIgnoreCase) - || content.Contains("html", StringComparison.OrdinalIgnoreCase); + var isInvalidTag = content.IndexOf("head", StringComparison.OrdinalIgnoreCase) >= 0 + || content.IndexOf("meta", StringComparison.OrdinalIgnoreCase) >= 0 + || content.IndexOf("title", StringComparison.OrdinalIgnoreCase) >= 0 + || content.IndexOf("link", StringComparison.OrdinalIgnoreCase) >= 0 + || content.IndexOf("base", StringComparison.OrdinalIgnoreCase) >= 0 + || content.IndexOf("script", StringComparison.OrdinalIgnoreCase) >= 0 + || content.IndexOf("style", StringComparison.OrdinalIgnoreCase) >= 0 + || content.IndexOf("html", StringComparison.OrdinalIgnoreCase) >= 0; return isValidToken && !isInvalidTag; } }