Allow invalid HTML to be in Razor pages.
- Modified the TagHelperParseTreeRewriter to not remove invalid HTML snippets. - Added tests to validate invalid HTML is allowed. #212
This commit is contained in:
parent
39accef1ad
commit
8d4bdbdb84
|
|
@ -56,8 +56,10 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
|
||||||
// Get tag name of the current block (doesn't matter if it's an end or start tag)
|
// Get tag name of the current block (doesn't matter if it's an end or start tag)
|
||||||
var tagName = GetTagName(childBlock);
|
var tagName = GetTagName(childBlock);
|
||||||
|
|
||||||
|
// Could not determine tag name, it can't be a TagHelper, continue on and track the element.
|
||||||
if (tagName == null)
|
if (tagName == null)
|
||||||
{
|
{
|
||||||
|
_currentBlock.Children.Add(child);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -224,9 +226,14 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
|
||||||
}
|
}
|
||||||
|
|
||||||
var childSpan = (Span)child;
|
var childSpan = (Span)child;
|
||||||
var textSymbol = childSpan.Symbols.FirstHtmlSymbolAs(HtmlSymbolType.Text);
|
var textSymbol = childSpan.Symbols.FirstHtmlSymbolAs(HtmlSymbolType.WhiteSpace | HtmlSymbolType.Text);
|
||||||
|
|
||||||
return textSymbol != null ? textSymbol.Content : null;
|
if (textSymbol == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return textSymbol.Type == HtmlSymbolType.WhiteSpace ? null : textSymbol.Content;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsSelfClosing(Block beginTagBlock)
|
private static bool IsSelfClosing(Block beginTagBlock)
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,11 @@
|
||||||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
// Copyright (c) Microsoft Open Technologies, Inc. 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;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Razor.Tokenizer.Symbols
|
namespace Microsoft.AspNet.Razor.Tokenizer.Symbols
|
||||||
{
|
{
|
||||||
|
[Flags]
|
||||||
public enum HtmlSymbolType
|
public enum HtmlSymbolType
|
||||||
{
|
{
|
||||||
Unknown,
|
Unknown,
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ namespace Microsoft.AspNet.Razor.Tokenizer.Symbols
|
||||||
/// <returns>The first <see cref="HtmlSymbol"/> of type <paramref name="type"/>.</returns>
|
/// <returns>The first <see cref="HtmlSymbol"/> of type <paramref name="type"/>.</returns>
|
||||||
public static HtmlSymbol FirstHtmlSymbolAs(this IEnumerable<ISymbol> symbols, HtmlSymbolType type)
|
public static HtmlSymbol FirstHtmlSymbolAs(this IEnumerable<ISymbol> symbols, HtmlSymbolType type)
|
||||||
{
|
{
|
||||||
return symbols.OfType<HtmlSymbol>().FirstOrDefault(sym => sym.Type == type);
|
return symbols.OfType<HtmlSymbol>().FirstOrDefault(sym => (type & sym.Type) == sym.Type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -92,6 +92,7 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[MemberData(nameof(IncompleteHelperBlockData))]
|
[MemberData(nameof(IncompleteHelperBlockData))]
|
||||||
public void TagHelperParseTreeRewriter_CreatesErrorForIncompleteTagHelper(
|
public void TagHelperParseTreeRewriter_CreatesErrorForIncompleteTagHelper(
|
||||||
|
|
@ -102,6 +103,128 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
||||||
RunParseTreeRewriterTest(documentContent, expectedOutput, new[] { expectedError }, "strong", "p");
|
RunParseTreeRewriterTest(documentContent, expectedOutput, new[] { expectedError }, "strong", "p");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static TheoryData<string, MarkupBlock> InvalidHtmlBlockData
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var factory = CreateDefaultSpanFactory();
|
||||||
|
var blockFactory = new BlockFactory(factory);
|
||||||
|
var dateTimeNow = new ExpressionBlock(
|
||||||
|
factory.CodeTransition(),
|
||||||
|
factory.Code("DateTime.Now")
|
||||||
|
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||||
|
.Accepts(AcceptedCharacters.NonWhiteSpace));
|
||||||
|
|
||||||
|
return new TheoryData<string, MarkupBlock>
|
||||||
|
{
|
||||||
|
{
|
||||||
|
"<<<p>>></p>",
|
||||||
|
new MarkupBlock(
|
||||||
|
blockFactory.MarkupTagBlock("<"),
|
||||||
|
blockFactory.MarkupTagBlock("<"),
|
||||||
|
new MarkupTagHelperBlock("p",
|
||||||
|
factory.Markup(">>")))
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<<p />",
|
||||||
|
new MarkupBlock(
|
||||||
|
blockFactory.MarkupTagBlock("<"),
|
||||||
|
new MarkupTagHelperBlock("p"))
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"< p />",
|
||||||
|
new MarkupBlock(
|
||||||
|
blockFactory.MarkupTagBlock("< p />"))
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<input <p />",
|
||||||
|
new MarkupBlock(
|
||||||
|
blockFactory.MarkupTagBlock("<input "),
|
||||||
|
new MarkupTagHelperBlock("p"))
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"< class=\"foo\" <p />",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagBlock(
|
||||||
|
factory.Markup("<"),
|
||||||
|
new MarkupBlock(
|
||||||
|
new AttributeBlockCodeGenerator(
|
||||||
|
name: "class",
|
||||||
|
prefix: new LocationTagged<string>(" class=\"", 1, 0, 1),
|
||||||
|
suffix: new LocationTagged<string>("\"", 12, 0, 12)),
|
||||||
|
factory.Markup(" class=\"").With(SpanCodeGenerator.Null),
|
||||||
|
factory.Markup("foo").With(new LiteralAttributeCodeGenerator(
|
||||||
|
prefix: new LocationTagged<string>(string.Empty, 9, 0, 9),
|
||||||
|
value: new LocationTagged<string>("foo", 9, 0, 9))),
|
||||||
|
factory.Markup("\"").With(SpanCodeGenerator.Null)),
|
||||||
|
factory.Markup(" ")),
|
||||||
|
new MarkupTagHelperBlock("p"))
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"</<<p>/></p>>",
|
||||||
|
new MarkupBlock(
|
||||||
|
blockFactory.MarkupTagBlock("</"),
|
||||||
|
blockFactory.MarkupTagBlock("<"),
|
||||||
|
new MarkupTagHelperBlock("p",
|
||||||
|
factory.Markup("/>")),
|
||||||
|
factory.Markup(">"))
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"</<<p>/><strong></p>>",
|
||||||
|
new MarkupBlock(
|
||||||
|
blockFactory.MarkupTagBlock("</"),
|
||||||
|
blockFactory.MarkupTagBlock("<"),
|
||||||
|
new MarkupTagHelperBlock("p",
|
||||||
|
factory.Markup("/>"),
|
||||||
|
blockFactory.MarkupTagBlock("<strong>")),
|
||||||
|
factory.Markup(">"))
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"</<<p>@DateTime.Now/><strong></p>>",
|
||||||
|
new MarkupBlock(
|
||||||
|
blockFactory.MarkupTagBlock("</"),
|
||||||
|
blockFactory.MarkupTagBlock("<"),
|
||||||
|
new MarkupTagHelperBlock("p",
|
||||||
|
dateTimeNow,
|
||||||
|
factory.Markup("/>"),
|
||||||
|
blockFactory.MarkupTagBlock("<strong>")),
|
||||||
|
factory.Markup(">"))
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"</ /< ><p>@DateTime.Now / ><strong></p></ >",
|
||||||
|
new MarkupBlock(
|
||||||
|
blockFactory.MarkupTagBlock("</ "),
|
||||||
|
factory.Markup("/"),
|
||||||
|
blockFactory.MarkupTagBlock("< >"),
|
||||||
|
new MarkupTagHelperBlock("p",
|
||||||
|
dateTimeNow,
|
||||||
|
factory.Markup(" / >"),
|
||||||
|
blockFactory.MarkupTagBlock("<strong>")),
|
||||||
|
blockFactory.MarkupTagBlock("</ >"))
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<p>< @DateTime.Now ></ @DateTime.Now ></p>",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock("p",
|
||||||
|
new MarkupTagBlock(
|
||||||
|
factory.Markup("< "),
|
||||||
|
dateTimeNow,
|
||||||
|
factory.Markup(" >")),
|
||||||
|
blockFactory.MarkupTagBlock("</ "),
|
||||||
|
dateTimeNow,
|
||||||
|
factory.Markup(" >")))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(InvalidHtmlBlockData))]
|
||||||
|
public void TagHelperParseTreeRewriter_AllowsInvalidHtml(string documentContent, MarkupBlock expectedOutput)
|
||||||
|
{
|
||||||
|
RunParseTreeRewriterTest(documentContent, expectedOutput, "p");
|
||||||
|
}
|
||||||
|
|
||||||
public static IEnumerable<object[]> TextTagsBlockData
|
public static IEnumerable<object[]> TextTagsBlockData
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue