From 168fcbb9c13747da58dbda8a501888c2393d04f8 Mon Sep 17 00:00:00 2001 From: sornaks Date: Wed, 29 Jul 2015 16:16:49 -0700 Subject: [PATCH] Replacing BufferedEntryCollection with BufferedHtmlContent so any IHtmlContent can be added to a TagHelperContent. - Introducing a new logic to calculate IsEmpty/IsWhitespace. - Making Buffer private in DefaultTagHelperContent. - Making SetContent non-abstract. --- .../TagHelpers/DefaultTagHelperContent.cs | 206 +++++++++++------- .../TagHelpers/TagHelperContent.cs | 35 ++- .../project.json | 2 +- .../TagHelpers/DefaultTagHelperContentTest.cs | 32 +-- 4 files changed, 152 insertions(+), 123 deletions(-) diff --git a/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/DefaultTagHelperContent.cs b/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/DefaultTagHelperContent.cs index edb31dcb2e..80c6c50e62 100644 --- a/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/DefaultTagHelperContent.cs +++ b/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/DefaultTagHelperContent.cs @@ -2,8 +2,9 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Collections.Generic; using System.IO; +using System.Text; +using Microsoft.AspNet.Html.Abstractions; using Microsoft.Framework.Internal; using Microsoft.Framework.WebEncoders; @@ -14,35 +15,60 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers /// public class DefaultTagHelperContent : TagHelperContent { - private readonly BufferEntryCollection _buffer; + private BufferedHtmlContent _buffer; - /// - /// Instantiates a new instance of . - /// - public DefaultTagHelperContent() - { - _buffer = new BufferEntryCollection(); - } - - /// - public override bool IsModified + private BufferedHtmlContent Buffer { get { - return _buffer.IsModified; + if (_buffer == null) + { + _buffer = new BufferedHtmlContent(); + } + + return _buffer; } } /// + public override bool IsModified => _buffer != null; + + /// + /// Returns true for a cleared . public override bool IsWhiteSpace { get { - foreach (var value in _buffer) + if (_buffer == null) { - if (!string.IsNullOrWhiteSpace(value)) + return true; + } + + using (var writer = new EmptyOrWhiteSpaceWriter()) + { + foreach (var entry in _buffer.Entries) { - return false; + if (entry == null) + { + continue; + } + + var stringValue = entry as string; + if (stringValue != null) + { + if (!string.IsNullOrWhiteSpace(stringValue)) + { + return false; + } + } + else + { + ((IHtmlContent)entry).WriteTo(writer, HtmlEncoder.Default); + if (!writer.IsWhiteSpace) + { + return false; + } + } } } @@ -55,11 +81,36 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers { get { - foreach (var value in _buffer) + if (_buffer == null) { - if (!string.IsNullOrEmpty(value)) + return true; + } + + using (var writer = new EmptyOrWhiteSpaceWriter()) + { + foreach (var entry in _buffer.Entries) { - return false; + if (entry == null) + { + continue; + } + + var stringValue = entry as string; + if (stringValue != null) + { + if (!string.IsNullOrEmpty(stringValue)) + { + return false; + } + } + else + { + ((IHtmlContent)entry).WriteTo(writer, HtmlEncoder.Default); + if (!writer.IsEmpty) + { + return false; + } + } } } @@ -67,55 +118,38 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers } } - /// - public override TagHelperContent SetContent(string value) - { - Clear(); - Append(value); - return this; - } - - /// - public override TagHelperContent SetContent(TagHelperContent tagHelperContent) - { - Clear(); - Append(tagHelperContent); - return this; - } - - /// public override TagHelperContent Append(string value) { - _buffer.Add(value); + Buffer.Append(value); return this; } /// public override TagHelperContent AppendFormat([NotNull] string format, object arg0) { - _buffer.Add(string.Format(format, arg0)); + Buffer.Append(string.Format(format, arg0)); return this; } /// public override TagHelperContent AppendFormat([NotNull] string format, object arg0, object arg1) { - _buffer.Add(string.Format(format, arg0, arg1)); + Buffer.Append(string.Format(format, arg0, arg1)); return this; } /// public override TagHelperContent AppendFormat([NotNull] string format, object arg0, object arg1, object arg2) { - _buffer.Add(string.Format(format, arg0, arg1, arg2)); + Buffer.Append(string.Format(format, arg0, arg1, arg2)); return this; } /// public override TagHelperContent AppendFormat([NotNull] string format, params object[] args) { - _buffer.Add(string.Format(format, args)); + Buffer.Append(string.Format(format, args)); return this; } @@ -125,7 +159,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers [NotNull] string format, object arg0) { - _buffer.Add(string.Format(provider, format, arg0)); + Buffer.Append(string.Format(provider, format, arg0)); return this; } @@ -136,7 +170,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers object arg0, object arg1) { - _buffer.Add(string.Format(provider, format, arg0, arg1)); + Buffer.Append(string.Format(provider, format, arg0, arg1)); return this; } @@ -148,7 +182,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers object arg1, object arg2) { - _buffer.Add(string.Format(provider, format, arg0, arg1, arg2)); + Buffer.Append(string.Format(provider, format, arg0, arg1, arg2)); return this; } @@ -158,43 +192,43 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers [NotNull] string format, params object[] args) { - _buffer.Add(string.Format(provider, format, args)); + Buffer.Append(string.Format(provider, format, args)); return this; } /// - public override TagHelperContent Append(TagHelperContent tagHelperContent) + public override TagHelperContent Append(IHtmlContent htmlContent) { - if (tagHelperContent != null) - { - foreach (var value in tagHelperContent) - { - Append(value); - } - } - - // If Append() was called with an empty TagHelperContent IsModified should - // still be true. If the content was not already modified, it means it is empty. - // So the Clear() method can be used to indirectly set the IsModified. - if (!IsModified) - { - Clear(); - } - + Buffer.Append(htmlContent); return this; } /// public override TagHelperContent Clear() { - _buffer.Clear(); + Buffer.Clear(); return this; } /// public override string GetContent() { - return string.Join(string.Empty, _buffer); + if (_buffer == null) + { + return string.Empty; + } + + using (var writer = new StringWriter()) + { + WriteTo(writer, HtmlEncoder.Default); + return writer.ToString(); + } + } + + /// + public override void WriteTo([NotNull] TextWriter writer, [NotNull] IHtmlEncoder encoder) + { + Buffer.WriteTo(writer, encoder); } /// @@ -203,20 +237,40 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers return GetContent(); } - /// - public override IEnumerator GetEnumerator() + // Overrides Write(string) to find if the content written is empty/whitespace. + private class EmptyOrWhiteSpaceWriter : TextWriter { - // The enumerator is exposed so that SetContent(TagHelperContent) and Append(TagHelperContent) - // can use this to iterate through the values of the buffer. - return _buffer.GetEnumerator(); - } - - /// - public override void WriteTo(TextWriter writer, IHtmlEncoder encoder) - { - foreach (var entry in _buffer) + public override Encoding Encoding { - writer.Write(entry); + get + { + throw new NotImplementedException(); + } + } + + public bool IsEmpty { get; private set; } = true; + + public bool IsWhiteSpace { get; private set; } = true; + +#if DNXCORE50 + // This is an abstract method in DNXCore + public override void Write(char value) + { + throw new NotImplementedException(); + } +#endif + + public override void Write(string value) + { + if (IsEmpty && !string.IsNullOrEmpty(value)) + { + IsEmpty = false; + } + + if (IsWhiteSpace && !string.IsNullOrWhiteSpace(value)) + { + IsWhiteSpace = false; + } } } } diff --git a/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperContent.cs b/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperContent.cs index e5cb6509a1..cf5abd1e3e 100644 --- a/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperContent.cs +++ b/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperContent.cs @@ -2,8 +2,6 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Collections; -using System.Collections.Generic; using System.IO; using Microsoft.AspNet.Html.Abstractions; using Microsoft.Framework.WebEncoders; @@ -13,7 +11,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers /// /// Abstract class used to buffer content returned by s. /// - public abstract class TagHelperContent : IEnumerable, IHtmlContent + public abstract class TagHelperContent : IHtmlContent { /// /// Gets a value indicating whether the content was modifed. @@ -35,14 +33,24 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers /// /// The that replaces the content. /// A reference to this instance after the set operation has completed. - public abstract TagHelperContent SetContent(string value); + public TagHelperContent SetContent(string value) + { + Clear(); + Append(value); + return this; + } /// /// Sets the content. /// - /// The that replaces the content. + /// The that replaces the content. /// A reference to this instance after the set operation has completed. - public abstract TagHelperContent SetContent(TagHelperContent tagHelperContent); + public TagHelperContent SetContent(IHtmlContent htmlContent) + { + Clear(); + Append(htmlContent); + return this; + } /// /// Appends to the existing content. @@ -168,11 +176,11 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers public abstract TagHelperContent AppendFormat(IFormatProvider provider, string format, params object[] args); /// - /// Appends to the existing content. + /// Appends to the existing content. /// - /// The to be appended. + /// The to be appended. /// A reference to this instance after the append operation has completed. - public abstract TagHelperContent Append(TagHelperContent tagHelperContent); + public abstract TagHelperContent Append(IHtmlContent htmlContent); /// /// Clears the content. @@ -186,15 +194,6 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers /// A containing the content. public abstract string GetContent(); - /// - public abstract IEnumerator GetEnumerator(); - - /// - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - /// public abstract void WriteTo(TextWriter writer, IHtmlEncoder encoder); } diff --git a/src/Microsoft.AspNet.Razor.Runtime/project.json b/src/Microsoft.AspNet.Razor.Runtime/project.json index cf5e7fefb6..73e4a85112 100644 --- a/src/Microsoft.AspNet.Razor.Runtime/project.json +++ b/src/Microsoft.AspNet.Razor.Runtime/project.json @@ -8,7 +8,7 @@ "dependencies": { "Microsoft.AspNet.Html.Abstractions": "1.0.0-*", "Microsoft.AspNet.Razor": "4.0.0-*", - "Microsoft.Framework.BufferEntryCollection.Sources": { + "Microsoft.Framework.BufferedHtmlContent.Sources": { "type": "build", "version": "1.0.0-*" }, diff --git a/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/DefaultTagHelperContentTest.cs b/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/DefaultTagHelperContentTest.cs index 3a9cb11fb0..2178371f71 100644 --- a/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/DefaultTagHelperContentTest.cs +++ b/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/DefaultTagHelperContentTest.cs @@ -301,7 +301,6 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers // Assert Assert.Equal(expected, copiedTagHelperContent.GetContent()); - Assert.Equal(new[] { text1, text2 }, copiedTagHelperContent.ToArray()); } [Fact] @@ -526,23 +525,6 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers Assert.Equal(expected, actual, StringComparer.Ordinal); } - [Fact] - public void GetEnumerator_EnumeratesThroughBuffer() - { - // Arrange - var tagHelperContent = new DefaultTagHelperContent(); - var expected = new string[] { "Hello", "World" }; - tagHelperContent.SetContent(expected[0]); - tagHelperContent.Append(expected[1]); - var i = 0; - - // Act & Assert - foreach (var val in tagHelperContent) - { - Assert.Equal(expected[i++], val); - } - } - [Fact] public void Fluent_SetContent_Append_WritesExpectedContent() { @@ -562,17 +544,14 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers { // Arrange var tagHelperContent = new DefaultTagHelperContent(); - var expected = new[] { "First ", "Second Third" }; + var expected = "First Second Third"; var i = 0; // Act tagHelperContent.SetContent("First ").AppendFormat("{0} Third", "Second"); // Assert - foreach (var value in tagHelperContent) - { - Assert.Equal(expected[i++], value); - } + Assert.Equal(expected, tagHelperContent.GetContent()); } [Fact] @@ -580,7 +559,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers { // Arrange var tagHelperContent = new DefaultTagHelperContent(); - var expected = new[] { "First ", "Second Third ", "Fourth" }; + var expected = "First Second Third Fourth"; var i = 0; // Act @@ -590,10 +569,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers .Append("Fourth"); // Assert - foreach (var value in tagHelperContent) - { - Assert.Equal(expected[i++], value); - } + Assert.Equal(expected, tagHelperContent.GetContent()); } [Fact]