Initial commit
This commit is contained in:
parent
b14fa9d990
commit
f9661e2bf1
|
|
@ -0,0 +1,50 @@
|
||||||
|
*.doc diff=astextplain
|
||||||
|
*.DOC diff=astextplain
|
||||||
|
*.docx diff=astextplain
|
||||||
|
*.DOCX diff=astextplain
|
||||||
|
*.dot diff=astextplain
|
||||||
|
*.DOT diff=astextplain
|
||||||
|
*.pdf diff=astextplain
|
||||||
|
*.PDF diff=astextplain
|
||||||
|
*.rtf diff=astextplain
|
||||||
|
*.RTF diff=astextplain
|
||||||
|
|
||||||
|
*.jpg binary
|
||||||
|
*.png binary
|
||||||
|
*.gif binary
|
||||||
|
|
||||||
|
*.cs text=auto diff=csharp
|
||||||
|
*.vb text=auto
|
||||||
|
*.resx text=auto
|
||||||
|
*.c text=auto
|
||||||
|
*.cpp text=auto
|
||||||
|
*.cxx text=auto
|
||||||
|
*.h text=auto
|
||||||
|
*.hxx text=auto
|
||||||
|
*.py text=auto
|
||||||
|
*.rb text=auto
|
||||||
|
*.java text=auto
|
||||||
|
*.html text=auto
|
||||||
|
*.htm text=auto
|
||||||
|
*.css text=auto
|
||||||
|
*.scss text=auto
|
||||||
|
*.sass text=auto
|
||||||
|
*.less text=auto
|
||||||
|
*.js text=auto
|
||||||
|
*.lisp text=auto
|
||||||
|
*.clj text=auto
|
||||||
|
*.sql text=auto
|
||||||
|
*.php text=auto
|
||||||
|
*.lua text=auto
|
||||||
|
*.m text=auto
|
||||||
|
*.asm text=auto
|
||||||
|
*.erl text=auto
|
||||||
|
*.fs text=auto
|
||||||
|
*.fsx text=auto
|
||||||
|
*.hs text=auto
|
||||||
|
|
||||||
|
*.csproj text=auto
|
||||||
|
*.vbproj text=auto
|
||||||
|
*.fsproj text=auto
|
||||||
|
*.dbproj text=auto
|
||||||
|
*.sln text=auto eol=crlf
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
[Oo]bj/
|
||||||
|
[Bb]in/
|
||||||
|
TestResults/
|
||||||
|
.nuget/
|
||||||
|
_ReSharper.*/
|
||||||
|
packages/
|
||||||
|
artifacts/
|
||||||
|
PublishProfiles/
|
||||||
|
*.user
|
||||||
|
*.suo
|
||||||
|
*.cache
|
||||||
|
*.docstates
|
||||||
|
_ReSharper.*
|
||||||
|
nuget.exe
|
||||||
|
*net45.csproj
|
||||||
|
*net451.csproj
|
||||||
|
*k10.csproj
|
||||||
|
*.psess
|
||||||
|
*.vsp
|
||||||
|
*.pidb
|
||||||
|
*.userprefs
|
||||||
|
*DS_Store
|
||||||
|
*.ncrunchsolution
|
||||||
|
*.*sdf
|
||||||
|
*.ipch
|
||||||
|
*.sln.ide
|
||||||
|
project.lock.json
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
language: csharp
|
||||||
|
sudo: required
|
||||||
|
dist: trusty
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- gettext
|
||||||
|
- libcurl4-openssl-dev
|
||||||
|
- libicu-dev
|
||||||
|
- libssl-dev
|
||||||
|
- libunwind8
|
||||||
|
- zlib1g
|
||||||
|
env:
|
||||||
|
- KOREBUILD_DNU_RESTORE_CORECLR=true KOREBUILD_TEST_DNXCORE=true
|
||||||
|
mono:
|
||||||
|
- 4.0.5
|
||||||
|
script:
|
||||||
|
- ./build.sh --quiet verify
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio 14
|
||||||
|
VisualStudioVersion = 14.0.24711.0
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{A5A15F1C-885A-452A-A731-B0173DDBD913}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{F31FF137-390C-49BF-A3BD-7C6ED3597C21}"
|
||||||
|
EndProject
|
||||||
|
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Html", "src\Microsoft.AspNet.Html.Abstractions\Microsoft.AspNet.Html.xproj", "{68A28E4A-3ADE-4187-9625-4FF185887CB3}"
|
||||||
|
EndProject
|
||||||
|
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Html.Test", "test\Microsoft.AspNet.Html.Abstractions.Test\Microsoft.AspNet.Html.Test.xproj", "{2D187B88-94BD-4A39-AC97-F8F8B9363301}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Debug|Mixed Platforms = Debug|Mixed Platforms
|
||||||
|
Debug|x86 = Debug|x86
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
Release|Mixed Platforms = Release|Mixed Platforms
|
||||||
|
Release|x86 = Release|x86
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{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
|
||||||
|
{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
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(NestedProjects) = preSolution
|
||||||
|
{68A28E4A-3ADE-4187-9625-4FF185887CB3} = {A5A15F1C-885A-452A-A731-B0173DDBD913}
|
||||||
|
{2D187B88-94BD-4A39-AC97-F8F8B9363301} = {F31FF137-390C-49BF-A3BD-7C6ED3597C21}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<configuration>
|
||||||
|
<packageSources>
|
||||||
|
<add key="AspNetVNext" value="https://www.myget.org/F/aspnetcidev/api/v3/index.json" />
|
||||||
|
<add key="NuGet" value="https://api.nuget.org/v3/index.json" />
|
||||||
|
</packageSources>
|
||||||
|
</configuration>
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
"adx": { // Packages written by the ADX team and that ship on NuGet.org
|
||||||
|
"rules": [
|
||||||
|
"AssemblyHasDocumentFileRule",
|
||||||
|
"AssemblyHasVersionAttributesRule",
|
||||||
|
"AssemblyHasServicingAttributeRule",
|
||||||
|
"AssemblyHasNeutralResourcesLanguageAttributeRule",
|
||||||
|
"SatellitePackageRule",
|
||||||
|
"StrictSemanticVersionValidationRule"
|
||||||
|
],
|
||||||
|
"packages": {
|
||||||
|
"Microsoft.AspNet.Html.Abstractions": { }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Default": { // Rules to run for packages not listed in any other set.
|
||||||
|
"rules": [
|
||||||
|
"AssemblyHasDocumentFileRule",
|
||||||
|
"AssemblyHasVersionAttributesRule",
|
||||||
|
"AssemblyHasServicingAttributeRule",
|
||||||
|
"AssemblyHasNeutralResourcesLanguageAttributeRule",
|
||||||
|
"SatellitePackageRule",
|
||||||
|
"StrictSemanticVersionValidationRule"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
init:
|
||||||
|
- git config --global core.autocrlf true
|
||||||
|
build_script:
|
||||||
|
- build.cmd --quiet verify
|
||||||
|
clone_depth: 1
|
||||||
|
test: off
|
||||||
|
deploy: off
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
@echo off
|
||||||
|
cd %~dp0
|
||||||
|
|
||||||
|
SETLOCAL
|
||||||
|
SET NUGET_VERSION=latest
|
||||||
|
SET CACHED_NUGET=%LocalAppData%\NuGet\nuget.%NUGET_VERSION%.exe
|
||||||
|
SET BUILDCMD_KOREBUILD_VERSION=
|
||||||
|
SET BUILDCMD_DNX_VERSION=
|
||||||
|
|
||||||
|
IF EXIST %CACHED_NUGET% goto copynuget
|
||||||
|
echo Downloading latest version of NuGet.exe...
|
||||||
|
IF NOT EXIST %LocalAppData%\NuGet md %LocalAppData%\NuGet
|
||||||
|
@powershell -NoProfile -ExecutionPolicy unrestricted -Command "$ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest 'https://dist.nuget.org/win-x86-commandline/%NUGET_VERSION%/nuget.exe' -OutFile '%CACHED_NUGET%'"
|
||||||
|
|
||||||
|
:copynuget
|
||||||
|
IF EXIST .nuget\nuget.exe goto restore
|
||||||
|
md .nuget
|
||||||
|
copy %CACHED_NUGET% .nuget\nuget.exe > nul
|
||||||
|
|
||||||
|
:restore
|
||||||
|
IF EXIST packages\Sake goto getdnx
|
||||||
|
IF "%BUILDCMD_KOREBUILD_VERSION%"=="" (
|
||||||
|
.nuget\nuget.exe install KoreBuild -ExcludeVersion -o packages -nocache -pre
|
||||||
|
) ELSE (
|
||||||
|
.nuget\nuget.exe install KoreBuild -version %BUILDCMD_KOREBUILD_VERSION% -ExcludeVersion -o packages -nocache -pre
|
||||||
|
)
|
||||||
|
.nuget\NuGet.exe install Sake -ExcludeVersion -Source https://www.nuget.org/api/v2/ -Out packages
|
||||||
|
|
||||||
|
:getdnx
|
||||||
|
IF "%BUILDCMD_DNX_VERSION%"=="" (
|
||||||
|
SET BUILDCMD_DNX_VERSION=latest
|
||||||
|
)
|
||||||
|
IF "%SKIP_DNX_INSTALL%"=="" (
|
||||||
|
CALL packages\KoreBuild\build\dnvm install %BUILDCMD_DNX_VERSION% -runtime CoreCLR -arch x86 -alias default
|
||||||
|
CALL packages\KoreBuild\build\dnvm install default -runtime CLR -arch x86 -alias default
|
||||||
|
) ELSE (
|
||||||
|
CALL packages\KoreBuild\build\dnvm use default -runtime CLR -arch x86
|
||||||
|
)
|
||||||
|
|
||||||
|
packages\Sake\tools\Sake.exe -I packages\KoreBuild\build -f makefile.shade %*
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
if test `uname` = Darwin; then
|
||||||
|
cachedir=~/Library/Caches/KBuild
|
||||||
|
else
|
||||||
|
if [ -z $XDG_DATA_HOME ]; then
|
||||||
|
cachedir=$HOME/.local/share
|
||||||
|
else
|
||||||
|
cachedir=$XDG_DATA_HOME;
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
mkdir -p $cachedir
|
||||||
|
nugetVersion=latest
|
||||||
|
cachePath=$cachedir/nuget.$nugetVersion.exe
|
||||||
|
|
||||||
|
url=https://dist.nuget.org/win-x86-commandline/$nugetVersion/nuget.exe
|
||||||
|
|
||||||
|
if test ! -f $cachePath; then
|
||||||
|
wget -O $cachePath $url 2>/dev/null || curl -o $cachePath --location $url /dev/null
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test ! -e .nuget; then
|
||||||
|
mkdir .nuget
|
||||||
|
cp $cachePath .nuget/nuget.exe
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test ! -d packages/Sake; then
|
||||||
|
mono .nuget/nuget.exe install KoreBuild -ExcludeVersion -o packages -nocache -pre
|
||||||
|
mono .nuget/nuget.exe install Sake -ExcludeVersion -Source https://www.nuget.org/api/v2/ -Out packages
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! type dnvm > /dev/null 2>&1; then
|
||||||
|
source packages/KoreBuild/build/dnvm.sh
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! type dnx > /dev/null 2>&1 || [ -z "$SKIP_DNX_INSTALL" ]; then
|
||||||
|
dnvm install latest -runtime coreclr -alias default
|
||||||
|
dnvm install default -runtime mono -alias default
|
||||||
|
else
|
||||||
|
dnvm use default -runtime mono
|
||||||
|
fi
|
||||||
|
|
||||||
|
mono packages/Sake/tools/Sake.exe -I packages/KoreBuild/build -f makefile.shade "$@"
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"projects": ["src"]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
|
||||||
|
var VERSION='0.1'
|
||||||
|
var FULL_VERSION='0.1'
|
||||||
|
var AUTHORS='Microsoft Open Technologies, Inc.'
|
||||||
|
|
||||||
|
use-standard-lifecycle
|
||||||
|
k-standard-goals
|
||||||
|
|
||||||
|
#xml-docs-test .clean .build-compile description='Check generated XML documentation files for errors' target='package'
|
||||||
|
k-xml-docs-test
|
||||||
|
|
@ -0,0 +1,138 @@
|
||||||
|
// 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
|
||||||
|
{
|
||||||
|
/// <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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,324 @@
|
||||||
|
// 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
|
||||||
|
{
|
||||||
|
/// <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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
// 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
|
||||||
|
{
|
||||||
|
/// <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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
// 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
|
||||||
|
{
|
||||||
|
/// <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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
// 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
|
||||||
|
{
|
||||||
|
/// <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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
// 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
|
||||||
|
{
|
||||||
|
/// <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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
<?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>
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
// 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.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
{
|
||||||
|
"version": "1.0.0-*",
|
||||||
|
"description": "ASP.NET 5 HTML content interface.",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git://github.com/aspnet/htmlabstractions"
|
||||||
|
},
|
||||||
|
"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-*"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,436 @@
|
||||||
|
// 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.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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,145 @@
|
||||||
|
// 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;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
<?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>
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"compilationOptions": {
|
||||||
|
"warningsAsErrors": true,
|
||||||
|
"keyFile": "../../tools/Key.snk"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.AspNet.Html": "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": { }
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
Loading…
Reference in New Issue