@@ -195,6 +195,67 @@ public void ParseBlockGivesWhitespacePreceedingAtToCodeIfThereIsNoMarkupOnThatLi
195195 Factory . Markup ( " </ul>" ) . Accepts ( AcceptedCharacters . None ) ) ) ;
196196 }
197197
198+ [ Fact ]
199+ public void ParseDocumentGivesWhitespacePreceedingAtToCodeIfThereIsNoMarkupOnThatLine ( )
200+ {
201+ ParseDocumentTest ( @" <ul>
202+ @foreach(var p in Products) {
203+ <li>Product: @p.Name</li>
204+ }
205+ </ul>" ,
206+ new MarkupBlock (
207+ Factory . Markup ( " <ul>\r \n " ) ,
208+ new StatementBlock (
209+ Factory . Code ( " " ) . AsStatement ( ) ,
210+ Factory . CodeTransition ( ) ,
211+ Factory . Code ( "foreach(var p in Products) {\r \n " ) . AsStatement ( ) ,
212+ new MarkupBlock (
213+ Factory . Markup ( " <li>Product: " ) ,
214+ new ExpressionBlock (
215+ Factory . CodeTransition ( ) ,
216+ Factory . Code ( "p.Name" )
217+ . AsImplicitExpression ( CSharpCodeParser . DefaultKeywords )
218+ . Accepts ( AcceptedCharacters . NonWhiteSpace ) ) ,
219+ Factory . Markup ( "</li>\r \n " ) . Accepts ( AcceptedCharacters . None ) ) ,
220+ Factory . Code ( " }\r \n " ) . AsStatement ( ) . Accepts ( AcceptedCharacters . None ) ) ,
221+ Factory . Markup ( " </ul>" ) ) ) ;
222+ }
223+
224+ [ Fact ]
225+ public void SectionContextGivesWhitespacePreceedingAtToCodeIfThereIsNoMarkupOnThatLine ( )
226+ {
227+ ParseDocumentTest ( @"@section foo {
228+ <ul>
229+ @foreach(var p in Products) {
230+ <li>Product: @p.Name</li>
231+ }
232+ </ul>
233+ }" ,
234+ new MarkupBlock (
235+ Factory . EmptyHtml ( ) ,
236+ new SectionBlock ( new SectionCodeGenerator ( "foo" ) ,
237+ Factory . CodeTransition ( ) ,
238+ Factory . MetaCode ( "section foo {" ) . AutoCompleteWith ( null , atEndOfSpan : true ) ,
239+ new MarkupBlock (
240+ Factory . Markup ( "\r \n <ul>\r \n " ) ,
241+ new StatementBlock (
242+ Factory . Code ( " " ) . AsStatement ( ) ,
243+ Factory . CodeTransition ( ) ,
244+ Factory . Code ( "foreach(var p in Products) {\r \n " ) . AsStatement ( ) ,
245+ new MarkupBlock (
246+ Factory . Markup ( " <li>Product: " ) ,
247+ new ExpressionBlock (
248+ Factory . CodeTransition ( ) ,
249+ Factory . Code ( "p.Name" )
250+ . AsImplicitExpression ( CSharpCodeParser . DefaultKeywords )
251+ . Accepts ( AcceptedCharacters . NonWhiteSpace ) ) ,
252+ Factory . Markup ( "</li>\r \n " ) . Accepts ( AcceptedCharacters . None ) ) ,
253+ Factory . Code ( " }\r \n " ) . AsStatement ( ) . Accepts ( AcceptedCharacters . None ) ) ,
254+ Factory . Markup ( " </ul>\r \n " ) ) ,
255+ Factory . MetaCode ( "}" ) . Accepts ( AcceptedCharacters . None ) ) ,
256+ Factory . EmptyHtml ( ) ) ) ;
257+ }
258+
198259 [ Fact ]
199260 public void CSharpCodeParserDoesNotAcceptLeadingOrTrailingWhitespaceInDesignMode ( )
200261 {
@@ -218,5 +279,72 @@ public void CSharpCodeParserDoesNotAcceptLeadingOrTrailingWhitespaceInDesignMode
218279 Factory . Markup ( "\r \n </ul>" ) . Accepts ( AcceptedCharacters . None ) ) ,
219280 designTimeParser : true ) ;
220281 }
282+
283+ // Tests for "@@" escape sequence:
284+ [ Fact ]
285+ public void ParseBlockTreatsTwoAtSignsAsEscapeSequence ( )
286+ {
287+ HtmlParserTestUtils . RunSingleAtEscapeTest ( ParseBlockTest ) ;
288+ }
289+
290+ [ Fact ]
291+ public void ParseBlockTreatsPairsOfAtSignsAsEscapeSequence ( )
292+ {
293+ HtmlParserTestUtils . RunMultiAtEscapeTest ( ParseBlockTest ) ;
294+ }
295+
296+ [ Fact ]
297+ public void ParseDocumentTreatsTwoAtSignsAsEscapeSequence ( )
298+ {
299+ HtmlParserTestUtils . RunSingleAtEscapeTest ( ParseDocumentTest , lastSpanAcceptedCharacters : AcceptedCharacters . Any ) ;
300+ }
301+
302+ [ Fact ]
303+ public void ParseDocumentTreatsPairsOfAtSignsAsEscapeSequence ( )
304+ {
305+ HtmlParserTestUtils . RunMultiAtEscapeTest ( ParseDocumentTest , lastSpanAcceptedCharacters : AcceptedCharacters . Any ) ;
306+ }
307+
308+ [ Fact ]
309+ public void SectionBodyTreatsTwoAtSignsAsEscapeSequence ( )
310+ {
311+ ParseDocumentTest ( "@section Foo { <foo>@@bar</foo> }" ,
312+ new MarkupBlock (
313+ Factory . EmptyHtml ( ) ,
314+ new SectionBlock ( new SectionCodeGenerator ( "Foo" ) ,
315+ Factory . CodeTransition ( ) ,
316+ Factory . MetaCode ( "section Foo {" ) . AutoCompleteWith ( null , atEndOfSpan : true ) ,
317+ new MarkupBlock (
318+ Factory . Markup ( " <foo>" ) ,
319+ Factory . Markup ( "@" ) . Hidden ( ) ,
320+ Factory . Markup ( "@bar</foo> " ) ) ,
321+ Factory . MetaCode ( "}" ) . Accepts ( AcceptedCharacters . None ) ) ,
322+ Factory . EmptyHtml ( ) ) ) ;
323+ }
324+
325+ [ Fact ]
326+ public void SectionBodyTreatsPairsOfAtSignsAsEscapeSequence ( )
327+ {
328+ ParseDocumentTest ( "@section Foo { <foo>@@@@@bar</foo> }" ,
329+ new MarkupBlock (
330+ Factory . EmptyHtml ( ) ,
331+ new SectionBlock ( new SectionCodeGenerator ( "Foo" ) ,
332+ Factory . CodeTransition ( ) ,
333+ Factory . MetaCode ( "section Foo {" ) . AutoCompleteWith ( null , atEndOfSpan : true ) ,
334+ new MarkupBlock (
335+ Factory . Markup ( " <foo>" ) ,
336+ Factory . Markup ( "@" ) . Hidden ( ) ,
337+ Factory . Markup ( "@" ) ,
338+ Factory . Markup ( "@" ) . Hidden ( ) ,
339+ Factory . Markup ( "@" ) ,
340+ new ExpressionBlock (
341+ Factory . CodeTransition ( ) ,
342+ Factory . Code ( "bar" )
343+ . AsImplicitExpression ( CSharpCodeParser . DefaultKeywords )
344+ . Accepts ( AcceptedCharacters . NonWhiteSpace ) ) ,
345+ Factory . Markup ( "</foo> " ) ) ,
346+ Factory . MetaCode ( "}" ) . Accepts ( AcceptedCharacters . None ) ) ,
347+ Factory . EmptyHtml ( ) ) ) ;
348+ }
221349 }
222350}
0 commit comments