Moved AddTagHelperHtmlAttribute from renderer to writer
This commit is contained in:
parent
cf44f103c1
commit
0b17f14d68
|
|
@ -216,6 +216,11 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
||||||
Context.TagHelperWriter.WriteCreateTagHelper(Context, node);
|
Context.TagHelperWriter.WriteCreateTagHelper(Context, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void VisitAddTagHelperHtmlAttribute(AddTagHelperHtmlAttributeIRNode node)
|
||||||
|
{
|
||||||
|
Context.TagHelperWriter.WriteAddTagHelperHtmlAttribute(Context, node);
|
||||||
|
}
|
||||||
|
|
||||||
public override void VisitExecuteTagHelpers(ExecuteTagHelpersIRNode node)
|
public override void VisitExecuteTagHelpers(ExecuteTagHelpersIRNode node)
|
||||||
{
|
{
|
||||||
Context.TagHelperWriter.WriteExecuteTagHelpers(Context, node);
|
Context.TagHelperWriter.WriteExecuteTagHelpers(Context, node);
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
||||||
|
|
||||||
public override void WriteAddTagHelperHtmlAttribute(CSharpRenderingContext context, AddTagHelperHtmlAttributeIRNode node)
|
public override void WriteAddTagHelperHtmlAttribute(CSharpRenderingContext context, AddTagHelperHtmlAttributeIRNode node)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
context.RenderChildren(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void WriteCreateTagHelper(CSharpRenderingContext context, CreateTagHelperIRNode node)
|
public override void WriteCreateTagHelper(CSharpRenderingContext context, CreateTagHelperIRNode node)
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,8 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
||||||
|
|
||||||
public string WriteHtmlContentMethod { get; set; } = "WriteLiteral";
|
public string WriteHtmlContentMethod { get; set; } = "WriteLiteral";
|
||||||
|
|
||||||
|
public string WriteAttributeValueMethod { get; set; } = "WriteAttributeValue";
|
||||||
|
|
||||||
public override void WriteCSharpExpression(CSharpRenderingContext context, CSharpExpressionIRNode node)
|
public override void WriteCSharpExpression(CSharpRenderingContext context, CSharpExpressionIRNode node)
|
||||||
{
|
{
|
||||||
if (context == null)
|
if (context == null)
|
||||||
|
|
|
||||||
|
|
@ -278,77 +278,6 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
||||||
.WriteEndMethodInvocation();
|
.WriteEndMethodInvocation();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void VisitAddTagHelperHtmlAttribute(AddTagHelperHtmlAttributeIRNode node)
|
|
||||||
{
|
|
||||||
var attributeValueStyleParameter = $"global::Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeValueStyle.{node.ValueStyle}";
|
|
||||||
var isConditionalAttributeValue = node.Children.Any(child => child is CSharpAttributeValueIRNode);
|
|
||||||
|
|
||||||
// All simple text and minimized attributes will be pre-allocated.
|
|
||||||
if (isConditionalAttributeValue)
|
|
||||||
{
|
|
||||||
// Dynamic attribute value should be run through the conditional attribute removal system. It's
|
|
||||||
// unbound and contains C#.
|
|
||||||
|
|
||||||
// TagHelper attribute rendering is buffered by default. We do not want to write to the current
|
|
||||||
// writer.
|
|
||||||
var valuePieceCount = node.Children.Count(
|
|
||||||
child => child is HtmlAttributeValueIRNode || child is CSharpAttributeValueIRNode);
|
|
||||||
|
|
||||||
Context.Writer
|
|
||||||
.WriteStartMethodInvocation("BeginAddHtmlAttributeValues" /* ORIGINAL: BeginAddHtmlAttributeValuesMethodName */)
|
|
||||||
.Write("__tagHelperExecutionContext" /* ORIGINAL: ExecutionContextVariableName */)
|
|
||||||
.WriteParameterSeparator()
|
|
||||||
.WriteStringLiteral(node.Name)
|
|
||||||
.WriteParameterSeparator()
|
|
||||||
.Write(valuePieceCount.ToString(CultureInfo.InvariantCulture))
|
|
||||||
.WriteParameterSeparator()
|
|
||||||
.Write(attributeValueStyleParameter)
|
|
||||||
.WriteEndMethodInvocation();
|
|
||||||
|
|
||||||
var initialRenderingConventions = Context.RenderingConventions;
|
|
||||||
Context.RenderingConventions = new TagHelperHtmlAttributeRenderingConventions(Context.Writer);
|
|
||||||
VisitDefault(node);
|
|
||||||
Context.RenderingConventions = initialRenderingConventions;
|
|
||||||
|
|
||||||
Context.Writer
|
|
||||||
.WriteMethodInvocation(
|
|
||||||
"EndAddHtmlAttributeValues" /* ORIGINAL: EndAddHtmlAttributeValuesMethodName */,
|
|
||||||
"__tagHelperExecutionContext" /* ORIGINAL: ExecutionContextVariableName */);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// This is a data-* attribute which includes C#. Do not perform the conditional attribute removal or
|
|
||||||
// other special cases used when IsDynamicAttributeValue(). But the attribute must still be buffered to
|
|
||||||
// determine its final value.
|
|
||||||
|
|
||||||
// Attribute value is not plain text, must be buffered to determine its final value.
|
|
||||||
Context.Writer.WriteMethodInvocation("BeginWriteTagHelperAttribute" /* ORIGINAL: BeginWriteTagHelperAttributeMethodName */);
|
|
||||||
|
|
||||||
// We're building a writing scope around the provided chunks which captures everything written from the
|
|
||||||
// page. Therefore, we do not want to write to any other buffer since we're using the pages buffer to
|
|
||||||
// ensure we capture all content that's written, directly or indirectly.
|
|
||||||
var initialRenderingConventions = Context.RenderingConventions;
|
|
||||||
Context.RenderingConventions = new CSharpRenderingConventions(Context.Writer);
|
|
||||||
VisitDefault(node);
|
|
||||||
Context.RenderingConventions = initialRenderingConventions;
|
|
||||||
|
|
||||||
Context.Writer
|
|
||||||
.WriteStartAssignment("__tagHelperStringValueBuffer" /* ORIGINAL: StringValueBufferVariableName */)
|
|
||||||
.WriteMethodInvocation("EndWriteTagHelperAttribute" /* ORIGINAL: EndWriteTagHelperAttributeMethodName */)
|
|
||||||
.WriteStartInstanceMethodInvocation(
|
|
||||||
"__tagHelperExecutionContext" /* ORIGINAL: ExecutionContextVariableName */,
|
|
||||||
"AddHtmlAttribute" /* ORIGINAL: ExecutionContextAddHtmlAttributeMethodName */)
|
|
||||||
.WriteStringLiteral(node.Name)
|
|
||||||
.WriteParameterSeparator()
|
|
||||||
.WriteStartMethodInvocation("Html.Raw" /* ORIGINAL: MarkAsHtmlEncodedMethodName */)
|
|
||||||
.Write("__tagHelperStringValueBuffer" /* ORIGINAL: StringValueBufferVariableName */)
|
|
||||||
.WriteEndMethodInvocation(endLine: false)
|
|
||||||
.WriteParameterSeparator()
|
|
||||||
.Write(attributeValueStyleParameter)
|
|
||||||
.WriteEndMethodInvocation();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void VisitSetPreallocatedTagHelperProperty(SetPreallocatedTagHelperPropertyIRNode node)
|
public override void VisitSetPreallocatedTagHelperProperty(SetPreallocatedTagHelperPropertyIRNode node)
|
||||||
{
|
{
|
||||||
var tagHelperVariableName = GetTagHelperVariableName(node.TagHelperTypeName);
|
var tagHelperVariableName = GetTagHelperVariableName(node.TagHelperTypeName);
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
||||||
|
|
@ -20,6 +22,8 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
||||||
|
|
||||||
public string ExecutionContextSetOutputContentAsyncMethodName { get; set; } = "SetOutputContentAsync";
|
public string ExecutionContextSetOutputContentAsyncMethodName { get; set; } = "SetOutputContentAsync";
|
||||||
|
|
||||||
|
public string ExecutionContextAddHtmlAttributeMethodName { get; set; } = "AddHtmlAttribute";
|
||||||
|
|
||||||
public string RunnerTypeName { get; set; } = "global::Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperRunner";
|
public string RunnerTypeName { get; set; } = "global::Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperRunner";
|
||||||
|
|
||||||
public string RunnerVariableName { get; set; } = "__tagHelperRunner";
|
public string RunnerVariableName { get; set; } = "__tagHelperRunner";
|
||||||
|
|
@ -44,6 +48,16 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
||||||
|
|
||||||
public string TagHelperOutputIsContentModifiedPropertyName { get; set; } = "IsContentModified";
|
public string TagHelperOutputIsContentModifiedPropertyName { get; set; } = "IsContentModified";
|
||||||
|
|
||||||
|
public string BeginAddHtmlAttributeValuesMethodName { get; set; } = "BeginAddHtmlAttributeValues";
|
||||||
|
|
||||||
|
public string EndAddHtmlAttributeValuesMethodName { get; set; } = "EndAddHtmlAttributeValues";
|
||||||
|
|
||||||
|
public string BeginWriteTagHelperAttributeMethodName { get; set; } = "BeginWriteTagHelperAttribute";
|
||||||
|
|
||||||
|
public string EndWriteTagHelperAttributeMethodName { get; set; } = "EndWriteTagHelperAttribute";
|
||||||
|
|
||||||
|
public string MarkAsHtmlEncodedMethodName { get; set; } = "Html.Raw";
|
||||||
|
|
||||||
public string WriteTagHelperOutputMethod { get; set; } = "Write";
|
public string WriteTagHelperOutputMethod { get; set; } = "Write";
|
||||||
|
|
||||||
public override void WriteDeclareTagHelperFields(CSharpRenderingContext context, DeclareTagHelperFieldsIRNode node)
|
public override void WriteDeclareTagHelperFields(CSharpRenderingContext context, DeclareTagHelperFieldsIRNode node)
|
||||||
|
|
@ -127,7 +141,82 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
||||||
|
|
||||||
public override void WriteAddTagHelperHtmlAttribute(CSharpRenderingContext context, AddTagHelperHtmlAttributeIRNode node)
|
public override void WriteAddTagHelperHtmlAttribute(CSharpRenderingContext context, AddTagHelperHtmlAttributeIRNode node)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
var attributeValueStyleParameter = $"global::Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeValueStyle.{node.ValueStyle}";
|
||||||
|
var isConditionalAttributeValue = node.Children.Any(child => child is CSharpAttributeValueIRNode);
|
||||||
|
|
||||||
|
// All simple text and minimized attributes will be pre-allocated.
|
||||||
|
if (isConditionalAttributeValue)
|
||||||
|
{
|
||||||
|
// Dynamic attribute value should be run through the conditional attribute removal system. It's
|
||||||
|
// unbound and contains C#.
|
||||||
|
|
||||||
|
// TagHelper attribute rendering is buffered by default. We do not want to write to the current
|
||||||
|
// writer.
|
||||||
|
var valuePieceCount = node.Children.Count(
|
||||||
|
child => child is HtmlAttributeValueIRNode || child is CSharpAttributeValueIRNode);
|
||||||
|
|
||||||
|
context.Writer
|
||||||
|
.WriteStartMethodInvocation(BeginAddHtmlAttributeValuesMethodName)
|
||||||
|
.Write(ExecutionContextVariableName)
|
||||||
|
.WriteParameterSeparator()
|
||||||
|
.WriteStringLiteral(node.Name)
|
||||||
|
.WriteParameterSeparator()
|
||||||
|
.Write(valuePieceCount.ToString(CultureInfo.InvariantCulture))
|
||||||
|
.WriteParameterSeparator()
|
||||||
|
.Write(attributeValueStyleParameter)
|
||||||
|
.WriteEndMethodInvocation();
|
||||||
|
|
||||||
|
// This can be removed once all the tag helper nodes are moved out of the renderers.
|
||||||
|
var initialRenderingConventions = context.RenderingConventions;
|
||||||
|
context.RenderingConventions = new TagHelperHtmlAttributeRenderingConventions(context.Writer);
|
||||||
|
using (context.Push(new TagHelperHtmlAttributeRuntimeBasicWriter()))
|
||||||
|
{
|
||||||
|
context.RenderChildren(node);
|
||||||
|
}
|
||||||
|
context.RenderingConventions = initialRenderingConventions;
|
||||||
|
|
||||||
|
context.Writer
|
||||||
|
.WriteMethodInvocation(
|
||||||
|
EndAddHtmlAttributeValuesMethodName,
|
||||||
|
ExecutionContextVariableName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// This is a data-* attribute which includes C#. Do not perform the conditional attribute removal or
|
||||||
|
// other special cases used when IsDynamicAttributeValue(). But the attribute must still be buffered to
|
||||||
|
// determine its final value.
|
||||||
|
|
||||||
|
// Attribute value is not plain text, must be buffered to determine its final value.
|
||||||
|
context.Writer.WriteMethodInvocation(BeginWriteTagHelperAttributeMethodName);
|
||||||
|
|
||||||
|
// We're building a writing scope around the provided chunks which captures everything written from the
|
||||||
|
// page. Therefore, we do not want to write to any other buffer since we're using the pages buffer to
|
||||||
|
// ensure we capture all content that's written, directly or indirectly.
|
||||||
|
// This can be removed once all the tag helper nodes are moved out of the renderers.
|
||||||
|
var initialRenderingConventions = context.RenderingConventions;
|
||||||
|
context.RenderingConventions = new CSharpRenderingConventions(context.Writer);
|
||||||
|
using (context.Push(new RuntimeBasicWriter()))
|
||||||
|
using (context.Push(new RuntimeTagHelperWriter()))
|
||||||
|
{
|
||||||
|
context.RenderChildren(node);
|
||||||
|
}
|
||||||
|
context.RenderingConventions = initialRenderingConventions;
|
||||||
|
|
||||||
|
context.Writer
|
||||||
|
.WriteStartAssignment(StringValueBufferVariableName)
|
||||||
|
.WriteMethodInvocation(EndWriteTagHelperAttributeMethodName)
|
||||||
|
.WriteStartInstanceMethodInvocation(
|
||||||
|
ExecutionContextVariableName,
|
||||||
|
ExecutionContextAddHtmlAttributeMethodName)
|
||||||
|
.WriteStringLiteral(node.Name)
|
||||||
|
.WriteParameterSeparator()
|
||||||
|
.WriteStartMethodInvocation(MarkAsHtmlEncodedMethodName)
|
||||||
|
.Write(StringValueBufferVariableName)
|
||||||
|
.WriteEndMethodInvocation(endLine: false)
|
||||||
|
.WriteParameterSeparator()
|
||||||
|
.Write(attributeValueStyleParameter)
|
||||||
|
.WriteEndMethodInvocation();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void WriteCreateTagHelper(CSharpRenderingContext context, CreateTagHelperIRNode node)
|
public override void WriteCreateTagHelper(CSharpRenderingContext context, CreateTagHelperIRNode node)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
||||||
|
{
|
||||||
|
internal class TagHelperHtmlAttributeRuntimeBasicWriter : RuntimeBasicWriter
|
||||||
|
{
|
||||||
|
// This will be used when HtmlAttributeValueIRNode and CSharpAttributeValueIRNode are moved to writers.
|
||||||
|
public new string WriteAttributeValueMethod { get; set; } = "AddHtmlAttributeValue";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
|
|
@ -180,5 +183,203 @@ __tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||||
csharp,
|
csharp,
|
||||||
ignoreLineEndingDifferences: true);
|
ignoreLineEndingDifferences: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void WriteAddTagHelperHtmlAttribute_RendersCorrectly()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var writer = new RuntimeTagHelperWriter();
|
||||||
|
var options = RazorParserOptions.CreateDefaultOptions();
|
||||||
|
var codeWriter = new Legacy.CSharpCodeWriter();
|
||||||
|
var context = new CSharpRenderingContext()
|
||||||
|
{
|
||||||
|
Writer = codeWriter,
|
||||||
|
Options = options,
|
||||||
|
BasicWriter = new RuntimeBasicWriter(),
|
||||||
|
TagHelperWriter = writer,
|
||||||
|
RenderChildren = n =>
|
||||||
|
{
|
||||||
|
codeWriter.WriteLine("Render Children");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var descriptors = new[]
|
||||||
|
{
|
||||||
|
CreateTagHelperDescriptor(
|
||||||
|
tagName: "input",
|
||||||
|
typeName: "InputTagHelper",
|
||||||
|
assemblyName: "TestAssembly")
|
||||||
|
};
|
||||||
|
var engine = RazorEngine.Create(builder => builder.AddTagHelpers(descriptors));
|
||||||
|
var content = @"
|
||||||
|
@addTagHelper *, TestAssembly
|
||||||
|
<input name=""value"" />";
|
||||||
|
var sourceDocument = TestRazorSourceDocument.Create(content);
|
||||||
|
var codeDocument = RazorCodeDocument.Create(sourceDocument);
|
||||||
|
var irDocument = Lower(codeDocument, engine);
|
||||||
|
var node = irDocument.Children.Last().Children[2] as AddTagHelperHtmlAttributeIRNode;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
writer.WriteAddTagHelperHtmlAttribute(context, node);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
var csharp = context.Writer.Builder.ToString();
|
||||||
|
Assert.Equal(
|
||||||
|
@"BeginWriteTagHelperAttribute();
|
||||||
|
Render Children
|
||||||
|
__tagHelperStringValueBuffer = EndWriteTagHelperAttribute();
|
||||||
|
__tagHelperExecutionContext.AddHtmlAttribute(""name"", Html.Raw(__tagHelperStringValueBuffer), global::Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeValueStyle.DoubleQuotes);
|
||||||
|
",
|
||||||
|
csharp,
|
||||||
|
ignoreLineEndingDifferences: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void WriteAddTagHelperHtmlAttribute_DataAttribute_RendersCorrectly()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var writer = new RuntimeTagHelperWriter();
|
||||||
|
var options = RazorParserOptions.CreateDefaultOptions();
|
||||||
|
var codeWriter = new Legacy.CSharpCodeWriter();
|
||||||
|
var context = new CSharpRenderingContext()
|
||||||
|
{
|
||||||
|
Writer = codeWriter,
|
||||||
|
Options = options,
|
||||||
|
BasicWriter = new RuntimeBasicWriter(),
|
||||||
|
TagHelperWriter = writer,
|
||||||
|
RenderChildren = n =>
|
||||||
|
{
|
||||||
|
codeWriter.WriteLine("Render Children");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var descriptors = new[]
|
||||||
|
{
|
||||||
|
CreateTagHelperDescriptor(
|
||||||
|
tagName: "input",
|
||||||
|
typeName: "InputTagHelper",
|
||||||
|
assemblyName: "TestAssembly")
|
||||||
|
};
|
||||||
|
var engine = RazorEngine.Create(builder => builder.AddTagHelpers(descriptors));
|
||||||
|
var content = @"
|
||||||
|
@addTagHelper *, TestAssembly
|
||||||
|
<input data-test=""Blah-@Foo"" />";
|
||||||
|
var sourceDocument = TestRazorSourceDocument.Create(content);
|
||||||
|
var codeDocument = RazorCodeDocument.Create(sourceDocument);
|
||||||
|
var irDocument = Lower(codeDocument, engine);
|
||||||
|
var node = irDocument.Children.Last().Children[2] as AddTagHelperHtmlAttributeIRNode;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
writer.WriteAddTagHelperHtmlAttribute(context, node);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
var csharp = context.Writer.Builder.ToString();
|
||||||
|
Assert.Equal(
|
||||||
|
@"BeginWriteTagHelperAttribute();
|
||||||
|
Render Children
|
||||||
|
__tagHelperStringValueBuffer = EndWriteTagHelperAttribute();
|
||||||
|
__tagHelperExecutionContext.AddHtmlAttribute(""data-test"", Html.Raw(__tagHelperStringValueBuffer), global::Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeValueStyle.DoubleQuotes);
|
||||||
|
",
|
||||||
|
csharp,
|
||||||
|
ignoreLineEndingDifferences: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void WriteAddTagHelperHtmlAttribute_DynamicAttribute_RendersCorrectly()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var writer = new RuntimeTagHelperWriter();
|
||||||
|
var options = RazorParserOptions.CreateDefaultOptions();
|
||||||
|
var codeWriter = new Legacy.CSharpCodeWriter();
|
||||||
|
var context = new CSharpRenderingContext()
|
||||||
|
{
|
||||||
|
Writer = codeWriter,
|
||||||
|
Options = options,
|
||||||
|
BasicWriter = new RuntimeBasicWriter(),
|
||||||
|
TagHelperWriter = writer,
|
||||||
|
RenderChildren = n =>
|
||||||
|
{
|
||||||
|
codeWriter.WriteLine("Render Children");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var descriptors = new[]
|
||||||
|
{
|
||||||
|
CreateTagHelperDescriptor(
|
||||||
|
tagName: "input",
|
||||||
|
typeName: "InputTagHelper",
|
||||||
|
assemblyName: "TestAssembly")
|
||||||
|
};
|
||||||
|
var engine = RazorEngine.Create(builder => builder.AddTagHelpers(descriptors));
|
||||||
|
var content = @"
|
||||||
|
@addTagHelper *, TestAssembly
|
||||||
|
<input test=""Blah-@Foo"" />";
|
||||||
|
var sourceDocument = TestRazorSourceDocument.Create(content);
|
||||||
|
var codeDocument = RazorCodeDocument.Create(sourceDocument);
|
||||||
|
var irDocument = Lower(codeDocument, engine);
|
||||||
|
var node = irDocument.Children.Last().Children[2] as AddTagHelperHtmlAttributeIRNode;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
writer.WriteAddTagHelperHtmlAttribute(context, node);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
var csharp = context.Writer.Builder.ToString();
|
||||||
|
Assert.Equal(
|
||||||
|
@"BeginAddHtmlAttributeValues(__tagHelperExecutionContext, ""test"", 2, global::Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeValueStyle.DoubleQuotes);
|
||||||
|
Render Children
|
||||||
|
EndAddHtmlAttributeValues(__tagHelperExecutionContext);
|
||||||
|
",
|
||||||
|
csharp,
|
||||||
|
ignoreLineEndingDifferences: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DocumentIRNode Lower(RazorCodeDocument codeDocument)
|
||||||
|
{
|
||||||
|
var engine = RazorEngine.Create();
|
||||||
|
|
||||||
|
return Lower(codeDocument, engine);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DocumentIRNode Lower(RazorCodeDocument codeDocument, RazorEngine engine)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < engine.Phases.Count; i++)
|
||||||
|
{
|
||||||
|
var phase = engine.Phases[i];
|
||||||
|
phase.Execute(codeDocument);
|
||||||
|
|
||||||
|
if (phase is IRazorIRLoweringPhase)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var irDocument = codeDocument.GetIRDocument();
|
||||||
|
Assert.NotNull(irDocument);
|
||||||
|
|
||||||
|
return irDocument;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static TagHelperDescriptor CreateTagHelperDescriptor(
|
||||||
|
string tagName,
|
||||||
|
string typeName,
|
||||||
|
string assemblyName,
|
||||||
|
IEnumerable<Action<ITagHelperBoundAttributeDescriptorBuilder>> attributes = null)
|
||||||
|
{
|
||||||
|
var builder = TagHelperDescriptorBuilder.Create(typeName, assemblyName);
|
||||||
|
|
||||||
|
if (attributes != null)
|
||||||
|
{
|
||||||
|
foreach (var attributeBuilder in attributes)
|
||||||
|
{
|
||||||
|
builder.BindAttribute(attributeBuilder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.TagMatchingRule(ruleBuilder => ruleBuilder.RequireTagName(tagName));
|
||||||
|
|
||||||
|
var descriptor = builder.Build();
|
||||||
|
|
||||||
|
return descriptor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue