273 lines
18 KiB
C#
273 lines
18 KiB
C#
|
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
|
|||
|
|
|||
|
using System.Web.Razor.Editor;
|
|||
|
using System.Web.Razor.Generator;
|
|||
|
using System.Web.Razor.Parser;
|
|||
|
using System.Web.Razor.Parser.SyntaxTree;
|
|||
|
using System.Web.Razor.Test.Framework;
|
|||
|
using System.Web.Razor.Text;
|
|||
|
using Xunit;
|
|||
|
|
|||
|
namespace System.Web.Razor.Test.Parser.Html
|
|||
|
{
|
|||
|
public class HtmlUrlAttributeTest : CsHtmlMarkupParserTestBase
|
|||
|
{
|
|||
|
[Fact]
|
|||
|
public void SimpleUrlInAttributeInMarkupBlock()
|
|||
|
{
|
|||
|
ParseBlockTest("<a href='~/Foo/Bar/Baz' />",
|
|||
|
new MarkupBlock(
|
|||
|
Factory.Markup("<a"),
|
|||
|
new MarkupBlock(new AttributeBlockCodeGenerator("href", new LocationTagged<string>(" href='", 2, 0, 2), new LocationTagged<string>("'", 22, 0, 22)),
|
|||
|
Factory.Markup(" href='").With(SpanCodeGenerator.Null),
|
|||
|
Factory.Markup("~/Foo/Bar/Baz")
|
|||
|
.WithEditorHints(EditorHints.VirtualPath)
|
|||
|
.With(new LiteralAttributeCodeGenerator(
|
|||
|
new LocationTagged<string>(String.Empty, 9, 0, 9),
|
|||
|
new LocationTagged<SpanCodeGenerator>(new ResolveUrlCodeGenerator(), 9, 0, 9))),
|
|||
|
Factory.Markup("'").With(SpanCodeGenerator.Null)),
|
|||
|
Factory.Markup(" />").Accepts(AcceptedCharacters.None)));
|
|||
|
}
|
|||
|
|
|||
|
[Fact]
|
|||
|
public void SimpleUrlInAttributeInMarkupDocument()
|
|||
|
{
|
|||
|
ParseDocumentTest("<a href='~/Foo/Bar/Baz' />",
|
|||
|
new MarkupBlock(
|
|||
|
Factory.Markup("<a"),
|
|||
|
new MarkupBlock(new AttributeBlockCodeGenerator("href", new LocationTagged<string>(" href='", 2, 0, 2), new LocationTagged<string>("'", 22, 0, 22)),
|
|||
|
Factory.Markup(" href='").With(SpanCodeGenerator.Null),
|
|||
|
Factory.Markup("~/Foo/Bar/Baz")
|
|||
|
.WithEditorHints(EditorHints.VirtualPath)
|
|||
|
.With(new LiteralAttributeCodeGenerator(
|
|||
|
new LocationTagged<string>(String.Empty, 9, 0, 9),
|
|||
|
new LocationTagged<SpanCodeGenerator>(new ResolveUrlCodeGenerator(), 9, 0, 9))),
|
|||
|
Factory.Markup("'").With(SpanCodeGenerator.Null)),
|
|||
|
Factory.Markup(" />")));
|
|||
|
}
|
|||
|
|
|||
|
[Fact]
|
|||
|
public void SimpleUrlInAttributeInMarkupSection()
|
|||
|
{
|
|||
|
ParseDocumentTest("@section Foo { <a href='~/Foo/Bar/Baz' /> }",
|
|||
|
new MarkupBlock(
|
|||
|
Factory.EmptyHtml(),
|
|||
|
new SectionBlock(new SectionCodeGenerator("Foo"),
|
|||
|
Factory.CodeTransition(),
|
|||
|
Factory.MetaCode("section Foo {")
|
|||
|
.AutoCompleteWith(null, atEndOfSpan: true)
|
|||
|
.Accepts(AcceptedCharacters.Any),
|
|||
|
new MarkupBlock(
|
|||
|
Factory.Markup(" <a"),
|
|||
|
new MarkupBlock(new AttributeBlockCodeGenerator("href", new LocationTagged<string>(" href='", 17, 0, 17), new LocationTagged<string>("'", 37, 0, 37)),
|
|||
|
Factory.Markup(" href='").With(SpanCodeGenerator.Null),
|
|||
|
Factory.Markup("~/Foo/Bar/Baz")
|
|||
|
.WithEditorHints(EditorHints.VirtualPath)
|
|||
|
.With(new LiteralAttributeCodeGenerator(
|
|||
|
new LocationTagged<string>(String.Empty, 24, 0, 24),
|
|||
|
new LocationTagged<SpanCodeGenerator>(new ResolveUrlCodeGenerator(), 24, 0, 24))),
|
|||
|
Factory.Markup("'").With(SpanCodeGenerator.Null)),
|
|||
|
Factory.Markup(" /> ")),
|
|||
|
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
|||
|
Factory.EmptyHtml()));
|
|||
|
}
|
|||
|
|
|||
|
[Fact]
|
|||
|
public void UrlWithExpressionsInAttributeInMarkupBlock()
|
|||
|
{
|
|||
|
ParseBlockTest("<a href='~/Foo/@id/Baz' />",
|
|||
|
new MarkupBlock(
|
|||
|
Factory.Markup("<a"),
|
|||
|
new MarkupBlock(new AttributeBlockCodeGenerator("href", new LocationTagged<string>(" href='", 2, 0, 2), new LocationTagged<string>("'", 22, 0, 22)),
|
|||
|
Factory.Markup(" href='").With(SpanCodeGenerator.Null),
|
|||
|
Factory.Markup("~/Foo/")
|
|||
|
.WithEditorHints(EditorHints.VirtualPath)
|
|||
|
.With(new LiteralAttributeCodeGenerator(
|
|||
|
new LocationTagged<string>(String.Empty, 9, 0, 9),
|
|||
|
new LocationTagged<SpanCodeGenerator>(new ResolveUrlCodeGenerator(), 9, 0, 9))),
|
|||
|
new MarkupBlock(new DynamicAttributeBlockCodeGenerator(new LocationTagged<string>(String.Empty, 15, 0, 15), 15, 0, 15),
|
|||
|
new ExpressionBlock(
|
|||
|
Factory.CodeTransition().Accepts(AcceptedCharacters.None),
|
|||
|
Factory.Code("id")
|
|||
|
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
|||
|
.Accepts(AcceptedCharacters.NonWhiteSpace))),
|
|||
|
Factory.Markup("/Baz")
|
|||
|
.With(new LiteralAttributeCodeGenerator(new LocationTagged<string>(String.Empty, 18, 0, 18), new LocationTagged<string>("/Baz", 18, 0, 18))),
|
|||
|
Factory.Markup("'").With(SpanCodeGenerator.Null)),
|
|||
|
Factory.Markup(" />").Accepts(AcceptedCharacters.None)));
|
|||
|
}
|
|||
|
|
|||
|
[Fact]
|
|||
|
public void UrlWithExpressionsInAttributeInMarkupDocument()
|
|||
|
{
|
|||
|
ParseDocumentTest("<a href='~/Foo/@id/Baz' />",
|
|||
|
new MarkupBlock(
|
|||
|
Factory.Markup("<a"),
|
|||
|
new MarkupBlock(new AttributeBlockCodeGenerator("href", new LocationTagged<string>(" href='", 2, 0, 2), new LocationTagged<string>("'", 22, 0, 22)),
|
|||
|
Factory.Markup(" href='").With(SpanCodeGenerator.Null),
|
|||
|
Factory.Markup("~/Foo/")
|
|||
|
.WithEditorHints(EditorHints.VirtualPath)
|
|||
|
.With(new LiteralAttributeCodeGenerator(
|
|||
|
new LocationTagged<string>(String.Empty, 9, 0, 9),
|
|||
|
new LocationTagged<SpanCodeGenerator>(new ResolveUrlCodeGenerator(), 9, 0, 9))),
|
|||
|
new MarkupBlock(new DynamicAttributeBlockCodeGenerator(new LocationTagged<string>(String.Empty, 15, 0, 15), 15, 0, 15),
|
|||
|
new ExpressionBlock(
|
|||
|
Factory.CodeTransition().Accepts(AcceptedCharacters.None),
|
|||
|
Factory.Code("id")
|
|||
|
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
|||
|
.Accepts(AcceptedCharacters.NonWhiteSpace))),
|
|||
|
Factory.Markup("/Baz")
|
|||
|
.With(new LiteralAttributeCodeGenerator(new LocationTagged<string>(String.Empty, 18, 0, 18), new LocationTagged<string>("/Baz", 18, 0, 18))),
|
|||
|
Factory.Markup("'").With(SpanCodeGenerator.Null)),
|
|||
|
Factory.Markup(" />")));
|
|||
|
}
|
|||
|
|
|||
|
[Fact]
|
|||
|
public void UrlWithExpressionsInAttributeInMarkupSection()
|
|||
|
{
|
|||
|
ParseDocumentTest("@section Foo { <a href='~/Foo/@id/Baz' /> }",
|
|||
|
new MarkupBlock(
|
|||
|
Factory.EmptyHtml(),
|
|||
|
new SectionBlock(new SectionCodeGenerator("Foo"),
|
|||
|
Factory.CodeTransition(),
|
|||
|
Factory.MetaCode("section Foo {")
|
|||
|
.AutoCompleteWith(null, atEndOfSpan: true),
|
|||
|
new MarkupBlock(
|
|||
|
Factory.Markup(" <a"),
|
|||
|
new MarkupBlock(new AttributeBlockCodeGenerator("href", new LocationTagged<string>(" href='", 17, 0, 17), new LocationTagged<string>("'", 37, 0, 37)),
|
|||
|
Factory.Markup(" href='").With(SpanCodeGenerator.Null),
|
|||
|
Factory.Markup("~/Foo/")
|
|||
|
.WithEditorHints(EditorHints.VirtualPath)
|
|||
|
.With(new LiteralAttributeCodeGenerator(
|
|||
|
new LocationTagged<string>(String.Empty, 24, 0, 24),
|
|||
|
new LocationTagged<SpanCodeGenerator>(new ResolveUrlCodeGenerator(), 24, 0, 24))),
|
|||
|
new MarkupBlock(new DynamicAttributeBlockCodeGenerator(new LocationTagged<string>(String.Empty, 30, 0, 30), 30, 0, 30),
|
|||
|
new ExpressionBlock(
|
|||
|
Factory.CodeTransition().Accepts(AcceptedCharacters.None),
|
|||
|
Factory.Code("id")
|
|||
|
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
|||
|
.Accepts(AcceptedCharacters.NonWhiteSpace))),
|
|||
|
Factory.Markup("/Baz")
|
|||
|
.With(new LiteralAttributeCodeGenerator(new LocationTagged<string>(String.Empty, 33, 0, 33), new LocationTagged<string>("/Baz", 33, 0, 33))),
|
|||
|
Factory.Markup("'").With(SpanCodeGenerator.Null)),
|
|||
|
Factory.Markup(" /> ")),
|
|||
|
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
|||
|
Factory.EmptyHtml()));
|
|||
|
}
|
|||
|
|
|||
|
[Fact]
|
|||
|
public void UrlWithComplexCharactersInAttributeInMarkupBlock()
|
|||
|
{
|
|||
|
ParseBlockTest("<a href='~/Foo+Bar:Baz(Biz),Boz' />",
|
|||
|
new MarkupBlock(
|
|||
|
Factory.Markup("<a"),
|
|||
|
new MarkupBlock(new AttributeBlockCodeGenerator("href", new LocationTagged<string>(" href='", 2, 0, 2), new LocationTagged<string>("'", 31, 0, 31)),
|
|||
|
Factory.Markup(" href='").With(SpanCodeGenerator.Null),
|
|||
|
Factory.Markup("~/Foo+Bar:Baz(Biz),Boz")
|
|||
|
.WithEditorHints(EditorHints.VirtualPath)
|
|||
|
.With(new LiteralAttributeCodeGenerator(
|
|||
|
new LocationTagged<string>(String.Empty, 9, 0, 9),
|
|||
|
new LocationTagged<SpanCodeGenerator>(new ResolveUrlCodeGenerator(), 9, 0, 9))),
|
|||
|
Factory.Markup("'").With(SpanCodeGenerator.Null)),
|
|||
|
Factory.Markup(" />").Accepts(AcceptedCharacters.None)));
|
|||
|
}
|
|||
|
|
|||
|
[Fact]
|
|||
|
public void UrlWithComplexCharactersInAttributeInMarkupDocument()
|
|||
|
{
|
|||
|
ParseDocumentTest("<a href='~/Foo+Bar:Baz(Biz),Boz' />",
|
|||
|
new MarkupBlock(
|
|||
|
Factory.Markup("<a"),
|
|||
|
new MarkupBlock(new AttributeBlockCodeGenerator("href", new LocationTagged<string>(" href='", 2, 0, 2), new LocationTagged<string>("'", 31, 0, 31)),
|
|||
|
Factory.Markup(" href='").With(SpanCodeGenerator.Null),
|
|||
|
Factory.Markup("~/Foo+Bar:Baz(Biz),Boz")
|
|||
|
.WithEditorHints(EditorHints.VirtualPath)
|
|||
|
.With(new LiteralAttributeCodeGenerator(
|
|||
|
new LocationTagged<string>(String.Empty, 9, 0, 9),
|
|||
|
new LocationTagged<SpanCodeGenerator>(new ResolveUrlCodeGenerator(), 9, 0, 9))),
|
|||
|
Factory.Markup("'").With(SpanCodeGenerator.Null)),
|
|||
|
Factory.Markup(" />")));
|
|||
|
}
|
|||
|
|
|||
|
[Fact]
|
|||
|
public void UrlInUnquotedAttributeValueInMarkupBlock()
|
|||
|
{
|
|||
|
ParseBlockTest("<a href=~/Foo+Bar:Baz(Biz),Boz/@id/Boz />",
|
|||
|
new MarkupBlock(
|
|||
|
Factory.Markup("<a"),
|
|||
|
new MarkupBlock(new AttributeBlockCodeGenerator("href", new LocationTagged<string>(" href=", 2, 0, 2), new LocationTagged<string>(String.Empty, 38, 0, 38)),
|
|||
|
Factory.Markup(" href=").With(SpanCodeGenerator.Null),
|
|||
|
Factory.Markup("~/Foo+Bar:Baz(Biz),Boz/")
|
|||
|
.WithEditorHints(EditorHints.VirtualPath)
|
|||
|
.With(new LiteralAttributeCodeGenerator(
|
|||
|
new LocationTagged<string>(String.Empty, 8, 0, 8),
|
|||
|
new LocationTagged<SpanCodeGenerator>(new ResolveUrlCodeGenerator(), 8, 0, 8))),
|
|||
|
new MarkupBlock(new DynamicAttributeBlockCodeGenerator(new LocationTagged<string>(String.Empty, 31, 0, 31), 31, 0, 31),
|
|||
|
new ExpressionBlock(
|
|||
|
Factory.CodeTransition()
|
|||
|
.Accepts(AcceptedCharacters.None),
|
|||
|
Factory.Code("id")
|
|||
|
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
|||
|
.Accepts(AcceptedCharacters.NonWhiteSpace))),
|
|||
|
Factory.Markup("/Boz").With(new LiteralAttributeCodeGenerator(new LocationTagged<string>(String.Empty, 34, 0, 34), new LocationTagged<string>("/Boz", 34, 0, 34)))),
|
|||
|
Factory.Markup(" />").Accepts(AcceptedCharacters.None)));
|
|||
|
}
|
|||
|
|
|||
|
[Fact]
|
|||
|
public void UrlInUnquotedAttributeValueInMarkupDocument()
|
|||
|
{
|
|||
|
ParseDocumentTest("<a href=~/Foo+Bar:Baz(Biz),Boz/@id/Boz />",
|
|||
|
new MarkupBlock(
|
|||
|
Factory.Markup("<a"),
|
|||
|
new MarkupBlock(new AttributeBlockCodeGenerator("href", new LocationTagged<string>(" href=", 2, 0, 2), new LocationTagged<string>(String.Empty, 38, 0, 38)),
|
|||
|
Factory.Markup(" href=").With(SpanCodeGenerator.Null),
|
|||
|
Factory.Markup("~/Foo+Bar:Baz(Biz),Boz/")
|
|||
|
.WithEditorHints(EditorHints.VirtualPath)
|
|||
|
.With(new LiteralAttributeCodeGenerator(
|
|||
|
new LocationTagged<string>(String.Empty, 8, 0, 8),
|
|||
|
new LocationTagged<SpanCodeGenerator>(new ResolveUrlCodeGenerator(), 8, 0, 8))),
|
|||
|
new MarkupBlock(new DynamicAttributeBlockCodeGenerator(new LocationTagged<string>(String.Empty, 31, 0, 31), 31, 0, 31),
|
|||
|
new ExpressionBlock(
|
|||
|
Factory.CodeTransition()
|
|||
|
.Accepts(AcceptedCharacters.None),
|
|||
|
Factory.Code("id")
|
|||
|
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
|||
|
.Accepts(AcceptedCharacters.NonWhiteSpace))),
|
|||
|
Factory.Markup("/Boz").With(new LiteralAttributeCodeGenerator(new LocationTagged<string>(String.Empty, 34, 0, 34), new LocationTagged<string>("/Boz", 34, 0, 34)))),
|
|||
|
Factory.Markup(" />")));
|
|||
|
}
|
|||
|
|
|||
|
[Fact]
|
|||
|
public void UrlInUnquotedAttributeValueInMarkupSection()
|
|||
|
{
|
|||
|
ParseDocumentTest("@section Foo { <a href=~/Foo+Bar:Baz(Biz),Boz/@id/Boz /> }",
|
|||
|
new MarkupBlock(
|
|||
|
Factory.EmptyHtml(),
|
|||
|
new SectionBlock(new SectionCodeGenerator("Foo"),
|
|||
|
Factory.CodeTransition(),
|
|||
|
Factory.MetaCode("section Foo {")
|
|||
|
.AutoCompleteWith(null, atEndOfSpan: true),
|
|||
|
new MarkupBlock(
|
|||
|
Factory.Markup(" <a"),
|
|||
|
new MarkupBlock(new AttributeBlockCodeGenerator("href", new LocationTagged<string>(" href=", 17, 0, 17), new LocationTagged<string>(String.Empty, 53, 0, 53)),
|
|||
|
Factory.Markup(" href=").With(SpanCodeGenerator.Null),
|
|||
|
Factory.Markup("~/Foo+Bar:Baz(Biz),Boz/")
|
|||
|
.WithEditorHints(EditorHints.VirtualPath)
|
|||
|
.With(new LiteralAttributeCodeGenerator(
|
|||
|
new LocationTagged<string>(String.Empty, 23, 0, 23),
|
|||
|
new LocationTagged<SpanCodeGenerator>(new ResolveUrlCodeGenerator(), 23, 0, 23))),
|
|||
|
new MarkupBlock(new DynamicAttributeBlockCodeGenerator(new LocationTagged<string>(String.Empty, 46, 0, 46), 46, 0, 46),
|
|||
|
new ExpressionBlock(
|
|||
|
Factory.CodeTransition()
|
|||
|
.Accepts(AcceptedCharacters.None),
|
|||
|
Factory.Code("id")
|
|||
|
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
|||
|
.Accepts(AcceptedCharacters.NonWhiteSpace))),
|
|||
|
Factory.Markup("/Boz").With(new LiteralAttributeCodeGenerator(new LocationTagged<string>(String.Empty, 49, 0, 49), new LocationTagged<string>("/Boz", 49, 0, 49)))),
|
|||
|
Factory.Markup(" /> ")),
|
|||
|
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
|||
|
Factory.EmptyHtml()));
|
|||
|
}
|
|||
|
}
|
|||
|
}
|