Moving Microsoft.AspNet.Html.Abstractions to a HtmlAbstractions repo

Fixes #418
This commit is contained in:
Pranav K 2015-12-01 15:40:47 -08:00
parent 67aa2546a8
commit a0a1c38e44
15 changed files with 0 additions and 1332 deletions

View File

@ -38,14 +38,10 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Extensions.WebEnc
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Extensions.WebEncoders.Tests", "test\Microsoft.Extensions.WebEncoders.Tests\Microsoft.Extensions.WebEncoders.Tests.xproj", "{7AE2731D-43CD-4CF8-850A-4914DE2CE930}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Html.Abstractions", "src\Microsoft.AspNet.Html.Abstractions\Microsoft.AspNet.Html.Abstractions.xproj", "{68A28E4A-3ADE-4187-9625-4FF185887CB3}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{982F09D8-621E-4872-BA7B-BBDEA47D1EFD}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "SampleApp", "samples\SampleApp\SampleApp.xproj", "{1D0764B4-1DEB-4232-A714-D4B7E846918A}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Html.Abstractions.Test", "test\Microsoft.AspNet.Html.Abstractions.Test\Microsoft.AspNet.Html.Abstractions.Test.xproj", "{2D187B88-94BD-4A39-AC97-F8F8B9363301}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -224,18 +220,6 @@ Global
{7AE2731D-43CD-4CF8-850A-4914DE2CE930}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{7AE2731D-43CD-4CF8-850A-4914DE2CE930}.Release|x86.ActiveCfg = Release|Any CPU
{7AE2731D-43CD-4CF8-850A-4914DE2CE930}.Release|x86.Build.0 = Release|Any CPU
{68A28E4A-3ADE-4187-9625-4FF185887CB3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{68A28E4A-3ADE-4187-9625-4FF185887CB3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{68A28E4A-3ADE-4187-9625-4FF185887CB3}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{68A28E4A-3ADE-4187-9625-4FF185887CB3}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{68A28E4A-3ADE-4187-9625-4FF185887CB3}.Debug|x86.ActiveCfg = Debug|Any CPU
{68A28E4A-3ADE-4187-9625-4FF185887CB3}.Debug|x86.Build.0 = Debug|Any CPU
{68A28E4A-3ADE-4187-9625-4FF185887CB3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{68A28E4A-3ADE-4187-9625-4FF185887CB3}.Release|Any CPU.Build.0 = Release|Any CPU
{68A28E4A-3ADE-4187-9625-4FF185887CB3}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{68A28E4A-3ADE-4187-9625-4FF185887CB3}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{68A28E4A-3ADE-4187-9625-4FF185887CB3}.Release|x86.ActiveCfg = Release|Any CPU
{68A28E4A-3ADE-4187-9625-4FF185887CB3}.Release|x86.Build.0 = Release|Any CPU
{1D0764B4-1DEB-4232-A714-D4B7E846918A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1D0764B4-1DEB-4232-A714-D4B7E846918A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1D0764B4-1DEB-4232-A714-D4B7E846918A}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
@ -248,18 +232,6 @@ Global
{1D0764B4-1DEB-4232-A714-D4B7E846918A}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{1D0764B4-1DEB-4232-A714-D4B7E846918A}.Release|x86.ActiveCfg = Release|Any CPU
{1D0764B4-1DEB-4232-A714-D4B7E846918A}.Release|x86.Build.0 = Release|Any CPU
{2D187B88-94BD-4A39-AC97-F8F8B9363301}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2D187B88-94BD-4A39-AC97-F8F8B9363301}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2D187B88-94BD-4A39-AC97-F8F8B9363301}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{2D187B88-94BD-4A39-AC97-F8F8B9363301}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{2D187B88-94BD-4A39-AC97-F8F8B9363301}.Debug|x86.ActiveCfg = Debug|Any CPU
{2D187B88-94BD-4A39-AC97-F8F8B9363301}.Debug|x86.Build.0 = Debug|Any CPU
{2D187B88-94BD-4A39-AC97-F8F8B9363301}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2D187B88-94BD-4A39-AC97-F8F8B9363301}.Release|Any CPU.Build.0 = Release|Any CPU
{2D187B88-94BD-4A39-AC97-F8F8B9363301}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{2D187B88-94BD-4A39-AC97-F8F8B9363301}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{2D187B88-94BD-4A39-AC97-F8F8B9363301}.Release|x86.ActiveCfg = Release|Any CPU
{2D187B88-94BD-4A39-AC97-F8F8B9363301}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -281,8 +253,6 @@ Global
{E6BB7AD1-BD10-4A23-B780-F4A86ADF00D1} = {F31FF137-390C-49BF-A3BD-7C6ED3597C21}
{DD2CE416-765E-4000-A03E-C2FF165DA1B6} = {A5A15F1C-885A-452A-A731-B0173DDBD913}
{7AE2731D-43CD-4CF8-850A-4914DE2CE930} = {F31FF137-390C-49BF-A3BD-7C6ED3597C21}
{68A28E4A-3ADE-4187-9625-4FF185887CB3} = {A5A15F1C-885A-452A-A731-B0173DDBD913}
{1D0764B4-1DEB-4232-A714-D4B7E846918A} = {982F09D8-621E-4872-BA7B-BBDEA47D1EFD}
{2D187B88-94BD-4A39-AC97-F8F8B9363301} = {F31FF137-390C-49BF-A3BD-7C6ED3597C21}
EndGlobalSection
EndGlobal

View File

@ -9,7 +9,6 @@
"StrictSemanticVersionValidationRule"
],
"packages": {
"Microsoft.AspNet.Html.Abstractions": { },
"Microsoft.AspNet.Http": { },
"Microsoft.AspNet.Http.Abstractions": { },
"Microsoft.AspNet.Http.Extensions": { },

View File

@ -1,138 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// 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.Encodings.Web;
namespace Microsoft.AspNet.Html.Abstractions
{
/// <summary>
/// An <see cref="IHtmlContentBuilder"/> implementation using an in memory list.
/// </summary>
public class HtmlContentBuilder : IHtmlContentBuilder
{
/// <summary>
/// Creates a new <see cref="HtmlContentBuilder"/>.
/// </summary>
public HtmlContentBuilder()
: this(new List<object>())
{
}
/// <summary>
/// Creates a new <see cref="HtmlContentBuilder"/> with the given initial capacity.
/// </summary>
/// <param name="capacity">The initial capacity of the backing store.</param>
public HtmlContentBuilder(int capacity)
: this(new List<object>(capacity))
{
}
/// <summary>
/// Creates a new <see cref="HtmlContentBuilder"/> with the given list of entries.
/// </summary>
/// <param name="entries">
/// The list of entries. The <see cref="HtmlContentBuilder"/> will use this list without making a copy.
/// </param>
public HtmlContentBuilder(IList<object> entries)
{
if (entries == null)
{
throw new ArgumentNullException(nameof(entries));
}
Entries = entries;
}
// This is not List<IHtmlContent> because that would lead to wrapping all strings to IHtmlContent
// which is not space performant.
//
// In general unencoded strings are added here. We're optimizing for that case, and allocating
// a wrapper when encoded strings are used.
//
// internal for testing.
internal IList<object> Entries { get; }
/// <inheritdoc />
public IHtmlContentBuilder Append(string unencoded)
{
if (!string.IsNullOrEmpty(unencoded))
{
Entries.Add(unencoded);
}
return this;
}
/// <inheritdoc />
public IHtmlContentBuilder Append(IHtmlContent htmlContent)
{
if (htmlContent == null)
{
return this;
}
Entries.Add(htmlContent);
return this;
}
/// <inheritdoc />
public IHtmlContentBuilder AppendHtml(string encoded)
{
if (!string.IsNullOrEmpty(encoded))
{
Entries.Add(new HtmlEncodedString(encoded));
}
return this;
}
/// <inheritdoc />
public IHtmlContentBuilder Clear()
{
Entries.Clear();
return this;
}
/// <inheritdoc />
public void WriteTo(TextWriter writer, HtmlEncoder encoder)
{
if (writer == null)
{
throw new ArgumentNullException(nameof(writer));
}
if (encoder == null)
{
throw new ArgumentNullException(nameof(encoder));
}
for (var i = 0; i < Entries.Count; i++)
{
var entry = Entries[i];
var entryAsString = entry as string;
if (entryAsString != null)
{
encoder.Encode(writer, entryAsString);
}
else
{
// Only string, IHtmlContent values can be added to the buffer.
((IHtmlContent)entry).WriteTo(writer, encoder);
}
}
}
private string DebuggerToString()
{
using (var writer = new StringWriter())
{
WriteTo(writer, HtmlEncoder.Default);
return writer.ToString();
}
}
}
}

View File

@ -1,324 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Text.Encodings.Web;
namespace Microsoft.AspNet.Html.Abstractions
{
/// <summary>
/// Extension methods for <see cref="IHtmlContentBuilder"/>.
/// </summary>
public static class HtmlContentBuilderExtensions
{
/// <summary>
/// Appends the specified <paramref name="format"/> to the existing content after replacing each format
/// item with the HTML encoded <see cref="string"/> representation of the corresponding item in the
/// <paramref name="args"/> array.
/// </summary>
/// <param name="builder">The <see cref="IHtmlContentBuilder"/>.</param>
/// <param name="format">
/// The composite format <see cref="string"/> (see http://msdn.microsoft.com/en-us/library/txafckwd.aspx).
/// The format string is assumed to be HTML encoded as-provided, and no further encoding will be performed.
/// </param>
/// <param name="args">
/// The object array to format. Each element in the array will be formatted and then HTML encoded.
/// </param>
/// <returns>A reference to this instance after the append operation has completed.</returns>
public static IHtmlContentBuilder AppendFormat(
this IHtmlContentBuilder builder,
string format,
params object[] args)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
if (format == null)
{
throw new ArgumentNullException(nameof(format));
}
if (args == null)
{
throw new ArgumentNullException(nameof(args));
}
builder.Append(new HtmlFormatString(format, args));
return builder;
}
/// <summary>
/// Appends the specified <paramref name="format"/> to the existing content with information from the
/// <paramref name="formatProvider"/> after replacing each format item with the HTML encoded
/// <see cref="string"/> representation of the corresponding item in the <paramref name="args"/> array.
/// </summary>
/// <param name="builder">The <see cref="IHtmlContentBuilder"/>.</param>
/// <param name="formatProvider">An object that supplies culture-specific formatting information.</param>
/// <param name="format">
/// The composite format <see cref="string"/> (see http://msdn.microsoft.com/en-us/library/txafckwd.aspx).
/// The format string is assumed to be HTML encoded as-provided, and no further encoding will be performed.
/// </param>
/// <param name="args">
/// The object array to format. Each element in the array will be formatted and then HTML encoded.
/// </param>
/// <returns>A reference to this instance after the append operation has completed.</returns>
public static IHtmlContentBuilder AppendFormat(
this IHtmlContentBuilder builder,
IFormatProvider formatProvider,
string format,
params object[] args)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
if (format == null)
{
throw new ArgumentNullException(nameof(format));
}
if (args == null)
{
throw new ArgumentNullException(nameof(args));
}
builder.Append(new HtmlFormatString(formatProvider, format, args));
return builder;
}
/// <summary>
/// Appends an <see cref="Environment.NewLine"/>.
/// </summary>
/// <param name="builder">The <see cref="IHtmlContentBuilder"/>.</param>
/// <returns>The <see cref="IHtmlContentBuilder"/>.</returns>
public static IHtmlContentBuilder AppendLine(this IHtmlContentBuilder builder)
{
builder.Append(HtmlEncodedString.NewLine);
return builder;
}
/// <summary>
/// Appends an <see cref="Environment.NewLine"/> after appending the <see cref="string"/> value.
/// The value is treated as unencoded as-provided, and will be HTML encoded before writing to output.
/// </summary>
/// <param name="builder">The <see cref="IHtmlContentBuilder"/>.</param>
/// <param name="unencoded">The <see cref="string"/> to append.</param>
/// <returns>The <see cref="IHtmlContentBuilder"/>.</returns>
public static IHtmlContentBuilder AppendLine(this IHtmlContentBuilder builder, string unencoded)
{
builder.Append(unencoded);
builder.Append(HtmlEncodedString.NewLine);
return builder;
}
/// <summary>
/// Appends an <see cref="Environment.NewLine"/> after appending the <see cref="IHtmlContent"/> value.
/// </summary>
/// <param name="builder">The <see cref="IHtmlContentBuilder"/>.</param>
/// <param name="content">The <see cref="IHtmlContent"/> to append.</param>
/// <returns>The <see cref="IHtmlContentBuilder"/>.</returns>
public static IHtmlContentBuilder AppendLine(this IHtmlContentBuilder builder, IHtmlContent content)
{
builder.Append(content);
builder.Append(HtmlEncodedString.NewLine);
return builder;
}
/// <summary>
/// Appends an <see cref="Environment.NewLine"/> after appending the <see cref="string"/> value.
/// The value is treated as HTML encoded as-provided, and no further encoding will be performed.
/// </summary>
/// <param name="builder">The <see cref="IHtmlContentBuilder"/>.</param>
/// <param name="encoded">The HTML encoded <see cref="string"/> to append.</param>
/// <returns>The <see cref="IHtmlContentBuilder"/>.</returns>
public static IHtmlContentBuilder AppendHtmlLine(this IHtmlContentBuilder builder, string encoded)
{
builder.AppendHtml(encoded);
builder.Append(HtmlEncodedString.NewLine);
return builder;
}
/// <summary>
/// Sets the content to the <see cref="string"/> value. The value is treated as unencoded as-provided,
/// and will be HTML encoded before writing to output.
/// </summary>
/// <param name="builder">The <see cref="IHtmlContentBuilder"/>.</param>
/// <param name="unencoded">The <see cref="string"/> value that replaces the content.</param>
/// <returns>The <see cref="IHtmlContentBuilder"/>.</returns>
public static IHtmlContentBuilder SetContent(this IHtmlContentBuilder builder, string unencoded)
{
builder.Clear();
builder.Append(unencoded);
return builder;
}
/// <summary>
/// Sets the content to the <see cref="IHtmlContent"/> value.
/// </summary>
/// <param name="builder">The <see cref="IHtmlContentBuilder"/>.</param>
/// <param name="content">The <see cref="IHtmlContent"/> value that replaces the content.</param>
/// <returns>The <see cref="IHtmlContentBuilder"/>.</returns>
public static IHtmlContentBuilder SetContent(this IHtmlContentBuilder builder, IHtmlContent content)
{
builder.Clear();
builder.Append(content);
return builder;
}
/// <summary>
/// Sets the content to the <see cref="string"/> value. The value is treated as HTML encoded as-provided, and
/// no further encoding will be performed.
/// </summary>
/// <param name="builder">The <see cref="IHtmlContentBuilder"/>.</param>
/// <param name="encoded">The HTML encoded <see cref="string"/> that replaces the content.</param>
/// <returns>The <see cref="IHtmlContentBuilder"/>.</returns>
public static IHtmlContentBuilder SetHtmlContent(this IHtmlContentBuilder builder, string encoded)
{
builder.Clear();
builder.AppendHtml(encoded);
return builder;
}
[DebuggerDisplay("{DebuggerToString()}")]
private class HtmlFormatString : IHtmlContent
{
private readonly IFormatProvider _formatProvider;
private readonly string _format;
private readonly object[] _args;
public HtmlFormatString(string format, object[] args)
: this(null, format, args)
{
}
public HtmlFormatString(IFormatProvider formatProvider, string format, object[] args)
{
Debug.Assert(format != null);
Debug.Assert(args != null);
_formatProvider = formatProvider ?? CultureInfo.CurrentCulture;
_format = format;
_args = args;
}
public void WriteTo(TextWriter writer, HtmlEncoder encoder)
{
if (writer == null)
{
throw new ArgumentNullException(nameof(writer));
}
if (encoder == null)
{
throw new ArgumentNullException(nameof(encoder));
}
var formatProvider = new EncodingFormatProvider(_formatProvider, encoder);
writer.Write(string.Format(formatProvider, _format, _args));
}
private string DebuggerToString()
{
using (var writer = new StringWriter())
{
WriteTo(writer, HtmlEncoder.Default);
return writer.ToString();
}
}
}
// This class implements Html encoding via an ICustomFormatter. Passing an instance of this
// class into a string.Format method or anything similar will evaluate arguments implementing
// IHtmlContent without HTML encoding them, and will give other arguments the standard
// composite format string treatment, and then HTML encode the result.
//
// Plenty of examples of ICustomFormatter and the interactions with string.Format here:
// https://msdn.microsoft.com/en-us/library/system.string.format(v=vs.110).aspx#Format6_Example
private class EncodingFormatProvider : IFormatProvider, ICustomFormatter
{
private readonly HtmlEncoder _encoder;
private readonly IFormatProvider _formatProvider;
public EncodingFormatProvider(IFormatProvider formatProvider, HtmlEncoder encoder)
{
Debug.Assert(formatProvider != null);
Debug.Assert(encoder != null);
_formatProvider = formatProvider;
_encoder = encoder;
}
public string Format(string format, object arg, IFormatProvider formatProvider)
{
// This is the case we need to special case. We trust the IHtmlContent instance to do the
// right thing with encoding.
var htmlContent = arg as IHtmlContent;
if (htmlContent != null)
{
using (var writer = new StringWriter())
{
htmlContent.WriteTo(writer, _encoder);
return writer.ToString();
}
}
// If we get here then 'arg' is not an IHtmlContent, and we want to handle it the way a normal
// string.Format would work, but then HTML encode the result.
//
// First check for an ICustomFormatter - if the IFormatProvider is a CultureInfo, then it's likely
// that ICustomFormatter will be null.
var customFormatter = (ICustomFormatter)_formatProvider.GetFormat(typeof(ICustomFormatter));
if (customFormatter != null)
{
var result = customFormatter.Format(format, arg, _formatProvider);
if (result != null)
{
return _encoder.Encode(result);
}
}
// Next check if 'arg' is an IFormattable (DateTime is an example).
//
// An IFormattable will likely call back into the IFormatterProvider and ask for more information
// about how to format itself. This is the typical case when IFormatterProvider is a CultureInfo.
var formattable = arg as IFormattable;
if (formattable != null)
{
var result = formattable.ToString(format, _formatProvider);
if (result != null)
{
return _encoder.Encode(result);
}
}
// If we get here then there's nothing really smart left to try.
if (arg != null)
{
var result = arg.ToString();
if (result != null)
{
return _encoder.Encode(result);
}
}
return string.Empty;
}
public object GetFormat(Type formatType)
{
if (formatType == typeof(ICustomFormatter))
{
return this;
}
return null;
}
}
}
}

View File

@ -1,49 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Diagnostics;
using System.IO;
using System.Text.Encodings.Web;
namespace Microsoft.AspNet.Html.Abstractions
{
/// <summary>
/// An <see cref="IHtmlContent"/> impelementation that wraps an HTML encoded <see cref="string"/>.
/// </summary>
[DebuggerDisplay("{DebuggerToString()}")]
public class HtmlEncodedString : IHtmlContent
{
/// <summary>
/// An <see cref="IHtmlContent"/> instance for <see cref="Environment.NewLine"/>.
/// </summary>
public static readonly IHtmlContent NewLine = new HtmlEncodedString(Environment.NewLine);
private readonly string _value;
/// <summary>
/// Creates a new <see cref="HtmlEncodedString"/>.
/// </summary>
/// <param name="value">The HTML encoded value.</param>
public HtmlEncodedString(string value)
{
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
_value = value;
}
/// <inheritdoc />
public void WriteTo(TextWriter writer, HtmlEncoder encoder)
{
writer.Write(_value);
}
private string DebuggerToString()
{
return _value;
}
}
}

View File

@ -1,49 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.IO;
namespace Microsoft.AspNet.Html.Abstractions
{
/// <summary>
/// A <see cref="TextWriter"/> which supports special processing of <see cref="IHtmlContent"/>.
/// </summary>
public abstract class HtmlTextWriter : TextWriter
{
/// <summary>
/// Writes an <see cref="IHtmlContent"/> value.
/// </summary>
/// <param name="value">The <see cref="IHtmlContent"/> value.</param>
public abstract void Write(IHtmlContent value);
/// <inheritdoc />
public override void Write(object value)
{
var htmlContent = value as IHtmlContent;
if (htmlContent == null)
{
base.Write(value);
}
else
{
Write(htmlContent);
}
}
/// <inheritdoc />
public override void WriteLine(object value)
{
var htmlContent = value as IHtmlContent;
if (htmlContent == null)
{
base.Write(value);
}
else
{
Write(htmlContent);
}
base.WriteLine();
}
}
}

View File

@ -1,22 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.IO;
using System.Text.Encodings.Web;
namespace Microsoft.AspNet.Html.Abstractions
{
/// <summary>
/// HTML content which can be written to a TextWriter.
/// </summary>
public interface IHtmlContent
{
/// <summary>
/// Writes the content by encoding it with the specified <paramref name="encoder"/>
/// to the specified <paramref name="writer"/>.
/// </summary>
/// <param name="writer">The <see cref="TextWriter"/> to which the content is written.</param>
/// <param name="encoder">The <see cref="HtmlEncoder"/> which encodes the content to be written.</param>
void WriteTo(TextWriter writer, HtmlEncoder encoder);
}
}

View File

@ -1,40 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNet.Html.Abstractions
{
/// <summary>
/// A builder for HTML content.
/// </summary>
public interface IHtmlContentBuilder : IHtmlContent
{
/// <summary>
/// Appends an <see cref="IHtmlContent"/> instance.
/// </summary>
/// <param name="content">The <see cref="IHtmlContent"/> to append.</param>
/// <returns>The <see cref="IHtmlContentBuilder"/>.</returns>
IHtmlContentBuilder Append(IHtmlContent content);
/// <summary>
/// Appends a <see cref="string"/> value. The value is treated as unencoded as-provided, and will be HTML
/// encoded before writing to output.
/// </summary>
/// <param name="unencoded">The <see cref="string"/> to append.</param>
/// <returns>The <see cref="IHtmlContentBuilder"/>.</returns>
IHtmlContentBuilder Append(string unencoded);
/// <summary>
/// Appends an HTML encoded <see cref="string"/> value. The value is treated as HTML encoded as-provided, and
/// no further encoding will be performed.
/// </summary>
/// <param name="encoded">The HTML encoded <see cref="string"/> to append.</param>
/// <returns>The <see cref="IHtmlContentBuilder"/>.</returns>
IHtmlContentBuilder AppendHtml(string encoded);
/// <summary>
/// Clears the content.
/// </summary>
/// <returns>The <see cref="IHtmlContentBuilder"/>.</returns>
IHtmlContentBuilder Clear();
}
}

View File

@ -1,19 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>68a28e4a-3ade-4187-9625-4ff185887cb3</ProjectGuid>
<RootNamespace>Microsoft.AspNet.Html.Abstractions</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

View File

@ -1,10 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
[assembly: AssemblyMetadata("Serviceable", "True")]
[assembly: NeutralResourcesLanguage("en-us")]
[assembly: InternalsVisibleTo("Microsoft.AspNet.Html.Abstractions.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]

View File

@ -1,29 +0,0 @@
{
"version": "1.0.0-*",
"description": "ASP.NET 5 HTML content interface.",
"repository": {
"type": "git",
"url": "git://github.com/aspnet/httpabstractions"
},
"compilationOptions": {
"warningsAsErrors": true,
"keyFile": "../../tools/Key.snk"
},
"dependencies": {
"System.Text.Encodings.Web": "4.0.0-*"
},
"frameworks": {
"net451": {
"frameworkAssemblies": {
"System.IO": "",
"System.Runtime": ""
}
},
"dotnet5.4": {
"dependencies": {
"System.Collections": "4.0.11-*",
"System.Resources.ResourceManager": "4.0.1-*"
}
}
}
}

View File

@ -1,436 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// 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.Globalization;
using System.IO;
using System.Text.Encodings.Web;
using Microsoft.AspNet.Testing;
using Microsoft.Extensions.WebEncoders.Testing;
using Xunit;
namespace Microsoft.AspNet.Html.Abstractions.Test
{
public class HtmlContentBuilderExtensionsTest
{
[Fact]
public void Builder_AppendLine_Empty()
{
// Arrange
var builder = new TestHtmlContentBuilder();
// Act
builder.AppendLine();
// Assert
Assert.Collection(
builder.Entries,
entry => Assert.Equal(Environment.NewLine, HtmlContentToString(entry)));
}
[Fact]
public void Builder_AppendLine_String()
{
// Arrange
var builder = new TestHtmlContentBuilder();
// Act
builder.AppendLine("Hi");
// Assert
Assert.Collection(
builder.Entries,
entry => Assert.Equal("Hi", Assert.IsType<UnencodedString>(entry).Value),
entry => Assert.Equal(Environment.NewLine, HtmlContentToString(entry)));
}
[Fact]
public void Builder_AppendLine_IHtmlContent()
{
// Arrange
var builder = new TestHtmlContentBuilder();
var content = new OtherHtmlContent("Hi");
// Act
builder.AppendLine(content);
// Assert
Assert.Collection(
builder.Entries,
entry => Assert.Same(content, entry),
entry => Assert.Equal(Environment.NewLine, HtmlContentToString(entry)));
}
[Fact]
public void Builder_AppendHtmlLine_String()
{
// Arrange
var builder = new TestHtmlContentBuilder();
// Act
builder.AppendHtmlLine("Hi");
// Assert
Assert.Collection(
builder.Entries,
entry => Assert.Equal("Hi", Assert.IsType<EncodedString>(entry).Value),
entry => Assert.Equal(Environment.NewLine, HtmlContentToString(entry)));
}
[Fact]
public void Builder_SetContent_String()
{
// Arrange
var builder = new TestHtmlContentBuilder();
builder.Append("Existing Content. Will be Cleared.");
// Act
builder.SetContent("Hi");
// Assert
Assert.Collection(
builder.Entries,
entry => Assert.Equal("Hi", Assert.IsType<UnencodedString>(entry).Value));
}
[Fact]
public void Builder_SetContent_IHtmlContent()
{
// Arrange
var builder = new TestHtmlContentBuilder();
builder.Append("Existing Content. Will be Cleared.");
var content = new OtherHtmlContent("Hi");
// Act
builder.SetContent(content);
// Assert
Assert.Collection(
builder.Entries,
entry => Assert.Same(content, entry));
}
[Fact]
public void Builder_SetHtmlContent_String()
{
// Arrange
var builder = new TestHtmlContentBuilder();
builder.Append("Existing Content. Will be Cleared.");
// Act
builder.SetHtmlContent("Hi");
// Assert
Assert.Collection(
builder.Entries,
entry => Assert.Equal("Hi", Assert.IsType<EncodedString>(entry).Value));
}
[Fact]
public void Builder_AppendFormat()
{
// Arrange
var builder = new TestHtmlContentBuilder();
// Act
builder.AppendFormat("{0} {1} {2} {3}!", "First", "Second", "Third", "Fourth");
// Assert
Assert.Equal(
"HtmlEncode[[First]] HtmlEncode[[Second]] HtmlEncode[[Third]] HtmlEncode[[Fourth]]!",
HtmlContentToString(builder));
}
[Fact]
public void Builder_AppendFormat_HtmlContent()
{
// Arrange
var builder = new TestHtmlContentBuilder();
// Act
builder.AppendFormat("{0}!", new EncodedString("First"));
// Assert
Assert.Equal(
"First!",
HtmlContentToString(builder));
}
[Fact]
public void Builder_AppendFormatContent_With1Argument()
{
// Arrange
var builder = new TestHtmlContentBuilder();
// Act
builder.AppendFormat("0x{0:X} - hex equivalent for 50.", 50);
// Assert
Assert.Equal(
"0xHtmlEncode[[32]] - hex equivalent for 50.",
HtmlContentToString(builder));
}
[Fact]
public void Builder_AppendFormatContent_With2Arguments()
{
// Arrange
var builder = new TestHtmlContentBuilder();
// Act
builder.AppendFormat("0x{0:X} - hex equivalent for {1}.", 50, 50);
// Assert
Assert.Equal(
"0xHtmlEncode[[32]] - hex equivalent for HtmlEncode[[50]].",
HtmlContentToString(builder));
}
[Fact]
public void Builder_AppendFormatContent_With3Arguments()
{
// Arrange
var builder = new TestHtmlContentBuilder();
// Act
builder.AppendFormat("0x{0:X} - {1} equivalent for {2}.", 50, "hex", 50);
// Assert
Assert.Equal(
"0xHtmlEncode[[32]] - HtmlEncode[[hex]] equivalent for HtmlEncode[[50]].",
HtmlContentToString(builder));
}
[Fact]
public void Builder_AppendFormat_WithAlignmentComponent()
{
// Arrange
var builder = new TestHtmlContentBuilder();
// Act
builder.AppendFormat("{0, -25} World!", "Hello");
// Assert
Assert.Equal(
"HtmlEncode[[Hello]] World!",
HtmlContentToString(builder));
}
[Fact]
public void Builder_AppendFormat_WithFormatStringComponent()
{
// Arrange
var builder = new TestHtmlContentBuilder();
// Act
builder.AppendFormat("0x{0:X}", 50);
// Assert
Assert.Equal("0xHtmlEncode[[32]]", HtmlContentToString(builder));
}
[Fact]
public void Builder_AppendFormat_WithCulture()
{
// Arrange
var builder = new TestHtmlContentBuilder();
// Act
builder.AppendFormat(
CultureInfo.InvariantCulture,
"Numbers in InvariantCulture - {0, -5:N} {1} {2} {3}!",
1.1,
2.98,
145.82,
32.86);
// Assert
Assert.Equal(
"Numbers in InvariantCulture - HtmlEncode[[1.10]] HtmlEncode[[2.98]] " +
"HtmlEncode[[145.82]] HtmlEncode[[32.86]]!",
HtmlContentToString(builder));
}
[Fact]
public void Builder_AppendFormat_WithCulture_1Argument()
{
// Arrange
var builder = new TestHtmlContentBuilder();
// Act
builder.AppendFormat(
CultureInfo.InvariantCulture,
"Numbers in InvariantCulture - {0:N}!",
1.1);
// Assert
Assert.Equal(
"Numbers in InvariantCulture - HtmlEncode[[1.10]]!",
HtmlContentToString(builder));
}
[Fact]
public void Builder_AppendFormat_WithCulture_2Arguments()
{
// Arrange
var builder = new TestHtmlContentBuilder();
// Act
builder.AppendFormat(
CultureInfo.InvariantCulture,
"Numbers in InvariantCulture - {0:N} {1}!",
1.1,
2.98);
// Assert
Assert.Equal(
"Numbers in InvariantCulture - HtmlEncode[[1.10]] HtmlEncode[[2.98]]!",
HtmlContentToString(builder));
}
[Fact]
public void Builder_AppendFormat_WithCulture_3Arguments()
{
// Arrange
var builder = new TestHtmlContentBuilder();
// Act
builder.AppendFormat(
CultureInfo.InvariantCulture,
"Numbers in InvariantCulture - {0:N} {1} {2}!",
1.1,
2.98,
3.12);
// Assert
Assert.Equal(
"Numbers in InvariantCulture - HtmlEncode[[1.10]] HtmlEncode[[2.98]] HtmlEncode[[3.12]]!",
HtmlContentToString(builder));
}
[Fact]
public void Builder_AppendFormat_WithDifferentCulture()
{
// Arrange
var builder = new TestHtmlContentBuilder();
var culture = new CultureInfo("fr-FR");
// Act
builder.AppendFormat(culture, "{0} in french!", 1.21);
// Assert
Assert.Equal(
"HtmlEncode[[1,21]] in french!",
HtmlContentToString(builder));
}
[Fact]
[ReplaceCulture("de-DE", "de-DE")]
public void Builder_AppendFormat_WithDifferentCurrentCulture()
{
// Arrange
var builder = new TestHtmlContentBuilder();
// Act
builder.AppendFormat(CultureInfo.CurrentCulture, "{0:D}", DateTime.Parse("01/02/2015"));
// Assert
Assert.Equal(
"HtmlEncode[[Sonntag, 1. Februar 2015]]",
HtmlContentToString(builder));
}
private static string HtmlContentToString(IHtmlContent content)
{
using (var writer = new StringWriter())
{
content.WriteTo(writer, new HtmlTestEncoder());
return writer.ToString();
}
}
private class TestHtmlContentBuilder : IHtmlContentBuilder
{
public List<IHtmlContent> Entries { get; } = new List<IHtmlContent>();
public IHtmlContentBuilder Append(string unencoded)
{
Entries.Add(new UnencodedString(unencoded));
return this;
}
public IHtmlContentBuilder Append(IHtmlContent content)
{
Entries.Add(content);
return this;
}
public IHtmlContentBuilder AppendHtml(string encoded)
{
Entries.Add(new EncodedString(encoded));
return this;
}
public IHtmlContentBuilder Clear()
{
Entries.Clear();
return this;
}
public void WriteTo(TextWriter writer, HtmlEncoder encoder)
{
foreach (var entry in Entries)
{
entry.WriteTo(writer, encoder);
}
}
}
private class EncodedString : IHtmlContent
{
public EncodedString(string value)
{
Value = value;
}
public string Value { get; }
public void WriteTo(TextWriter writer, HtmlEncoder encoder)
{
writer.Write(Value);
}
}
private class UnencodedString : IHtmlContent
{
public UnencodedString(string value)
{
Value = value;
}
public string Value { get; }
public void WriteTo(TextWriter writer, HtmlEncoder encoder)
{
encoder.Encode(writer, Value);
}
}
private class OtherHtmlContent : IHtmlContent
{
public OtherHtmlContent(string value)
{
Value = value;
}
public string Value { get; }
public void WriteTo(TextWriter writer, HtmlEncoder encoder)
{
throw new NotImplementedException();
}
}
}
}

View File

@ -1,145 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.IO;
using System.Text.Encodings.Web;
using Microsoft.AspNet.Html.Abstractions;
using Microsoft.Extensions.WebEncoders.Testing;
using Xunit;
namespace Microsoft.Extensions.Internal
{
public class HtmlContentBuilderTest
{
[Fact]
public void AppendString_AppendsAString()
{
// Arrange
var content = new HtmlContentBuilder();
// Act
content.Append("Hello");
// Assert
var result = Assert.Single(content.Entries);
Assert.IsType<string>(result);
}
[Fact]
public void AppendString_WrittenAsEncoded()
{
// Arrange
var content = new HtmlContentBuilder();
content.Append("Hello");
var writer = new StringWriter();
// Act
content.WriteTo(writer, new HtmlTestEncoder());
// Assert
Assert.Equal("HtmlEncode[[Hello]]", writer.ToString());
}
[Fact]
public void AppendHtml_DoesNotGetWrittenAsEncoded()
{
// Arrange
var content = new HtmlContentBuilder();
content.AppendHtml("Hello");
var writer = new StringWriter();
// Act
content.WriteTo(writer, new HtmlTestEncoder());
// Assert
Assert.Equal("Hello", writer.ToString());
}
[Fact]
public void AppendIHtmlContent_AppendsAsIs()
{
// Arrange
var content = new HtmlContentBuilder();
var writer = new StringWriter();
// Act
content.Append(new TestHtmlContent("Hello"));
// Assert
var result = Assert.Single(content.Entries);
var testHtmlContent = Assert.IsType<TestHtmlContent>(result);
testHtmlContent.WriteTo(writer, new HtmlTestEncoder());
Assert.Equal("Written from TestHtmlContent: Hello", writer.ToString());
}
[Fact]
public void CanAppendMultipleItems()
{
// Arrange
var content = new HtmlContentBuilder();
// Act
content.Append(new TestHtmlContent("hello"));
content.Append("Test");
// Assert
Assert.Equal(2, content.Entries.Count);
Assert.Equal("Written from TestHtmlContent: hello", content.Entries[0].ToString());
Assert.Equal("Test", content.Entries[1]);
}
[Fact]
public void Clear_DeletesAllItems()
{
// Arrange
var content = new HtmlContentBuilder();
content.Append(new TestHtmlContent("hello"));
content.Append("Test");
// Act
content.Clear();
// Assert
Assert.Equal(0, content.Entries.Count);
}
[Fact]
public void WriteTo_WritesAllItems()
{
// Arrange
var content = new HtmlContentBuilder();
var writer = new StringWriter();
content.Append(new TestHtmlContent("Hello"));
content.Append("Test");
// Act
content.WriteTo(writer, new HtmlTestEncoder());
// Assert
Assert.Equal(2, content.Entries.Count);
Assert.Equal("Written from TestHtmlContent: HelloHtmlEncode[[Test]]", writer.ToString());
}
private class TestHtmlContent : IHtmlContent
{
private string _content;
public TestHtmlContent(string content)
{
_content = content;
}
public void WriteTo(TextWriter writer, HtmlEncoder encoder)
{
writer.Write(ToString());
}
public override string ToString()
{
return "Written from TestHtmlContent: " + _content;
}
}
}
}

View File

@ -1,21 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>2d187b88-94bd-4a39-ac97-f8f8b9363301</ProjectGuid>
<RootNamespace>Microsoft.AspNet.Html.Abstractions.Test</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<ItemGroup>
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
</ItemGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

View File

@ -1,19 +0,0 @@
{
"compilationOptions": {
"warningsAsErrors": true,
"keyFile": "../../tools/Key.snk"
},
"dependencies": {
"Microsoft.AspNet.Html.Abstractions": "1.0.0-*",
"Microsoft.AspNet.Testing": "1.0.0-*",
"Microsoft.Extensions.WebEncoders": "1.0.0-*",
"xunit.runner.aspnet": "2.0.0-aspnet-*"
},
"commands": {
"test": "xunit.runner.aspnet"
},
"frameworks": {
"dnx451": { },
"dnxcore50": { }
}
}