diff --git a/src/Microsoft.AspNet.Razor/Parser/HtmlMarkupParser.cs b/src/Microsoft.AspNet.Razor/Parser/HtmlMarkupParser.cs index 5486d3d4e8..8da02adc94 100644 --- a/src/Microsoft.AspNet.Razor/Parser/HtmlMarkupParser.cs +++ b/src/Microsoft.AspNet.Razor/Parser/HtmlMarkupParser.cs @@ -134,12 +134,35 @@ namespace Microsoft.AspNet.Razor.Parser { if (last != null) { + // Don't render the whitespace between the start of the line and the razor comment. + if (startOfLine && last.Type == HtmlSymbolType.WhiteSpace) + { + AddMarkerSymbolIfNecessary(); + // Output the symbols that may have been accepted prior to the whitespace. + Output(SpanKind.Markup); + + Span.ChunkGenerator = SpanChunkGenerator.Null; + } + Accept(last); last = null; } + AddMarkerSymbolIfNecessary(); Output(SpanKind.Markup); + RazorComment(); + + // Handle the whitespace and newline at the end of a razor comment. + if (startOfLine && + (At(HtmlSymbolType.NewLine) || + (At(HtmlSymbolType.WhiteSpace) && NextIs(HtmlSymbolType.NewLine)))) + { + AcceptWhile(IsSpacingToken(includeNewLines: false)); + AcceptAndMoveNext(); + Span.ChunkGenerator = SpanChunkGenerator.Null; + Output(SpanKind.Markup); + } } else { diff --git a/test/Microsoft.AspNet.Razor.Test/Parser/CSharp/CSharpRazorCommentsTest.cs b/test/Microsoft.AspNet.Razor.Test/Parser/CSharp/CSharpRazorCommentsTest.cs index b89b61c3dc..a49e5077a3 100644 --- a/test/Microsoft.AspNet.Razor.Test/Parser/CSharp/CSharpRazorCommentsTest.cs +++ b/test/Microsoft.AspNet.Razor.Test/Parser/CSharp/CSharpRazorCommentsTest.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using Microsoft.AspNet.Razor.Chunks.Generators; using Microsoft.AspNet.Razor.Parser; using Microsoft.AspNet.Razor.Parser.SyntaxTree; using Microsoft.AspNet.Razor.Test.Framework; @@ -128,7 +129,8 @@ namespace Microsoft.AspNet.Razor.Test.Parser.CSharp new MarkupBlock( new MarkupTagBlock( Factory.MarkupTransition("" + Environment.NewLine + + "@**@" + Environment.NewLine + + "

", + new MarkupBlock( + new MarkupTagBlock( + Factory.Markup("

")), + Factory.Markup(Environment.NewLine), + new CommentBlock( + Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition) + .Accepts(AcceptedCharacters.None), + Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar) + .Accepts(AcceptedCharacters.None), + Factory.Span(SpanKind.Comment, new HtmlSymbol( + Factory.LocationTracker.CurrentLocation, + string.Empty, + HtmlSymbolType.Unknown)) + .Accepts(AcceptedCharacters.Any), + Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar) + .Accepts(AcceptedCharacters.None), + Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition) + .Accepts(AcceptedCharacters.None)), + Factory.Markup(Environment.NewLine).With(SpanChunkGenerator.Null), + new MarkupTagBlock( + Factory.Markup("

")) + )); + } + + [Fact] + public void MultipleRazorCommentInMarkup() + { + ParseDocumentTest( + "

" + Environment.NewLine + + " @**@ " + Environment.NewLine + + "@**@" + Environment.NewLine + + "

", + new MarkupBlock( + new MarkupTagBlock( + Factory.Markup("

")), + Factory.Markup(Environment.NewLine), + Factory.Markup(" ").With(SpanChunkGenerator.Null), + new CommentBlock( + Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition) + .Accepts(AcceptedCharacters.None), + Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar) + .Accepts(AcceptedCharacters.None), + Factory.Span(SpanKind.Comment, new HtmlSymbol( + Factory.LocationTracker.CurrentLocation, + string.Empty, + HtmlSymbolType.Unknown)) + .Accepts(AcceptedCharacters.Any), + Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar) + .Accepts(AcceptedCharacters.None), + Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition) + .Accepts(AcceptedCharacters.None)), + Factory.Markup(" " + Environment.NewLine).With(SpanChunkGenerator.Null), + new CommentBlock( + Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition) + .Accepts(AcceptedCharacters.None), + Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar) + .Accepts(AcceptedCharacters.None), + Factory.Span(SpanKind.Comment, new HtmlSymbol( + Factory.LocationTracker.CurrentLocation, + string.Empty, + HtmlSymbolType.Unknown)) + .Accepts(AcceptedCharacters.Any), + Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar) + .Accepts(AcceptedCharacters.None), + Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition) + .Accepts(AcceptedCharacters.None)), + Factory.Markup(Environment.NewLine).With(SpanChunkGenerator.Null), + new MarkupTagBlock( + Factory.Markup("

")) + )); + } + + [Fact] + public void MultipleRazorCommentsInSameLineInMarkup() + { + ParseDocumentTest( + "

" + Environment.NewLine + + "@**@ @**@" + Environment.NewLine + + "

", + new MarkupBlock( + new MarkupTagBlock( + Factory.Markup("

")), + Factory.Markup(Environment.NewLine), + new CommentBlock( + Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition) + .Accepts(AcceptedCharacters.None), + Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar) + .Accepts(AcceptedCharacters.None), + Factory.Span(SpanKind.Comment, new HtmlSymbol( + Factory.LocationTracker.CurrentLocation, + string.Empty, + HtmlSymbolType.Unknown)) + .Accepts(AcceptedCharacters.Any), + Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar) + .Accepts(AcceptedCharacters.None), + Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition) + .Accepts(AcceptedCharacters.None)), + Factory.EmptyHtml(), + Factory.Markup(" ").With(SpanChunkGenerator.Null), + new CommentBlock( + Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition) + .Accepts(AcceptedCharacters.None), + Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar) + .Accepts(AcceptedCharacters.None), + Factory.Span(SpanKind.Comment, new HtmlSymbol( + Factory.LocationTracker.CurrentLocation, + string.Empty, + HtmlSymbolType.Unknown)) + .Accepts(AcceptedCharacters.Any), + Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar) + .Accepts(AcceptedCharacters.None), + Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition) + .Accepts(AcceptedCharacters.None)), + Factory.Markup(Environment.NewLine).With(SpanChunkGenerator.Null), + new MarkupTagBlock( + Factory.Markup("

")) + )); + } + + [Fact] + public void RazorCommentsSurroundingMarkup() + { + ParseDocumentTest( + "

" + Environment.NewLine + + "@* hello *@ content @* world *@" + Environment.NewLine + + "

", + new MarkupBlock( + new MarkupTagBlock( + Factory.Markup("

")), + Factory.Markup(Environment.NewLine), + new CommentBlock( + Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition) + .Accepts(AcceptedCharacters.None), + Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar) + .Accepts(AcceptedCharacters.None), + Factory.Span(SpanKind.Comment, new HtmlSymbol( + Factory.LocationTracker.CurrentLocation, + " hello ", + HtmlSymbolType.RazorComment)) + .Accepts(AcceptedCharacters.Any), + Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar) + .Accepts(AcceptedCharacters.None), + Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition) + .Accepts(AcceptedCharacters.None)), + Factory.Markup(" content "), + new CommentBlock( + Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition) + .Accepts(AcceptedCharacters.None), + Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar) + .Accepts(AcceptedCharacters.None), + Factory.Span(SpanKind.Comment, new HtmlSymbol( + Factory.LocationTracker.CurrentLocation, + " world ", + HtmlSymbolType.RazorComment)) + .Accepts(AcceptedCharacters.Any), + Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar) + .Accepts(AcceptedCharacters.None), + Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition) + .Accepts(AcceptedCharacters.None)), + Factory.Markup(Environment.NewLine), + new MarkupTagBlock( + Factory.Markup("

")) + )); + } + + [Fact] + public void RazorCommentWithExtraNewLineInMarkup() + { + ParseDocumentTest( + "

" + Environment.NewLine + Environment.NewLine + + "@* content *@" + Environment.NewLine + + "@*" + Environment.NewLine + + "content" + Environment.NewLine + + "*@" + Environment.NewLine + Environment.NewLine + + "

", + new MarkupBlock( + new MarkupTagBlock( + Factory.Markup("

")), + Factory.Markup(Environment.NewLine + Environment.NewLine), + new CommentBlock( + Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition) + .Accepts(AcceptedCharacters.None), + Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar) + .Accepts(AcceptedCharacters.None), + Factory.Span(SpanKind.Comment, new HtmlSymbol( + Factory.LocationTracker.CurrentLocation, + " content ", + HtmlSymbolType.RazorComment)) + .Accepts(AcceptedCharacters.Any), + Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar) + .Accepts(AcceptedCharacters.None), + Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition) + .Accepts(AcceptedCharacters.None)), + Factory.Markup(Environment.NewLine).With(SpanChunkGenerator.Null), + new CommentBlock( + Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition) + .Accepts(AcceptedCharacters.None), + Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar) + .Accepts(AcceptedCharacters.None), + Factory.Span(SpanKind.Comment, new HtmlSymbol( + Factory.LocationTracker.CurrentLocation, + Environment.NewLine + "content" + Environment.NewLine, + HtmlSymbolType.RazorComment)) + .Accepts(AcceptedCharacters.Any), + Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar) + .Accepts(AcceptedCharacters.None), + Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition) + .Accepts(AcceptedCharacters.None)), + Factory.Markup(Environment.NewLine).With(SpanChunkGenerator.Null), + Factory.Markup(Environment.NewLine), + new MarkupTagBlock( + Factory.Markup("

")) + )); + } } } diff --git a/test/Microsoft.AspNet.Razor.Test/TestFiles/CodeGenerator/Output/Templates.cs b/test/Microsoft.AspNet.Razor.Test/TestFiles/CodeGenerator/Output/Templates.cs index 78243fcdb8..73437adf9d 100644 --- a/test/Microsoft.AspNet.Razor.Test/TestFiles/CodeGenerator/Output/Templates.cs +++ b/test/Microsoft.AspNet.Razor.Test/TestFiles/CodeGenerator/Output/Templates.cs @@ -156,9 +156,8 @@ WriteTo(__razor_template_writer, item); #line default #line hidden - Instrumentation.BeginContext(574, 93, true); - WriteLiteralTo(__razor_template_writer, "\r\n