In RazorCompiler, support components with children
This commit is contained in:
parent
d67bf63864
commit
95023c0300
|
|
@ -220,17 +220,17 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
||||||
case HtmlTokenType.EndTag:
|
case HtmlTokenType.EndTag:
|
||||||
{
|
{
|
||||||
var nextTag = nextToken.AsTag();
|
var nextTag = nextToken.AsTag();
|
||||||
var isComponent = false;
|
var tagNameOriginalCase = GetTagNameWithOriginalCase(originalHtmlContent, nextTag);
|
||||||
|
var isComponent = TryGetComponentTypeNameFromTagName(tagNameOriginalCase, out var componentTypeName);
|
||||||
|
|
||||||
if (nextToken.Type == HtmlTokenType.StartTag)
|
if (nextToken.Type == HtmlTokenType.StartTag)
|
||||||
{
|
{
|
||||||
var tagNameOriginalCase = GetTagNameWithOriginalCase(originalHtmlContent, nextTag);
|
if (isComponent)
|
||||||
if (TryGetComponentTypeNameFromTagName(tagNameOriginalCase, out var componentTypeName))
|
|
||||||
{
|
{
|
||||||
codeWriter
|
codeWriter
|
||||||
.WriteStartMethodInvocation($"{builderVarName}.{nameof(RenderTreeBuilder.OpenComponent)}<{componentTypeName}>")
|
.WriteStartMethodInvocation($"{builderVarName}.{nameof(RenderTreeBuilder.OpenComponent)}<{componentTypeName}>")
|
||||||
.Write((_sourceSequence++).ToString())
|
.Write((_sourceSequence++).ToString())
|
||||||
.WriteEndMethodInvocation();
|
.WriteEndMethodInvocation();
|
||||||
isComponent = true;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -304,7 +304,10 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetTagNameWithOriginalCase(string document, HtmlTagToken tagToken)
|
private static string GetTagNameWithOriginalCase(string document, HtmlTagToken tagToken)
|
||||||
=> document.Substring(tagToken.Position.Position, tagToken.Name.Length);
|
{
|
||||||
|
var offset = tagToken.Type == HtmlTokenType.EndTag ? 1 : 0; // For end tags, skip the '/'
|
||||||
|
return document.Substring(tagToken.Position.Position + offset, tagToken.Name.Length);
|
||||||
|
}
|
||||||
|
|
||||||
private bool TryGetComponentTypeNameFromTagName(string tagName, out string componentTypeName)
|
private bool TryGetComponentTypeNameFromTagName(string tagName, out string componentTypeName)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -371,7 +371,7 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Collection(frames,
|
Assert.Collection(frames,
|
||||||
frame => AssertFrame.Component<TestComponent>(frame, 0));
|
frame => AssertFrame.Component<TestComponent>(frame, 1, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -398,7 +398,7 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test
|
||||||
// This problem will probably go away on its own when we have new component
|
// This problem will probably go away on its own when we have new component
|
||||||
// tooling.
|
// tooling.
|
||||||
Assert.Collection(frames,
|
Assert.Collection(frames,
|
||||||
frame => AssertFrame.Component<TestComponent>(frame, 0),
|
frame => AssertFrame.Component<TestComponent>(frame, 4, 0),
|
||||||
frame => AssertFrame.Attribute(frame, "intproperty", "123", 1),
|
frame => AssertFrame.Attribute(frame, "intproperty", "123", 1),
|
||||||
frame => AssertFrame.Attribute(frame, "stringproperty", "My string", 2),
|
frame => AssertFrame.Attribute(frame, "stringproperty", "My string", 2),
|
||||||
frame =>
|
frame =>
|
||||||
|
|
@ -408,6 +408,26 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CanIncludeChildrenInComponents()
|
||||||
|
{
|
||||||
|
// Arrange/Act
|
||||||
|
var testComponentTypeName = typeof(TestComponent).FullName.Replace('+', '.');
|
||||||
|
var component = CompileToComponent($"<c:{testComponentTypeName} attr=\"abc\">" +
|
||||||
|
$"Some text" +
|
||||||
|
$"<some-child a='1'>Nested text</some-child>" +
|
||||||
|
$"</c:{testComponentTypeName}>");
|
||||||
|
var frames = GetRenderTree(component);
|
||||||
|
|
||||||
|
Assert.Collection(frames,
|
||||||
|
frame => AssertFrame.Component<TestComponent>(frame, 6, 0),
|
||||||
|
frame => AssertFrame.Attribute(frame, "attr", "abc", 1),
|
||||||
|
frame => AssertFrame.Text(frame, "Some text", 2),
|
||||||
|
frame => AssertFrame.Element(frame, "some-child", 3, 3),
|
||||||
|
frame => AssertFrame.Attribute(frame, "a", "1", 4),
|
||||||
|
frame => AssertFrame.Text(frame, "Nested text", 5));
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void ComponentsDoNotHaveLayoutAttributeByDefault()
|
public void ComponentsDoNotHaveLayoutAttributeByDefault()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -739,8 +739,8 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
Assert.Equal(1, entry.ReferenceFrameIndex);
|
Assert.Equal(1, entry.ReferenceFrameIndex);
|
||||||
},
|
},
|
||||||
entry => AssertEdit(entry, RenderTreeEditType.StepOut, 0));
|
entry => AssertEdit(entry, RenderTreeEditType.StepOut, 0));
|
||||||
AssertFrame.ComponentWithInstance<FakeComponent>(renderBatch.ReferenceFrames.Array[0], 0, 12);
|
AssertFrame.ComponentWithInstance<FakeComponent>(renderBatch.ReferenceFrames.Array[0], 0, null, 12);
|
||||||
AssertFrame.ComponentWithInstance<FakeComponent2>(renderBatch.ReferenceFrames.Array[1], 1, 13);
|
AssertFrame.ComponentWithInstance<FakeComponent2>(renderBatch.ReferenceFrames.Array[1], 1, null, 13);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
|
||||||
|
|
@ -58,16 +58,20 @@ namespace Microsoft.AspNetCore.Blazor.Test.Helpers
|
||||||
Assert.Equal(attributeValue, frame.AttributeValue);
|
Assert.Equal(attributeValue, frame.AttributeValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Component<T>(RenderTreeFrame frame, int? sequence = null) where T : IComponent
|
public static void Component<T>(RenderTreeFrame frame, int? subtreeLength = null, int? sequence = null) where T : IComponent
|
||||||
{
|
{
|
||||||
Assert.Equal(RenderTreeFrameType.Component, frame.FrameType);
|
Assert.Equal(RenderTreeFrameType.Component, frame.FrameType);
|
||||||
Assert.Equal(typeof(T), frame.ComponentType);
|
Assert.Equal(typeof(T), frame.ComponentType);
|
||||||
|
if (subtreeLength.HasValue)
|
||||||
|
{
|
||||||
|
Assert.Equal(subtreeLength.Value, frame.ComponentSubtreeLength);
|
||||||
|
}
|
||||||
AssertFrame.Sequence(frame, sequence);
|
AssertFrame.Sequence(frame, sequence);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ComponentWithInstance<T>(RenderTreeFrame frame, int componentId, int? sequence = null) where T : IComponent
|
public static void ComponentWithInstance<T>(RenderTreeFrame frame, int componentId, int? subtreeLength = null, int? sequence = null) where T : IComponent
|
||||||
{
|
{
|
||||||
AssertFrame.Component<T>(frame, sequence);
|
AssertFrame.Component<T>(frame, subtreeLength, sequence);
|
||||||
Assert.IsType<T>(frame.Component);
|
Assert.IsType<T>(frame.Component);
|
||||||
Assert.Equal(componentId, frame.ComponentId);
|
Assert.Equal(componentId, frame.ComponentId);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue