From 1b51f6bca67e0f2e2d2c4ded15775174c9f3c789 Mon Sep 17 00:00:00 2001 From: "N. Taylor Mullen" Date: Tue, 11 Aug 2015 12:40:15 -0700 Subject: [PATCH] Enable input, image and url resolution `TagHelper`s to be written as void elements. - Razor rendering now understands `TagMode` which allows void elements to be rendered. - Added a `TagStructure.WithoutEnd` bit to `InputTagHelper`, `ImageTagHelper` and `UrlResolutionTagHelper`. This will allow users to write the various elements in the void format. Used the HTML5 spec to determine the elements appropriate. - Added tests to ensure `TagMode.StartTagOnly` is rendered properly. - Updated a few functional tests to showcase the void element formats. aspnet/Razor#450 --- src/Microsoft.AspNet.Mvc.Razor/RazorPage.cs | 6 +- .../TagHelpers/UrlResolutionTagHelper.cs | 19 +- .../ImageTagHelper.cs | 5 +- .../InputTagHelper.cs | 2 +- ...tionWebSite.HtmlGeneration_Home.Image.html | 10 +- ...orWebSite.UrlResolution.Index.Encoded.html | 16 +- .../RazorWebSite.UrlResolution.Index.html | 16 +- .../Runtime/ModelExpressionTagHelper.cs | 4 +- .../RazorPageTest.cs | 230 ++++++++++++++---- .../FormTagHelperTest.cs | 11 +- .../InputTagHelperTest.cs | 39 ++- .../LabelTagHelperTest.cs | 6 +- .../OptionTagHelperTest.cs | 6 +- .../SelectTagHelperTest.cs | 12 +- .../TextAreaTagHelperTest.cs | 4 +- .../Views/HtmlGeneration_Home/Image.cshtml | 10 +- .../Views/UrlResolution/Index.cshtml | 16 +- .../TagHelpers/WebsiteInformationTagHelper.cs | 2 +- 18 files changed, 278 insertions(+), 136 deletions(-) diff --git a/src/Microsoft.AspNet.Mvc.Razor/RazorPage.cs b/src/Microsoft.AspNet.Mvc.Razor/RazorPage.cs index 5a0eb161b2..5c2b6088e9 100644 --- a/src/Microsoft.AspNet.Mvc.Razor/RazorPage.cs +++ b/src/Microsoft.AspNet.Mvc.Razor/RazorPage.cs @@ -336,7 +336,7 @@ namespace Microsoft.AspNet.Mvc.Razor } } - if (tagHelperOutput.SelfClosing) + if (tagHelperOutput.TagMode == TagMode.SelfClosing) { writer.Write(" /"); } @@ -344,7 +344,7 @@ namespace Microsoft.AspNet.Mvc.Razor writer.Write('>'); } - if (isTagNameNullOrWhitespace || !tagHelperOutput.SelfClosing) + if (isTagNameNullOrWhitespace || tagHelperOutput.TagMode == TagMode.StartTagAndEndTag) { WriteTo(writer, tagHelperOutput.PreContent); if (tagHelperOutput.IsContentModified) @@ -364,7 +364,7 @@ namespace Microsoft.AspNet.Mvc.Razor WriteTo(writer, tagHelperOutput.PostContent); } - if (!isTagNameNullOrWhitespace && !tagHelperOutput.SelfClosing) + if (!isTagNameNullOrWhitespace && tagHelperOutput.TagMode == TagMode.StartTagAndEndTag) { writer.Write(string.Format(CultureInfo.InvariantCulture, "", tagHelperOutput.TagName)); } diff --git a/src/Microsoft.AspNet.Mvc.Razor/TagHelpers/UrlResolutionTagHelper.cs b/src/Microsoft.AspNet.Mvc.Razor/TagHelpers/UrlResolutionTagHelper.cs index b3dc9cd61b..400e6895ce 100644 --- a/src/Microsoft.AspNet.Mvc.Razor/TagHelpers/UrlResolutionTagHelper.cs +++ b/src/Microsoft.AspNet.Mvc.Razor/TagHelpers/UrlResolutionTagHelper.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.ComponentModel; -using System.Linq; using System.Reflection; using Microsoft.AspNet.Mvc.Rendering; using Microsoft.AspNet.Razor.Runtime.TagHelpers; @@ -21,28 +20,28 @@ namespace Microsoft.AspNet.Mvc.Razor.TagHelpers [TargetElement("*", Attributes = "itemid")] [TargetElement("a", Attributes = "href")] [TargetElement("applet", Attributes = "archive")] - [TargetElement("area", Attributes = "href")] + [TargetElement("area", Attributes = "href", TagStructure = TagStructure.WithoutEndTag)] [TargetElement("audio", Attributes = "src")] - [TargetElement("base", Attributes = "href")] + [TargetElement("base", Attributes = "href", TagStructure = TagStructure.WithoutEndTag)] [TargetElement("blockquote", Attributes = "cite")] [TargetElement("button", Attributes = "formaction")] [TargetElement("del", Attributes = "cite")] - [TargetElement("embed", Attributes = "src")] + [TargetElement("embed", Attributes = "src", TagStructure = TagStructure.WithoutEndTag)] [TargetElement("form", Attributes = "action")] [TargetElement("html", Attributes = "manifest")] [TargetElement("iframe", Attributes = "src")] - [TargetElement("img", Attributes = "src")] - [TargetElement("input", Attributes = "src")] - [TargetElement("input", Attributes = "formaction")] + [TargetElement("img", Attributes = "src", TagStructure = TagStructure.WithoutEndTag)] + [TargetElement("input", Attributes = "src", TagStructure = TagStructure.WithoutEndTag)] + [TargetElement("input", Attributes = "formaction", TagStructure = TagStructure.WithoutEndTag)] [TargetElement("ins", Attributes = "cite")] - [TargetElement("link", Attributes = "href")] + [TargetElement("link", Attributes = "href", TagStructure = TagStructure.WithoutEndTag)] [TargetElement("menuitem", Attributes = "icon")] [TargetElement("object", Attributes = "archive")] [TargetElement("object", Attributes = "data")] [TargetElement("q", Attributes = "cite")] [TargetElement("script", Attributes = "src")] - [TargetElement("source", Attributes = "src")] - [TargetElement("track", Attributes = "src")] + [TargetElement("source", Attributes = "src", TagStructure = TagStructure.WithoutEndTag)] + [TargetElement("track", Attributes = "src", TagStructure = TagStructure.WithoutEndTag)] [TargetElement("video", Attributes = "src")] [TargetElement("video", Attributes = "poster")] [EditorBrowsable(EditorBrowsableState.Never)] diff --git a/src/Microsoft.AspNet.Mvc.TagHelpers/ImageTagHelper.cs b/src/Microsoft.AspNet.Mvc.TagHelpers/ImageTagHelper.cs index 28680f0647..47d7e365a2 100644 --- a/src/Microsoft.AspNet.Mvc.TagHelpers/ImageTagHelper.cs +++ b/src/Microsoft.AspNet.Mvc.TagHelpers/ImageTagHelper.cs @@ -16,7 +16,10 @@ namespace Microsoft.AspNet.Mvc.TagHelpers /// /// The tag helper won't process for cases with just the 'src' attribute. /// - [TargetElement("img", Attributes = AppendVersionAttributeName + "," + SrcAttributeName)] + [TargetElement( + "img", + Attributes = AppendVersionAttributeName + "," + SrcAttributeName, + TagStructure = TagStructure.WithoutEndTag)] public class ImageTagHelper : UrlResolutionTagHelper { private static readonly string Namespace = typeof(ImageTagHelper).Namespace; diff --git a/src/Microsoft.AspNet.Mvc.TagHelpers/InputTagHelper.cs b/src/Microsoft.AspNet.Mvc.TagHelpers/InputTagHelper.cs index 0492c4e77a..28f59acc1c 100644 --- a/src/Microsoft.AspNet.Mvc.TagHelpers/InputTagHelper.cs +++ b/src/Microsoft.AspNet.Mvc.TagHelpers/InputTagHelper.cs @@ -15,7 +15,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers /// /// implementation targeting <input> elements with an asp-for attribute. /// - [TargetElement("input", Attributes = ForAttributeName)] + [TargetElement("input", Attributes = ForAttributeName, TagStructure = TagStructure.WithoutEndTag)] public class InputTagHelper : TagHelper { private const string ForAttributeName = "asp-for"; diff --git a/test/Microsoft.AspNet.Mvc.FunctionalTests/compiler/resources/HtmlGenerationWebSite.HtmlGeneration_Home.Image.html b/test/Microsoft.AspNet.Mvc.FunctionalTests/compiler/resources/HtmlGenerationWebSite.HtmlGeneration_Home.Image.html index aa872be294..c851ccf084 100644 --- a/test/Microsoft.AspNet.Mvc.FunctionalTests/compiler/resources/HtmlGenerationWebSite.HtmlGeneration_Home.Image.html +++ b/test/Microsoft.AspNet.Mvc.FunctionalTests/compiler/resources/HtmlGenerationWebSite.HtmlGeneration_Home.Image.html @@ -9,27 +9,27 @@

Image Tag Helper Test

- Red block + Red block Red versioned - Red explicitly not versioned + Red explicitly not versioned - Absolute path versioned + Absolute path versioned Path to non existing file - Path with query string + Path with query string Path with query string - Path linking to some action + Path linking to some action \ No newline at end of file diff --git a/test/Microsoft.AspNet.Mvc.FunctionalTests/compiler/resources/RazorWebSite.UrlResolution.Index.Encoded.html b/test/Microsoft.AspNet.Mvc.FunctionalTests/compiler/resources/RazorWebSite.UrlResolution.Index.Encoded.html index 48c341cc8a..0cf79e7fbe 100644 --- a/test/Microsoft.AspNet.Mvc.FunctionalTests/compiler/resources/RazorWebSite.UrlResolution.Index.Encoded.html +++ b/test/Microsoft.AspNet.Mvc.FunctionalTests/compiler/resources/RazorWebSite.UrlResolution.Index.Encoded.html @@ -1,22 +1,22 @@ - +
Person - Url stuff - + Url stuff +