Extra newline no longer rendered at the end of a code block
- #485 - Using a flag to consume whitespace and newline at the end of a verbatim block - Added tests to validate nested blocks
This commit is contained in:
parent
493e5521b8
commit
e2881b0eca
|
|
@ -316,12 +316,16 @@ namespace Microsoft.AspNet.Razor.Parser
|
|||
Span.ChunkGenerator = SpanChunkGenerator.Null;
|
||||
}
|
||||
|
||||
if (!At(CSharpSymbolType.WhiteSpace) && !At(CSharpSymbolType.NewLine))
|
||||
if (!IsNested)
|
||||
{
|
||||
PutCurrentBack();
|
||||
EnsureCurrent();
|
||||
if (At(CSharpSymbolType.NewLine) ||
|
||||
(At(CSharpSymbolType.WhiteSpace) && NextIs(CSharpSymbolType.NewLine)))
|
||||
{
|
||||
Context.NullGenerateWhitespaceAndNewLine = true;
|
||||
}
|
||||
}
|
||||
|
||||
CompleteBlock(insertMarkerIfNecessary: false);
|
||||
Output(SpanKind.MetaCode);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -71,7 +71,19 @@ namespace Microsoft.AspNet.Razor.Parser
|
|||
var startOfLine = false;
|
||||
while (!EndOfFile && !condition(CurrentSymbol))
|
||||
{
|
||||
if (At(HtmlSymbolType.NewLine))
|
||||
if (Context.NullGenerateWhitespaceAndNewLine)
|
||||
{
|
||||
Context.NullGenerateWhitespaceAndNewLine = false;
|
||||
Span.ChunkGenerator = SpanChunkGenerator.Null;
|
||||
AcceptWhile(symbol => symbol.Type == HtmlSymbolType.WhiteSpace);
|
||||
if (At(HtmlSymbolType.NewLine))
|
||||
{
|
||||
AcceptAndMoveNext();
|
||||
}
|
||||
|
||||
Output(SpanKind.Markup);
|
||||
}
|
||||
else if (At(HtmlSymbolType.NewLine))
|
||||
{
|
||||
if (last != null)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -67,6 +67,8 @@ namespace Microsoft.AspNet.Razor.Parser
|
|||
public Span LastSpan { get; private set; }
|
||||
public bool WhiteSpaceIsSignificantToAncestorBlock { get; set; }
|
||||
|
||||
public bool NullGenerateWhitespaceAndNewLine { get; set; }
|
||||
|
||||
public AcceptedCharacters LastAcceptedCharacters
|
||||
{
|
||||
get
|
||||
|
|
|
|||
|
|
@ -290,6 +290,134 @@ namespace Microsoft.AspNet.Razor.Test.Parser.Html
|
|||
BlockFactory.MarkupTagBlock("</script>")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseDocumentDoesNotRenderExtraNewLineAtTheEndOfVerbatimBlock()
|
||||
{
|
||||
ParseDocumentTest("@{\r\n}\r\n<html>",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\r\n").AsStatement().AutoCompleteWith(null, false),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||
Factory.Markup("\r\n").With(SpanChunkGenerator.Null),
|
||||
BlockFactory.MarkupTagBlock("<html>")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseDocumentDoesNotRenderExtraWhitespaceAndNewLineAtTheEndOfVerbatimBlock()
|
||||
{
|
||||
ParseDocumentTest("@{\r\n} \t\r\n<html>",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\r\n").AsStatement().AutoCompleteWith(null, false),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||
Factory.Markup(" \t\r\n").With(SpanChunkGenerator.Null),
|
||||
BlockFactory.MarkupTagBlock("<html>")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseDocumentDoesNotIgnoreNewLineAtTheEndOfMarkupBlock()
|
||||
{
|
||||
ParseDocumentTest("@{\r\n}\r\n<html>\r\n",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\r\n").AsStatement().AutoCompleteWith(null, false),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||
Factory.Markup("\r\n").With(SpanChunkGenerator.Null),
|
||||
BlockFactory.MarkupTagBlock("<html>"),
|
||||
Factory.Markup("\r\n")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseDocumentDoesNotIgnoreWhitespaceAtTheEndOfVerbatimBlockIfNoNewlinePresent()
|
||||
{
|
||||
ParseDocumentTest("@{\r\n} \t<html>\r\n",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\r\n").AsStatement().AutoCompleteWith(null, false),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||
Factory.Markup(" \t"),
|
||||
BlockFactory.MarkupTagBlock("<html>"),
|
||||
Factory.Markup("\r\n")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseDocumentHandlesNewLineInNestedBlock()
|
||||
{
|
||||
ParseDocumentTest("@{\r\n@if(true){\r\n} \r\n}\r\n<html>",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\r\n").AsStatement().AutoCompleteWith(null, false),
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("if(true){\r\n}").AsStatement()),
|
||||
Factory.Code(" \r\n").AsStatement(),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||
Factory.Markup("\r\n").With(SpanChunkGenerator.Null),
|
||||
BlockFactory.MarkupTagBlock("<html>")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseDocumentHandlesNewLineAndMarkupInNestedBlock()
|
||||
{
|
||||
ParseDocumentTest("@{\r\n@if(true){\r\n} <input> }",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\r\n").AsStatement().AutoCompleteWith(null, false),
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("if(true){\r\n}").AsStatement()),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" "),
|
||||
new MarkupTagBlock(
|
||||
Factory.Markup("<input>").Accepts(AcceptedCharacters.None)),
|
||||
Factory.Markup(" ").Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyCSharp().AsStatement(),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseDocumentHandlesExtraNewLineBeforeMarkupInNestedBlock()
|
||||
{
|
||||
ParseDocumentTest("@{\r\n@if(true){\r\n} \r\n<input> \r\n}<html>",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\r\n").AsStatement().AutoCompleteWith(null, false),
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("if(true){\r\n}").AsStatement()),
|
||||
Factory.Code(" \r\n").AsStatement(),
|
||||
new MarkupBlock(
|
||||
new MarkupTagBlock(
|
||||
Factory.Markup("<input>").Accepts(AcceptedCharacters.None)),
|
||||
Factory.Markup(" \r\n").Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyCSharp().AsStatement(),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||
new MarkupTagBlock(
|
||||
Factory.Markup("<html>"))));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseSectionIgnoresTagsInContentsOfScriptTag()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ namespace TestOutput
|
|||
#line default
|
||||
#line hidden
|
||||
|
||||
Instrumentation.BeginContext(21, 4, true);
|
||||
WriteLiteral("\r\n\r\n");
|
||||
Instrumentation.BeginContext(23, 2, true);
|
||||
WriteLiteral("\r\n");
|
||||
Instrumentation.EndContext();
|
||||
#line 5 "Blocks.cshtml"
|
||||
while(i <= 10) {
|
||||
|
|
|
|||
|
|
@ -57,9 +57,6 @@ namespace TestOutput
|
|||
#line default
|
||||
#line hidden
|
||||
|
||||
Instrumentation.BeginContext(83, 2, true);
|
||||
WriteLiteral("\r\n");
|
||||
Instrumentation.EndContext();
|
||||
}
|
||||
#pragma warning restore 1998
|
||||
}
|
||||
|
|
|
|||
|
|
@ -265,8 +265,8 @@ if(true) {
|
|||
#line default
|
||||
#line hidden
|
||||
|
||||
Instrumentation.BeginContext(805, 14, true);
|
||||
WriteLiteral("\r\n ");
|
||||
Instrumentation.BeginContext(807, 12, true);
|
||||
WriteLiteral(" ");
|
||||
Instrumentation.EndContext();
|
||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input", TagMode.StartTagOnly, "test", async() => {
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@ namespace TestOutput
|
|||
#line default
|
||||
#line hidden
|
||||
|
||||
Instrumentation.BeginContext(54, 4, true);
|
||||
WriteLiteral("\r\n\r\n");
|
||||
Instrumentation.BeginContext(56, 2, true);
|
||||
WriteLiteral("\r\n");
|
||||
Instrumentation.EndContext();
|
||||
#line 6 "ExpressionsInCode.cshtml"
|
||||
if(foo != null) {
|
||||
|
|
|
|||
|
|
@ -42,8 +42,8 @@ namespace TestOutput
|
|||
#line default
|
||||
#line hidden
|
||||
|
||||
Instrumentation.BeginContext(94, 4, true);
|
||||
WriteLiteral("\r\n\r\n");
|
||||
Instrumentation.BeginContext(96, 2, true);
|
||||
WriteLiteral("\r\n");
|
||||
Instrumentation.EndContext();
|
||||
#line 8 "Instrumented.cshtml"
|
||||
while(i <= 10) {
|
||||
|
|
|
|||
|
|
@ -40,9 +40,6 @@ namespace TestOutput
|
|||
#line default
|
||||
#line hidden
|
||||
|
||||
Instrumentation.BeginContext(96, 2, true);
|
||||
WriteLiteral("\r\n");
|
||||
Instrumentation.EndContext();
|
||||
}
|
||||
#pragma warning restore 1998
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ namespace TestOutput
|
|||
#line default
|
||||
#line hidden
|
||||
|
||||
Instrumentation.BeginContext(21, 4, true);
|
||||
WriteLiteral("\r\n\r\n");
|
||||
Instrumentation.BeginContext(23, 2, true);
|
||||
WriteLiteral("\r\n");
|
||||
Instrumentation.EndContext();
|
||||
#line 5 ""
|
||||
while(i <= 10) {
|
||||
|
|
|
|||
|
|
@ -76,8 +76,8 @@ Write(ViewBag?.Method(Value?[23]?.More)?["key"]);
|
|||
#line default
|
||||
#line hidden
|
||||
|
||||
Instrumentation.BeginContext(135, 4, true);
|
||||
WriteLiteral("\r\n\r\n");
|
||||
Instrumentation.BeginContext(137, 2, true);
|
||||
WriteLiteral("\r\n");
|
||||
Instrumentation.EndContext();
|
||||
Instrumentation.BeginContext(140, 13, false);
|
||||
#line 8 "NullConditionalExpressions.cshtml"
|
||||
|
|
|
|||
|
|
@ -43,8 +43,8 @@ namespace TestOutput
|
|||
#line default
|
||||
#line hidden
|
||||
|
||||
Instrumentation.BeginContext(280, 51, true);
|
||||
WriteLiteral("\r\n\r\n<div class=\"randomNonTagHelperAttribute\">\r\n ");
|
||||
Instrumentation.BeginContext(282, 49, true);
|
||||
WriteLiteral("\r\n<div class=\"randomNonTagHelperAttribute\">\r\n ");
|
||||
Instrumentation.EndContext();
|
||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input", TagMode.SelfClosing, "test", async() => {
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,8 +43,8 @@ namespace TestOutput
|
|||
#line default
|
||||
#line hidden
|
||||
|
||||
Instrumentation.BeginContext(280, 51, true);
|
||||
WriteLiteral("\r\n\r\n<div class=\"randomNonTagHelperAttribute\">\r\n ");
|
||||
Instrumentation.BeginContext(282, 49, true);
|
||||
WriteLiteral("\r\n<div class=\"randomNonTagHelperAttribute\">\r\n ");
|
||||
Instrumentation.EndContext();
|
||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input", TagMode.SelfClosing, "test", async() => {
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,8 +40,8 @@ namespace TestOutput
|
|||
#line default
|
||||
#line hidden
|
||||
|
||||
Instrumentation.BeginContext(232, 4, true);
|
||||
WriteLiteral("\r\n\r\n");
|
||||
Instrumentation.BeginContext(234, 2, true);
|
||||
WriteLiteral("\r\n");
|
||||
Instrumentation.EndContext();
|
||||
#line 12 "RazorComments.cshtml"
|
||||
var bar = "@* bar *@";
|
||||
|
|
@ -49,8 +49,8 @@ namespace TestOutput
|
|||
#line default
|
||||
#line hidden
|
||||
|
||||
Instrumentation.BeginContext(263, 46, true);
|
||||
WriteLiteral("\r\n<p>But this should show the comment syntax: ");
|
||||
Instrumentation.BeginContext(265, 44, true);
|
||||
WriteLiteral("<p>But this should show the comment syntax: ");
|
||||
Instrumentation.EndContext();
|
||||
Instrumentation.BeginContext(310, 3, false);
|
||||
#line 13 "RazorComments.cshtml"
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ namespace TestOutput
|
|||
#line default
|
||||
#line hidden
|
||||
|
||||
Instrumentation.BeginContext(47, 33, true);
|
||||
WriteLiteral("\r\n\r\n<div>This is in the Body>\r\n\r\n");
|
||||
Instrumentation.BeginContext(49, 31, true);
|
||||
WriteLiteral("\r\n<div>This is in the Body>\r\n\r\n");
|
||||
Instrumentation.EndContext();
|
||||
DefineSection("Section2", async(__razor_template_writer) => {
|
||||
Instrumentation.BeginContext(99, 39, true);
|
||||
|
|
|
|||
|
|
@ -35,8 +35,8 @@ namespace TestOutput
|
|||
#line default
|
||||
#line hidden
|
||||
|
||||
Instrumentation.BeginContext(69, 4, true);
|
||||
WriteLiteral("\r\n\r\n");
|
||||
Instrumentation.BeginContext(71, 2, true);
|
||||
WriteLiteral("\r\n");
|
||||
Instrumentation.EndContext();
|
||||
DefineSection("MySection", async(__razor_template_writer) => {
|
||||
Instrumentation.BeginContext(93, 21, true);
|
||||
|
|
|
|||
|
|
@ -72,8 +72,8 @@ Write(foo(""));
|
|||
#line default
|
||||
#line hidden
|
||||
|
||||
Instrumentation.BeginContext(367, 10, true);
|
||||
WriteLiteral("\r\n\r\n<ul>\r\n");
|
||||
Instrumentation.BeginContext(369, 8, true);
|
||||
WriteLiteral("\r\n<ul>\r\n");
|
||||
Instrumentation.EndContext();
|
||||
Instrumentation.BeginContext(379, 11, false);
|
||||
#line 17 "Templates.cshtml"
|
||||
|
|
@ -156,8 +156,8 @@ WriteTo(__razor_template_writer, item);
|
|||
#line default
|
||||
#line hidden
|
||||
|
||||
Instrumentation.BeginContext(574, 79, true);
|
||||
WriteLiteralTo(__razor_template_writer, "\r\n <ul>\r\n <li>Child Items... ?</li>\r\n </ul>\r\n </li>");
|
||||
Instrumentation.BeginContext(576, 77, true);
|
||||
WriteLiteralTo(__razor_template_writer, " <ul>\r\n <li>Child Items... ?</li>\r\n </ul>\r\n </li>");
|
||||
Instrumentation.EndContext();
|
||||
}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -32,8 +32,8 @@ namespace TestOutput
|
|||
#line default
|
||||
#line hidden
|
||||
|
||||
Instrumentation.BeginContext(95, 4, true);
|
||||
WriteLiteral("\r\n\r\n");
|
||||
Instrumentation.BeginContext(97, 2, true);
|
||||
WriteLiteral("\r\n");
|
||||
Instrumentation.EndContext();
|
||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("p", TagMode.StartTagAndEndTag, "test", async() => {
|
||||
Instrumentation.BeginContext(128, 11, true);
|
||||
|
|
|
|||
Loading…
Reference in New Issue