In RazorCompiler, support self-closing and void elements
This commit is contained in:
parent
a64ece0319
commit
1c1fd69bf2
|
|
@ -8,6 +8,7 @@ using Microsoft.AspNetCore.Razor.Language.CodeGeneration;
|
|||
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
||||
using Microsoft.Blazor.RenderTree;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
|
|
@ -20,6 +21,13 @@ namespace Microsoft.Blazor.Build.Core.RazorCompilation.Engine
|
|||
{
|
||||
private const string builderVarName = "builder";
|
||||
|
||||
// Per the HTML spec, the following elements are inherently self-closing
|
||||
// For example, <img> is the same as <img /> (and therefore it cannot contain descendants)
|
||||
private static HashSet<string> htmlVoidElementsLookup
|
||||
= new HashSet<string>(
|
||||
new[] { "area", "base", "br", "col", "embed", "hr", "img", "input", "link", "meta", "param", "source", "track", "wbr" },
|
||||
StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
public override void BeginWriterScope(CodeRenderingContext context, string writer)
|
||||
{
|
||||
throw new System.NotImplementedException(nameof(BeginWriterScope));
|
||||
|
|
@ -119,26 +127,37 @@ namespace Microsoft.Blazor.Build.Core.RazorCompilation.Engine
|
|||
switch (nextToken.Type)
|
||||
{
|
||||
case HtmlTokenType.Character:
|
||||
// Text node
|
||||
context.CodeWriter
|
||||
.WriteStartMethodInvocation($"{builderVarName}.{nameof(RenderTreeBuilder.AddText)}")
|
||||
.WriteStringLiteral(nextToken.Data)
|
||||
.WriteEndMethodInvocation();
|
||||
break;
|
||||
{
|
||||
// Text node
|
||||
context.CodeWriter
|
||||
.WriteStartMethodInvocation($"{builderVarName}.{nameof(RenderTreeBuilder.AddText)}")
|
||||
.WriteStringLiteral(nextToken.Data)
|
||||
.WriteEndMethodInvocation();
|
||||
break;
|
||||
}
|
||||
|
||||
case HtmlTokenType.StartTag:
|
||||
var nextTag = nextToken.AsTag();
|
||||
context.CodeWriter
|
||||
.WriteStartMethodInvocation($"{builderVarName}.{nameof(RenderTreeBuilder.OpenElement)}")
|
||||
.WriteStringLiteral(nextTag.Data)
|
||||
.WriteEndMethodInvocation();
|
||||
break;
|
||||
|
||||
case HtmlTokenType.EndTag:
|
||||
context.CodeWriter
|
||||
.WriteStartMethodInvocation($"{builderVarName}.{nameof(RenderTreeBuilder.CloseElement)}")
|
||||
.WriteEndMethodInvocation();
|
||||
break;
|
||||
{
|
||||
var nextTag = nextToken.AsTag();
|
||||
if (nextToken.Type == HtmlTokenType.StartTag)
|
||||
{
|
||||
context.CodeWriter
|
||||
.WriteStartMethodInvocation($"{builderVarName}.{nameof(RenderTreeBuilder.OpenElement)}")
|
||||
.WriteStringLiteral(nextTag.Data)
|
||||
.WriteEndMethodInvocation();
|
||||
}
|
||||
|
||||
if (nextToken.Type == HtmlTokenType.EndTag
|
||||
|| nextTag.IsSelfClosing
|
||||
|| htmlVoidElementsLookup.Contains(nextTag.Data))
|
||||
{
|
||||
context.CodeWriter
|
||||
.WriteStartMethodInvocation($"{builderVarName}.{nameof(RenderTreeBuilder.CloseElement)}")
|
||||
.WriteEndMethodInvocation();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
throw new InvalidCastException($"Unsupported token type: {nextToken.Type.ToString()}");
|
||||
|
|
|
|||
|
|
@ -128,12 +128,35 @@ namespace Microsoft.Blazor.Build.Test
|
|||
var component = CompileToComponent("<myelem>Hello</myelem>");
|
||||
|
||||
// Assert
|
||||
var nodes = GetRenderTree(component).Where(NotWhitespace);
|
||||
Assert.Collection(nodes,
|
||||
Assert.Collection(GetRenderTree(component),
|
||||
node => AssertNode.Element(node, "myelem", 1),
|
||||
node => AssertNode.Text(node, "Hello"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanRenderSelfClosingElements()
|
||||
{
|
||||
// Arrange/Act
|
||||
var component = CompileToComponent("Some text so elem isn't at position 0 <myelem />");
|
||||
|
||||
// Assert
|
||||
Assert.Collection(GetRenderTree(component),
|
||||
node => AssertNode.Text(node, "Some text so elem isn't at position 0 "),
|
||||
node => AssertNode.Element(node, "myelem", 1));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanRenderVoidHtmlElements()
|
||||
{
|
||||
// Arrange/Act
|
||||
var component = CompileToComponent("Some text so elem isn't at position 0 <img>");
|
||||
|
||||
// Assert
|
||||
Assert.Collection(GetRenderTree(component),
|
||||
node => AssertNode.Text(node, "Some text so elem isn't at position 0 "),
|
||||
node => AssertNode.Element(node, "img", 1));
|
||||
}
|
||||
|
||||
private static bool NotWhitespace(RenderTreeNode node)
|
||||
=> node.NodeType != RenderTreeNodeType.Text
|
||||
|| !string.IsNullOrWhiteSpace(node.TextContent);
|
||||
|
|
|
|||
Loading…
Reference in New Issue