From c58df0b7399e6f3f3016ccf9265dda8ef3d6ec1a Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Mon, 19 Mar 2018 11:14:12 +0000 Subject: [PATCH] Temporary workaround for #219 ("data-" attributes don't compile) --- .../BlazorRuntimeNodeWriter.cs | 9 +++ .../RenderingRazorIntegrationTest.cs | 73 +++++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/src/Microsoft.AspNetCore.Blazor.Razor.Extensions/BlazorRuntimeNodeWriter.cs b/src/Microsoft.AspNetCore.Blazor.Razor.Extensions/BlazorRuntimeNodeWriter.cs index b1de0647cd..4dcae0feba 100644 --- a/src/Microsoft.AspNetCore.Blazor.Razor.Extensions/BlazorRuntimeNodeWriter.cs +++ b/src/Microsoft.AspNetCore.Blazor.Razor.Extensions/BlazorRuntimeNodeWriter.cs @@ -543,6 +543,15 @@ namespace Microsoft.AspNetCore.Blazor.Razor public override void BeginWriteAttribute(CodeWriter codeWriter, string key) { + // Temporary workaround for https://github.com/aspnet/Blazor/issues/219 + // Remove this logic once the underlying HTML parsing issue is fixed, + // as we don't really want special cases like this. + const string dataUnderscore = "data_"; + if (key.StartsWith(dataUnderscore, StringComparison.Ordinal)) + { + key = "data-" + key.Substring(dataUnderscore.Length); + } + codeWriter .WriteStartMethodInvocation($"{_scopeStack.BuilderVarName}.{nameof(BlazorApi.RenderTreeBuilder.AddAttribute)}") .Write((_sourceSequence++).ToString()) diff --git a/test/Microsoft.AspNetCore.Blazor.Build.Test/RenderingRazorIntegrationTest.cs b/test/Microsoft.AspNetCore.Blazor.Build.Test/RenderingRazorIntegrationTest.cs index 942d83e312..c0c6b1b263 100644 --- a/test/Microsoft.AspNetCore.Blazor.Build.Test/RenderingRazorIntegrationTest.cs +++ b/test/Microsoft.AspNetCore.Blazor.Build.Test/RenderingRazorIntegrationTest.cs @@ -180,6 +180,79 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test frame => AssertFrame.Attribute(frame, "attr", "Hello, WORLD with number 246!", 1)); } + [Fact] + public void SupportsHyphenedAttributesWithCSharpExpressionValues() + { + // Arrange/Act + var component = CompileToComponent( + "@{ var myValue = \"My string\"; }" + + ""); + + // Assert + Assert.Collection(GetRenderTree(component), + frame => AssertFrame.Element(frame, "elem", 2, 0), + frame => AssertFrame.Attribute(frame, "abc-def", "My string", 1)); + } + + [Fact] + public void SupportsDataDashAttributesWithLiteralValues() + { + // Arrange/Act + var component = CompileToComponent( + ""); + + // Assert + Assert.Collection(GetRenderTree(component), + frame => AssertFrame.Element(frame, "elem", 2, 0), + frame => AssertFrame.Attribute(frame, "data-abc", "Hello", 1)); + } + + [Fact(Skip = "Currently broken due to #219. TODO: Once the issue is fixed, re-enable this test, remove the test below, and remove the implementation of its workaround.")] + public void SupportsDataDashAttributesWithCSharpExpressionValues() + { + // Arrange/Act + var component = CompileToComponent( + "@{ var myValue = \"My string\"; }" + + ""); + + // Assert + Assert.Collection(GetRenderTree(component), + frame => AssertFrame.Element(frame, "elem", 2, 0), + frame => AssertFrame.Attribute(frame, "data-abc", "My string", 1)); + } + + [Fact] + public void TemporaryWorkaround_ConvertsDataUnderscoreAttributesToDataDash() + { + // This is a temporary workaround for https://github.com/aspnet/Blazor/issues/219 + // + // Currently Razor's HtmlMarkupParser looks for data-* attributes and handles + // them differently: https://github.com/aspnet/Razor/blob/dev/src/Microsoft.AspNetCore.Razor.Language/Legacy/HtmlMarkupParser.cs#L934 + // This is because Razor was historically used only on the server, and there's + // an argument that data-* shouldn't support conditional server-side rendering + // because of its HTML semantics. The result is that information about data-* + // attributes isn't retained in the IR - all we get there is literal HTML + // markup, which the Blazor code writer can't do anything useful with. + // + // The real solution would be to disable the parser's "data-*" special case + // for Blazor. We don't yet have a mechanism for disabling it, so as a short + // term workaround, we support data_* as an alternative syntax that renders + // as data-* in the DOM. + // + // This workaround (the automatic conversion of data_* to data-*) will be removed + // as soon as the underlying HTML parsing issue is resolved. + + // Arrange/Act + var component = CompileToComponent( + "@{ var myValue = \"My string\"; }" + + ""); + + // Assert + Assert.Collection(GetRenderTree(component), + frame => AssertFrame.Element(frame, "elem", 2, 0), + frame => AssertFrame.Attribute(frame, "data-abc", "My string", 1)); + } + [Fact] public void SupportsAttributesWithEventHandlerValues() {