From 2be88a5fe47256c92dec4122bcc6db5bdfa66cb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Standa=20Luke=C5=A1?= Date: Mon, 13 Apr 2020 22:36:11 +0100 Subject: [PATCH 1/3] Add HtmlSanitizedLiteralTemplate --- SanitizedHtmlLiteral/.gitignore | 3 + SanitizedHtmlLiteral/.vscode/launch.json | 36 ++++++++++++ SanitizedHtmlLiteral/.vscode/tasks.json | 42 ++++++++++++++ SanitizedHtmlLiteral/readme.md | 21 +++++++ .../DotVVM.Contrib.Samples.csproj | 26 +++++++++ .../DotVVM.Contrib.Samples/DotvvmStartup.cs | 56 +++++++++++++++++++ .../src/DotVVM.Contrib.Samples/Program.cs | 24 ++++++++ .../Properties/launchSettings.json | 22 ++++++++ .../src/DotVVM.Contrib.Samples/Startup.cs | 37 ++++++++++++ .../ViewModels/DefaultViewModel.cs | 13 +++++ .../ViewModels/MasterViewModel.cs | 20 +++++++ .../ViewModels/Sample1ViewModel.cs | 13 +++++ .../Views/Sample1.dothtml | 9 +++ .../Views/_default.dothtml | 9 +++ .../Views/_master.dotmaster | 26 +++++++++ .../src/DotVVM.Contrib.Samples/Web.config | 12 ++++ .../DotVVM.Contrib.SanitizedHtmlLiteral.sln | 37 ++++++++++++ .../DotVVM.Contrib.Tests/ComponentTests.cs | 23 ++++++++ .../Core/AppSeleniumTest.cs | 23 ++++++++ .../DotVVM.Contrib.Tests.csproj | 31 ++++++++++ .../DotVVM.Contrib.Tests/seleniumconfig.json | 17 ++++++ .../src/DotVVM.Contrib/DotVVM.Contrib.csproj | 33 +++++++++++ .../DotVVM.Contrib/Properties/AssemblyInfo.cs | 33 +++++++++++ .../DotVVM.Contrib/SanitizedHtmlLiteral.cs | 25 +++++++++ ...tizedHtmlLiteralConfigurationExtensions.cs | 38 +++++++++++++ .../DotVVM.Contrib.SanitizedHtmlLiteral.js | 12 ++++ .../DotVVM.Contrib.SanitizedHtmlLiteral.css | 1 + 27 files changed, 642 insertions(+) create mode 100644 SanitizedHtmlLiteral/.gitignore create mode 100644 SanitizedHtmlLiteral/.vscode/launch.json create mode 100644 SanitizedHtmlLiteral/.vscode/tasks.json create mode 100644 SanitizedHtmlLiteral/readme.md create mode 100644 SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/DotVVM.Contrib.Samples.csproj create mode 100644 SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/DotvvmStartup.cs create mode 100644 SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Program.cs create mode 100644 SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Properties/launchSettings.json create mode 100644 SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Startup.cs create mode 100644 SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/ViewModels/DefaultViewModel.cs create mode 100644 SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/ViewModels/MasterViewModel.cs create mode 100644 SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/ViewModels/Sample1ViewModel.cs create mode 100644 SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Views/Sample1.dothtml create mode 100644 SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Views/_default.dothtml create mode 100644 SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Views/_master.dotmaster create mode 100644 SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Web.config create mode 100644 SanitizedHtmlLiteral/src/DotVVM.Contrib.SanitizedHtmlLiteral.sln create mode 100644 SanitizedHtmlLiteral/src/DotVVM.Contrib.Tests/ComponentTests.cs create mode 100644 SanitizedHtmlLiteral/src/DotVVM.Contrib.Tests/Core/AppSeleniumTest.cs create mode 100644 SanitizedHtmlLiteral/src/DotVVM.Contrib.Tests/DotVVM.Contrib.Tests.csproj create mode 100644 SanitizedHtmlLiteral/src/DotVVM.Contrib.Tests/seleniumconfig.json create mode 100644 SanitizedHtmlLiteral/src/DotVVM.Contrib/DotVVM.Contrib.csproj create mode 100644 SanitizedHtmlLiteral/src/DotVVM.Contrib/Properties/AssemblyInfo.cs create mode 100644 SanitizedHtmlLiteral/src/DotVVM.Contrib/SanitizedHtmlLiteral.cs create mode 100644 SanitizedHtmlLiteral/src/DotVVM.Contrib/SanitizedHtmlLiteralConfigurationExtensions.cs create mode 100644 SanitizedHtmlLiteral/src/DotVVM.Contrib/Scripts/DotVVM.Contrib.SanitizedHtmlLiteral.js create mode 100644 SanitizedHtmlLiteral/src/DotVVM.Contrib/Styles/DotVVM.Contrib.SanitizedHtmlLiteral.css diff --git a/SanitizedHtmlLiteral/.gitignore b/SanitizedHtmlLiteral/.gitignore new file mode 100644 index 00000000..a1c96e99 --- /dev/null +++ b/SanitizedHtmlLiteral/.gitignore @@ -0,0 +1,3 @@ + +.fake +.ionide \ No newline at end of file diff --git a/SanitizedHtmlLiteral/.vscode/launch.json b/SanitizedHtmlLiteral/.vscode/launch.json new file mode 100644 index 00000000..131f68ee --- /dev/null +++ b/SanitizedHtmlLiteral/.vscode/launch.json @@ -0,0 +1,36 @@ +{ + // Use IntelliSense to find out which attributes exist for C# debugging + // Use hover for the description of the existing attributes + // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md + "version": "0.2.0", + "configurations": [ + { + "name": ".NET Core Launch (web)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + // If you have changed target frameworks, make sure to update the program path. + "program": "${workspaceFolder}/src/DotVVM.Contrib.Samples/bin/Debug/netcoreapp2.0/DotVVM.Contrib.Samples.dll", + "args": [], + "cwd": "${workspaceFolder}/src/DotVVM.Contrib.Samples", + "stopAtEntry": false, + // Enable launching a web browser when ASP.NET Core starts. For more information: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser + "serverReadyAction": { + "action": "openExternally", + "pattern": "^\\s*Now listening on:\\s+(https?://\\S+)" + }, + "env": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "sourceFileMap": { + "/Views": "${workspaceFolder}/Views" + } + }, + { + "name": ".NET Core Attach", + "type": "coreclr", + "request": "attach", + "processId": "${command:pickProcess}" + } + ] +} \ No newline at end of file diff --git a/SanitizedHtmlLiteral/.vscode/tasks.json b/SanitizedHtmlLiteral/.vscode/tasks.json new file mode 100644 index 00000000..cb131c93 --- /dev/null +++ b/SanitizedHtmlLiteral/.vscode/tasks.json @@ -0,0 +1,42 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/src/DotVVM.Contrib.Samples/DotVVM.Contrib.Samples.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "publish", + "command": "dotnet", + "type": "process", + "args": [ + "publish", + "${workspaceFolder}/src/DotVVM.Contrib.Samples/DotVVM.Contrib.Samples.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "watch", + "command": "dotnet", + "type": "process", + "args": [ + "watch", + "run", + "${workspaceFolder}/src/DotVVM.Contrib.Samples/DotVVM.Contrib.Samples.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + } + ] +} \ No newline at end of file diff --git a/SanitizedHtmlLiteral/readme.md b/SanitizedHtmlLiteral/readme.md new file mode 100644 index 00000000..afe6543a --- /dev/null +++ b/SanitizedHtmlLiteral/readme.md @@ -0,0 +1,21 @@ +# SanitizedHtmlLiteral + +TODO: what does the control do + +## Sample 1: Something + +You can do this: + +```DOTHTML + +``` + +
+ +## Sample 2: Something Else + +You can do also this: + +```DOTHTML + +``` \ No newline at end of file diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/DotVVM.Contrib.Samples.csproj b/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/DotVVM.Contrib.Samples.csproj new file mode 100644 index 00000000..0170e732 --- /dev/null +++ b/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/DotVVM.Contrib.Samples.csproj @@ -0,0 +1,26 @@ + + + netcoreapp2.0 + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/DotvvmStartup.cs b/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/DotvvmStartup.cs new file mode 100644 index 00000000..d9ddd66e --- /dev/null +++ b/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/DotvvmStartup.cs @@ -0,0 +1,56 @@ +using System.Collections.Generic; +using System.Linq; +using DotVVM.Framework; +using DotVVM.Framework.Configuration; +using DotVVM.Framework.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace DotVVM.Contrib.Samples +{ + public class DotvvmStartup : IDotvvmStartup, IDotvvmServiceConfigurator + { + // For more information about this class, visit https://dotvvm.com/docs/tutorials/basics-project-structure + public void Configure(DotvvmConfiguration config, string applicationPath) + { + config.AddContribSanitizedHtmlLiteralConfiguration(); + + ConfigureRoutes(config, applicationPath); + ConfigureControls(config, applicationPath); + ConfigureResources(config, applicationPath); + } + + private void ConfigureRoutes(DotvvmConfiguration config, string applicationPath) + { + config.RouteTable.Add("_Default", "", "Views/_default.dothtml"); + config.RouteTable.AutoDiscoverRoutes(new SamplesRouteStrategy(config)); + } + + private void ConfigureControls(DotvvmConfiguration config, string applicationPath) + { + // register code-only controls and markup controls + } + + private void ConfigureResources(DotvvmConfiguration config, string applicationPath) + { + // register custom resources and adjust paths to the built-in resources + } + + public void ConfigureServices(IDotvvmServiceCollection services) + { + services.AddDefaultTempStorages("Temp"); + + } + } + + internal class SamplesRouteStrategy : DefaultRouteStrategy + { + public SamplesRouteStrategy(DotvvmConfiguration config) : base(config) + { + } + + protected override IEnumerable DiscoverMarkupFiles() + { + return base.DiscoverMarkupFiles().Where(r => !r.ViewsFolderRelativePath.StartsWith("_")); + } + } +} diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Program.cs b/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Program.cs new file mode 100644 index 00000000..e582b2a9 --- /dev/null +++ b/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Program.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Hosting; + +namespace DotVVM.Contrib.Samples +{ + public class Program + { + public static void Main(string[] args) + { + var host = new WebHostBuilder() + .UseKestrel() + .UseContentRoot(Directory.GetCurrentDirectory()) + .UseIISIntegration() + .UseStartup() + .Build(); + + host.Run(); + } + } +} diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Properties/launchSettings.json b/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Properties/launchSettings.json new file mode 100644 index 00000000..22b6dfc5 --- /dev/null +++ b/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Properties/launchSettings.json @@ -0,0 +1,22 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:46582/", + "sslPort": 0 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "DotVVM.Contrib.Samples": { + "commandName": "Project" + } + } +} \ No newline at end of file diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Startup.cs b/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Startup.cs new file mode 100644 index 00000000..f291165f --- /dev/null +++ b/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Startup.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +namespace DotVVM.Contrib.Samples +{ + public class Startup + { + // This method gets called by the runtime. Use this method to add services to the container. + // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 + public void ConfigureServices(IServiceCollection services) + { + services.AddDotVVM(); + } + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) + { + loggerFactory.AddConsole(); + + // use DotVVM + var dotvvmConfiguration = app.UseDotVVM(env.ContentRootPath); + + // use static files + app.UseStaticFiles(new StaticFileOptions + { + FileProvider = new Microsoft.Extensions.FileProviders.PhysicalFileProvider(env.WebRootPath) + }); + } + } +} diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/ViewModels/DefaultViewModel.cs b/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/ViewModels/DefaultViewModel.cs new file mode 100644 index 00000000..90349d56 --- /dev/null +++ b/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/ViewModels/DefaultViewModel.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DotVVM.Framework.ViewModel; + +namespace DotVVM.Contrib.Samples.ViewModels +{ + public class DefaultViewModel : MasterViewModel + { + } +} + diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/ViewModels/MasterViewModel.cs b/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/ViewModels/MasterViewModel.cs new file mode 100644 index 00000000..240029c4 --- /dev/null +++ b/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/ViewModels/MasterViewModel.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DotVVM.Framework.ViewModel; + +namespace DotVVM.Contrib.Samples.ViewModels +{ + public class MasterViewModel : DotvvmViewModelBase + { + + public string[] AllSamples => Context.Configuration.RouteTable + .Where(r => !r.RouteName.StartsWith("_")) + .Select(r => "/" + r.RouteName) + .OrderBy(r => r) + .ToArray(); + + } +} + diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/ViewModels/Sample1ViewModel.cs b/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/ViewModels/Sample1ViewModel.cs new file mode 100644 index 00000000..0f5651b0 --- /dev/null +++ b/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/ViewModels/Sample1ViewModel.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DotVVM.Framework.ViewModel; + +namespace DotVVM.Contrib.Samples.ViewModels +{ + public class Sample1ViewModel : MasterViewModel + { + } +} + diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Views/Sample1.dothtml b/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Views/Sample1.dothtml new file mode 100644 index 00000000..048a68eb --- /dev/null +++ b/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Views/Sample1.dothtml @@ -0,0 +1,9 @@ +@viewModel DotVVM.Contrib.Samples.ViewModels.Sample1ViewModel, DotVVM.Contrib.Samples +@masterPage Views/_master.dotmaster + + + + + + + diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Views/_default.dothtml b/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Views/_default.dothtml new file mode 100644 index 00000000..c66b97f5 --- /dev/null +++ b/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Views/_default.dothtml @@ -0,0 +1,9 @@ +@viewModel DotVVM.Contrib.Samples.ViewModels.DefaultViewModel, DotVVM.Contrib.Samples +@masterPage Views/_master.dotmaster + + + + + + + diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Views/_master.dotmaster b/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Views/_master.dotmaster new file mode 100644 index 00000000..4ba2a2cc --- /dev/null +++ b/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Views/_master.dotmaster @@ -0,0 +1,26 @@ +@viewModel DotVVM.Contrib.Samples.ViewModels.MasterViewModel, DotVVM.Contrib.Samples + + + + + + + + + + +

SanitizedHtmlLiteral Samples

+ + +
  • + {{value: _this}} +
  • +
    +
    + + + + + + + diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Web.config b/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Web.config new file mode 100644 index 00000000..d579a1e9 --- /dev/null +++ b/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Web.config @@ -0,0 +1,12 @@ + + + + + + + + + + \ No newline at end of file diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib.SanitizedHtmlLiteral.sln b/SanitizedHtmlLiteral/src/DotVVM.Contrib.SanitizedHtmlLiteral.sln new file mode 100644 index 00000000..bde09d00 --- /dev/null +++ b/SanitizedHtmlLiteral/src/DotVVM.Contrib.SanitizedHtmlLiteral.sln @@ -0,0 +1,37 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27130.2027 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotVVM.Contrib", "DotVVM.Contrib\DotVVM.Contrib.csproj", "{3E6C2E46-18DB-47C8-94B8-8B447A6A9216}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotVVM.Contrib.Samples", "DotVVM.Contrib.Samples\DotVVM.Contrib.Samples.csproj", "{BEDB2964-D516-492B-AD08-9089F20AE84B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotVVM.Contrib.Tests", "DotVVM.Contrib.Tests\DotVVM.Contrib.Tests.csproj", "{14EF6655-DCED-41E1-A8E7-C242BF8F104B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3E6C2E46-18DB-47C8-94B8-8B447A6A9216}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3E6C2E46-18DB-47C8-94B8-8B447A6A9216}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3E6C2E46-18DB-47C8-94B8-8B447A6A9216}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3E6C2E46-18DB-47C8-94B8-8B447A6A9216}.Release|Any CPU.Build.0 = Release|Any CPU + {BEDB2964-D516-492B-AD08-9089F20AE84B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BEDB2964-D516-492B-AD08-9089F20AE84B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BEDB2964-D516-492B-AD08-9089F20AE84B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BEDB2964-D516-492B-AD08-9089F20AE84B}.Release|Any CPU.Build.0 = Release|Any CPU + {14EF6655-DCED-41E1-A8E7-C242BF8F104B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {14EF6655-DCED-41E1-A8E7-C242BF8F104B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {14EF6655-DCED-41E1-A8E7-C242BF8F104B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {14EF6655-DCED-41E1-A8E7-C242BF8F104B}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {981FF46F-62CC-44E3-9828-87F31EA76E71} + EndGlobalSection +EndGlobal diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib.Tests/ComponentTests.cs b/SanitizedHtmlLiteral/src/DotVVM.Contrib.Tests/ComponentTests.cs new file mode 100644 index 00000000..5fc64915 --- /dev/null +++ b/SanitizedHtmlLiteral/src/DotVVM.Contrib.Tests/ComponentTests.cs @@ -0,0 +1,23 @@ +using System; +using DotVVM.Contrib.Tests.Core; +using Xunit; +using Xunit.Abstractions; + +namespace DotVVM.Contrib.Tests +{ + public class ComponentTests : AppSeleniumTest + { + [Fact] + public void ComponentTest() + { + RunInAllBrowsers(browser => + { + browser.NavigateToUrl(); + }); + } + + public ComponentTests(ITestOutputHelper output) : base(output) + { + } + } +} diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib.Tests/Core/AppSeleniumTest.cs b/SanitizedHtmlLiteral/src/DotVVM.Contrib.Tests/Core/AppSeleniumTest.cs new file mode 100644 index 00000000..59801f32 --- /dev/null +++ b/SanitizedHtmlLiteral/src/DotVVM.Contrib.Tests/Core/AppSeleniumTest.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using System.Text; +using Riganti.Selenium.AssertApi; +using Riganti.Selenium.Core; +using Riganti.Selenium.Core.Abstractions; +using Xunit.Abstractions; + +namespace DotVVM.Contrib.Tests.Core +{ + public class AppSeleniumTest : SeleniumTest + { + public AppSeleniumTest(ITestOutputHelper output) : base(output) + { + } + + public void RunInAllBrowsers(Action testBody, [CallerMemberName] string callerMemberName = "", [CallerFilePath] string callerFilePath = "", [CallerLineNumber] int callerLineNumber = 0) + { + AssertApiSeleniumTestExecutorExtensions.RunInAllBrowsers(this, testBody, callerMemberName, callerFilePath, callerLineNumber); + } + } +} diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib.Tests/DotVVM.Contrib.Tests.csproj b/SanitizedHtmlLiteral/src/DotVVM.Contrib.Tests/DotVVM.Contrib.Tests.csproj new file mode 100644 index 00000000..052a1fc0 --- /dev/null +++ b/SanitizedHtmlLiteral/src/DotVVM.Contrib.Tests/DotVVM.Contrib.Tests.csproj @@ -0,0 +1,31 @@ + + + + netcoreapp2.0 + + false + + + + + + + + + Always + + + + + + + + all + runtime; build; native; contentfiles; analyzers + + + + + + + diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib.Tests/seleniumconfig.json b/SanitizedHtmlLiteral/src/DotVVM.Contrib.Tests/seleniumconfig.json new file mode 100644 index 00000000..4e229147 --- /dev/null +++ b/SanitizedHtmlLiteral/src/DotVVM.Contrib.Tests/seleniumconfig.json @@ -0,0 +1,17 @@ +{ + "factories": { + "chrome:fast": {} + }, + "baseUrls": [ + "http://localhost:46582/" + ], + "testRunOptions": { + "runInParallel": false, + "testAttemptsCount": 1 + }, + "logging": { + "loggers": { + "testContext": {} + } + } +} diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib/DotVVM.Contrib.csproj b/SanitizedHtmlLiteral/src/DotVVM.Contrib/DotVVM.Contrib.csproj new file mode 100644 index 00000000..74341c7d --- /dev/null +++ b/SanitizedHtmlLiteral/src/DotVVM.Contrib/DotVVM.Contrib.csproj @@ -0,0 +1,33 @@ + + + + netcoreapp2.0;net451 + DotVVM.Contrib.SanitizedHtmlLiteral + 0.0.1 + DotVVM Contrib + The SanitizedHtmlLiteral control for DotVVM made by DotVVM Contrib community. + false + dotvvm;asp.net;mvvm;owin;dotnetcore;dnx + https://github.com/riganti/dotvvm-contrib/blob/master/LICENSE + false + false + false + false + false + false + false + false + true + DotVVM.Contrib.SanitizedHtmlLiteral + + + + + + + + + + + + \ No newline at end of file diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib/Properties/AssemblyInfo.cs b/SanitizedHtmlLiteral/src/DotVVM.Contrib/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..66f81276 --- /dev/null +++ b/SanitizedHtmlLiteral/src/DotVVM.Contrib/Properties/AssemblyInfo.cs @@ -0,0 +1,33 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("DotVVM.Contrib.SanitizedHtmlLiteral")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("DotVVM.Contrib")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("0.0.1")] +[assembly: AssemblyVersion("0.0.1")] +[assembly: AssemblyFileVersion("0.0.1")] diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib/SanitizedHtmlLiteral.cs b/SanitizedHtmlLiteral/src/DotVVM.Contrib/SanitizedHtmlLiteral.cs new file mode 100644 index 00000000..4c2342f1 --- /dev/null +++ b/SanitizedHtmlLiteral/src/DotVVM.Contrib/SanitizedHtmlLiteral.cs @@ -0,0 +1,25 @@ +using System; +using DotVVM.Framework.Controls; +using DotVVM.Framework.Hosting; + +namespace DotVVM.Contrib +{ + /// + /// Renders a ... + /// + public class SanitizedHtmlLiteral : HtmlGenericControl + { + + public SanitizedHtmlLiteral() : base("div") + { + } + + protected override void OnPreRender(IDotvvmRequestContext context) + { + context.ResourceManager.AddRequiredResource("dotvvm.contrib.SanitizedHtmlLiteral"); + + base.OnPreRender(context); + } + + } +} diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib/SanitizedHtmlLiteralConfigurationExtensions.cs b/SanitizedHtmlLiteral/src/DotVVM.Contrib/SanitizedHtmlLiteralConfigurationExtensions.cs new file mode 100644 index 00000000..869e0e20 --- /dev/null +++ b/SanitizedHtmlLiteral/src/DotVVM.Contrib/SanitizedHtmlLiteralConfigurationExtensions.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using DotVVM.Framework.Configuration; +using DotVVM.Framework.ResourceManagement; + +namespace DotVVM.Contrib +{ + public static class SanitizedHtmlLiteralConfigurationExtensions + { + + public static void AddContribSanitizedHtmlLiteralConfiguration(this DotvvmConfiguration config) + { + config.Markup.Controls.Add(new DotvvmControlConfiguration() + { + Assembly = typeof(SanitizedHtmlLiteral).Assembly.GetName().Name, + Namespace = typeof(SanitizedHtmlLiteral).Namespace, + TagPrefix = "dc" + }); + + // register additional resources for the control and set up dependencies + config.Resources.Register("dotvvm.contrib.SanitizedHtmlLiteral", new ScriptResource() + { + Location = new EmbeddedResourceLocation(typeof(SanitizedHtmlLiteral).GetTypeInfo().Assembly, "DotVVM.Contrib.Scripts.DotVVM.Contrib.SanitizedHtmlLiteral.js"), + Dependencies = new [] { "dotvvm", "dotvvm.contrib.SanitizedHtmlLiteral.css" } + }); + config.Resources.Register("dotvvm.contrib.SanitizedHtmlLiteral.css", new StylesheetResource() + { + Location = new EmbeddedResourceLocation(typeof(SanitizedHtmlLiteral).GetTypeInfo().Assembly, "DotVVM.Contrib.Styles.DotVVM.Contrib.SanitizedHtmlLiteral.css") + }); + + // NOTE: all resource names should start with "dotvvm.contrib.SanitizedHtmlLiteral" + } + + } +} diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib/Scripts/DotVVM.Contrib.SanitizedHtmlLiteral.js b/SanitizedHtmlLiteral/src/DotVVM.Contrib/Scripts/DotVVM.Contrib.SanitizedHtmlLiteral.js new file mode 100644 index 00000000..7edbea8e --- /dev/null +++ b/SanitizedHtmlLiteral/src/DotVVM.Contrib/Scripts/DotVVM.Contrib.SanitizedHtmlLiteral.js @@ -0,0 +1,12 @@ +ko.bindingHandlers["dotvvm-contrib-SanitizedHtmlLiteral"] = { + init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { + + // TODO: init the control and subscribe to its events + + }, + update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { + var value = ko.unwrap(valueAccessor()); + + // TODO: update the control with a new value from the viewmodel + } +}; diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib/Styles/DotVVM.Contrib.SanitizedHtmlLiteral.css b/SanitizedHtmlLiteral/src/DotVVM.Contrib/Styles/DotVVM.Contrib.SanitizedHtmlLiteral.css new file mode 100644 index 00000000..5f282702 --- /dev/null +++ b/SanitizedHtmlLiteral/src/DotVVM.Contrib/Styles/DotVVM.Contrib.SanitizedHtmlLiteral.css @@ -0,0 +1 @@ + \ No newline at end of file From 8da78f9314e947d4403657be4e886c9e5ba2f55c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Standa=20Luke=C5=A1?= Date: Wed, 15 Apr 2020 17:58:14 +0200 Subject: [PATCH 2/3] Implemented HtmlSanitizedLiteral with client-side support --- .../DotVVM.Contrib.Samples.csproj | 5 +- .../ViewModels/Sample1ViewModel.cs | 13 ++ .../Views/Sample1.dothtml | 11 +- .../src/DotVVM.Contrib/DotVVM.Contrib.csproj | 11 +- .../DotVVM.Contrib/SanitizedHtmlLiteral.cs | 39 +++++- ...tizedHtmlLiteralConfigurationExtensions.cs | 12 +- .../DotVVM.Contrib.SanitizedHtmlLiteral.js | 15 +-- .../DotVVM.Contrib/Scripts/HtmlSanitizer.js | 111 ++++++++++++++++++ 8 files changed, 186 insertions(+), 31 deletions(-) create mode 100644 SanitizedHtmlLiteral/src/DotVVM.Contrib/Scripts/HtmlSanitizer.js diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/DotVVM.Contrib.Samples.csproj b/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/DotVVM.Contrib.Samples.csproj index 0170e732..d4fe60b9 100644 --- a/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/DotVVM.Contrib.Samples.csproj +++ b/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/DotVVM.Contrib.Samples.csproj @@ -15,12 +15,11 @@ - - + - \ No newline at end of file + diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/ViewModels/Sample1ViewModel.cs b/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/ViewModels/Sample1ViewModel.cs index 0f5651b0..e14cd692 100644 --- a/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/ViewModels/Sample1ViewModel.cs +++ b/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/ViewModels/Sample1ViewModel.cs @@ -8,6 +8,19 @@ namespace DotVVM.Contrib.Samples.ViewModels { public class Sample1ViewModel : MasterViewModel { + public string[] Htmls { get; set; } = new [] { @" + Hello + + + " + }; + + [AllowStaticCommand] + public static string[] MoreHtmls() => new [] { + "", + "
    my content
    ", + " nothing bad " + }; } } diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Views/Sample1.dothtml b/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Views/Sample1.dothtml index 048a68eb..08924421 100644 --- a/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Views/Sample1.dothtml +++ b/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Views/Sample1.dothtml @@ -3,7 +3,16 @@ - + +
    +

    + +
    + + + + +
    diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib/DotVVM.Contrib.csproj b/SanitizedHtmlLiteral/src/DotVVM.Contrib/DotVVM.Contrib.csproj index 74341c7d..9e65f915 100644 --- a/SanitizedHtmlLiteral/src/DotVVM.Contrib/DotVVM.Contrib.csproj +++ b/SanitizedHtmlLiteral/src/DotVVM.Contrib/DotVVM.Contrib.csproj @@ -1,7 +1,7 @@  - netcoreapp2.0;net451 + netcoreapp2.0 DotVVM.Contrib.SanitizedHtmlLiteral 0.0.1 DotVVM Contrib @@ -22,12 +22,13 @@ - - + + - + + - \ No newline at end of file + diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib/SanitizedHtmlLiteral.cs b/SanitizedHtmlLiteral/src/DotVVM.Contrib/SanitizedHtmlLiteral.cs index 4c2342f1..42461403 100644 --- a/SanitizedHtmlLiteral/src/DotVVM.Contrib/SanitizedHtmlLiteral.cs +++ b/SanitizedHtmlLiteral/src/DotVVM.Contrib/SanitizedHtmlLiteral.cs @@ -1,25 +1,52 @@ using System; +using DotVVM.Framework.Binding; using DotVVM.Framework.Controls; using DotVVM.Framework.Hosting; +using Ganss.XSS; namespace DotVVM.Contrib { /// /// Renders a ... /// - public class SanitizedHtmlLiteral : HtmlGenericControl + public class SanitizedHtmlLiteral : DotvvmControl { + [MarkupOptions(AllowBinding = true)] + public string Html + { + get { return (string)GetValue(HtmlProperty); } + set { SetValue(HtmlProperty, value); } + } + public static readonly DotvvmProperty HtmlProperty = + DotvvmProperty.Register(nameof(Html)); - public SanitizedHtmlLiteral() : base("div") + public SanitizedHtmlLiteral() { } protected override void OnPreRender(IDotvvmRequestContext context) { - context.ResourceManager.AddRequiredResource("dotvvm.contrib.SanitizedHtmlLiteral"); + if (HasValueBinding(HtmlProperty)) + context.ResourceManager.AddRequiredResource("dotvvm.contrib.SanitizedHtmlLiteral"); + } + + protected override void RenderContents(IHtmlWriter writer, IDotvvmRequestContext context) + { + var valueBinding = GetValueBinding(HtmlProperty); + if (valueBinding is object) + { + writer.WriteKnockoutDataBindComment("dotvvm-contrib-SanitizedHtmlLiteral", valueBinding.GetKnockoutBindingExpression(this)); + } + - base.OnPreRender(context); - } - + var sanitizer = new HtmlSanitizer(); + var sanitized = sanitizer.Sanitize(Html); + writer.WriteUnencodedText(sanitized); + + if (valueBinding is object) + { + writer.WriteKnockoutDataBindEndComment(); + } + } } } diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib/SanitizedHtmlLiteralConfigurationExtensions.cs b/SanitizedHtmlLiteral/src/DotVVM.Contrib/SanitizedHtmlLiteralConfigurationExtensions.cs index 869e0e20..aaf24e0b 100644 --- a/SanitizedHtmlLiteral/src/DotVVM.Contrib/SanitizedHtmlLiteralConfigurationExtensions.cs +++ b/SanitizedHtmlLiteral/src/DotVVM.Contrib/SanitizedHtmlLiteralConfigurationExtensions.cs @@ -21,14 +21,12 @@ public static void AddContribSanitizedHtmlLiteralConfiguration(this DotvvmConfig }); // register additional resources for the control and set up dependencies - config.Resources.Register("dotvvm.contrib.SanitizedHtmlLiteral", new ScriptResource() - { - Location = new EmbeddedResourceLocation(typeof(SanitizedHtmlLiteral).GetTypeInfo().Assembly, "DotVVM.Contrib.Scripts.DotVVM.Contrib.SanitizedHtmlLiteral.js"), - Dependencies = new [] { "dotvvm", "dotvvm.contrib.SanitizedHtmlLiteral.css" } + config.Resources.Register("HtmlSanitizer", new ScriptResource() { + Location = new EmbeddedResourceLocation(typeof(SanitizedHtmlLiteral).GetTypeInfo().Assembly, "DotVVM.Contrib.Scripts.HtmlSanitizer.js") }); - config.Resources.Register("dotvvm.contrib.SanitizedHtmlLiteral.css", new StylesheetResource() - { - Location = new EmbeddedResourceLocation(typeof(SanitizedHtmlLiteral).GetTypeInfo().Assembly, "DotVVM.Contrib.Styles.DotVVM.Contrib.SanitizedHtmlLiteral.css") + config.Resources.Register("dotvvm.contrib.SanitizedHtmlLiteral", new ScriptResource() { + Location = new EmbeddedResourceLocation(typeof(SanitizedHtmlLiteral).GetTypeInfo().Assembly, "DotVVM.Contrib.Scripts.DotVVM.Contrib.SanitizedHtmlLiteral.js"), + Dependencies = new[] { "knockout", "HtmlSanitizer" } }); // NOTE: all resource names should start with "dotvvm.contrib.SanitizedHtmlLiteral" diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib/Scripts/DotVVM.Contrib.SanitizedHtmlLiteral.js b/SanitizedHtmlLiteral/src/DotVVM.Contrib/Scripts/DotVVM.Contrib.SanitizedHtmlLiteral.js index 7edbea8e..7fd3d0e5 100644 --- a/SanitizedHtmlLiteral/src/DotVVM.Contrib/Scripts/DotVVM.Contrib.SanitizedHtmlLiteral.js +++ b/SanitizedHtmlLiteral/src/DotVVM.Contrib/Scripts/DotVVM.Contrib.SanitizedHtmlLiteral.js @@ -1,12 +1,9 @@ ko.bindingHandlers["dotvvm-contrib-SanitizedHtmlLiteral"] = { - init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { - - // TODO: init the control and subscribe to its events - - }, - update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { - var value = ko.unwrap(valueAccessor()); - - // TODO: update the control with a new value from the viewmodel + update(element, valueAccessor) { + const rawHtml = ko.unwrap(valueAccessor()) + const sanitizedHtml = HtmlSanitizer.SanitizeHtml(rawHtml) + ko.virtualElements.setDomNodeChildren(element, ko.utils.parseHtmlFragment(sanitizedHtml, element.ownerDocument)) } }; + +ko.virtualElements.allowedBindings["dotvvm-contrib-SanitizedHtmlLiteral"] = true diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib/Scripts/HtmlSanitizer.js b/SanitizedHtmlLiteral/src/DotVVM.Contrib/Scripts/HtmlSanitizer.js new file mode 100644 index 00000000..2ad8388e --- /dev/null +++ b/SanitizedHtmlLiteral/src/DotVVM.Contrib/Scripts/HtmlSanitizer.js @@ -0,0 +1,111 @@ +//JavaScript HTML Sanitizer, (c) Alexander Yumashev, Jitbit Software. + +//homepage https://github.com/jitbit/HtmlSanitizer + +//License: MIT https://github.com/jitbit/HtmlSanitizer/blob/master/LICENSE + +console.log('Sanitizer loading'); + +var HtmlSanitizer = new (function () { + + var tagWhitelist_ = { + 'A': true, 'ABBR': true, 'B': true, 'BLOCKQUOTE': true, 'BODY': true, 'BR': true, 'CENTER': true, 'CODE': true, 'DIV': true, 'EM': true, 'FONT': true, + 'H1': true, 'H2': true, 'H3': true, 'H4': true, 'H5': true, 'H6': true, 'HR': true, 'I': true, 'IMG': true, 'LABEL': true, 'LI': true, 'OL': true, 'P': true, 'PRE': true, + 'SMALL': true, 'SOURCE': true, 'SPAN': true, 'STRONG': true, 'TABLE': true, 'TBODY': true, 'TR': true, 'TD': true, 'TH': true, 'THEAD': true, 'UL': true, 'U': true, 'VIDEO': true + }; + + var contentTagWhiteList_ = { 'FORM': true }; //tags that will be converted to DIVs + + var attributeWhitelist_ = { 'align': true, 'color': true, 'controls': true, 'height': true, 'href': true, 'src': true, 'style': true, 'target': true, 'title': true, 'type': true, 'width': true }; + + var cssWhitelist_ = { 'color': true, 'background-color': true, 'font-size': true, 'text-align': true, 'text-decoration': true, 'font-weight': true }; + + var schemaWhiteList_ = [ 'http:', 'https:', 'data:', 'm-files:', 'file:', 'ftp:' ]; //which "protocols" are allowed in "href", "src" etc + + var uriAttributes_ = { 'href': true, 'action': true }; + + this.SanitizeHtml = function(input) { + input = input.trim(); + if (input == "") return ""; //to save performance and not create iframe + + //firefox "bogus node" workaround + if (input == "
    ") return ""; + + var iframe = document.createElement('iframe'); + if (iframe['sandbox'] === undefined) { + alert('Your browser does not support sandboxed iframes. Please upgrade to a modern browser.'); + return ''; + } + iframe['sandbox'] = 'allow-same-origin'; + iframe.style.display = 'none'; + document.body.appendChild(iframe); // necessary so the iframe contains a document + var iframedoc = iframe.contentDocument || iframe.contentWindow.document; + if (iframedoc.body == null) iframedoc.write(""); // null in IE + iframedoc.body.innerHTML = input; + + function makeSanitizedCopy(node) { + if (node.nodeType == Node.TEXT_NODE) { + var newNode = node.cloneNode(true); + } else if (node.nodeType == Node.ELEMENT_NODE && (tagWhitelist_[node.tagName] || contentTagWhiteList_[node.tagName])) { + + //remove useless empty spans (lots of those when pasting from MS Outlook) + if ((node.tagName == "SPAN" || node.tagName == "B" || node.tagName == "I" || node.tagName == "U") + && node.innerHTML.trim() == "") { + return document.createDocumentFragment(); + } + + if (contentTagWhiteList_[node.tagName]) + newNode = iframedoc.createElement('DIV'); //convert to DIV + else + newNode = iframedoc.createElement(node.tagName); + + for (var i = 0; i < node.attributes.length; i++) { + var attr = node.attributes[i]; + if (attributeWhitelist_[attr.name]) { + if (attr.name == "style") { + for (s = 0; s < node.style.length; s++) { + var styleName = node.style[s]; + if (cssWhitelist_[styleName]) + newNode.style.setProperty(styleName, node.style.getPropertyValue(styleName)); + } + } + else { + if (uriAttributes_[attr.name]) { //if this is a "uri" attribute, that can have "javascript:" or something + if (attr.value.indexOf(":") > -1 && !startsWithAny(attr.value, schemaWhiteList_)) + continue; + } + newNode.setAttribute(attr.name, attr.value); + } + } + } + for (i = 0; i < node.childNodes.length; i++) { + var subCopy = makeSanitizedCopy(node.childNodes[i]); + newNode.appendChild(subCopy, false); + } + } else { + newNode = document.createDocumentFragment(); + } + return newNode; + }; + + var resultElement = makeSanitizedCopy(iframedoc.body); + document.body.removeChild(iframe); + return resultElement.innerHTML + .replace(/]*>(\S)/g, "
    \n$1") + .replace(/div>
    \n Date: Thu, 16 Apr 2020 19:06:53 +0200 Subject: [PATCH 3/3] Move to subdirectory, cleanup --- .../SanitizedHtmlLiteral}/.gitignore | 0 .../SanitizedHtmlLiteral}/.vscode/launch.json | 0 .../SanitizedHtmlLiteral}/.vscode/tasks.json | 0 Controls/SanitizedHtmlLiteral/readme.md | 20 ++++++++++++++++++ .../DotVVM.Contrib.Samples.csproj | 0 .../DotVVM.Contrib.Samples/DotvvmStartup.cs | 0 .../src/DotVVM.Contrib.Samples/Program.cs | 0 .../Properties/launchSettings.json | 0 .../src/DotVVM.Contrib.Samples/Startup.cs | 0 .../ViewModels/DefaultViewModel.cs | 0 .../ViewModels/MasterViewModel.cs | 0 .../ViewModels/Sample1ViewModel.cs | 0 .../Views/Sample1.dothtml | 0 .../Views/_default.dothtml | 0 .../Views/_master.dotmaster | 0 .../src/DotVVM.Contrib.Samples/Web.config | 0 .../DotVVM.Contrib.SanitizedHtmlLiteral.sln | 0 .../DotVVM.Contrib.Tests/ComponentTests.cs | 0 .../Core/AppSeleniumTest.cs | 0 .../DotVVM.Contrib.Tests.csproj | 0 .../DotVVM.Contrib.Tests/seleniumconfig.json | 0 .../src/DotVVM.Contrib/DotVVM.Contrib.csproj | 1 - .../DotVVM.Contrib/Properties/AssemblyInfo.cs | 0 .../DotVVM.Contrib/SanitizedHtmlLiteral.cs | 5 +++-- ...tizedHtmlLiteralConfigurationExtensions.cs | 0 .../DotVVM.Contrib.SanitizedHtmlLiteral.js | 0 .../DotVVM.Contrib/Scripts/HtmlSanitizer.js | 0 SanitizedHtmlLiteral/readme.md | 21 ------------------- .../DotVVM.Contrib.SanitizedHtmlLiteral.css | 1 - 29 files changed, 23 insertions(+), 25 deletions(-) rename {SanitizedHtmlLiteral => Controls/SanitizedHtmlLiteral}/.gitignore (100%) rename {SanitizedHtmlLiteral => Controls/SanitizedHtmlLiteral}/.vscode/launch.json (100%) rename {SanitizedHtmlLiteral => Controls/SanitizedHtmlLiteral}/.vscode/tasks.json (100%) create mode 100644 Controls/SanitizedHtmlLiteral/readme.md rename {SanitizedHtmlLiteral => Controls/SanitizedHtmlLiteral}/src/DotVVM.Contrib.Samples/DotVVM.Contrib.Samples.csproj (100%) rename {SanitizedHtmlLiteral => Controls/SanitizedHtmlLiteral}/src/DotVVM.Contrib.Samples/DotvvmStartup.cs (100%) rename {SanitizedHtmlLiteral => Controls/SanitizedHtmlLiteral}/src/DotVVM.Contrib.Samples/Program.cs (100%) rename {SanitizedHtmlLiteral => Controls/SanitizedHtmlLiteral}/src/DotVVM.Contrib.Samples/Properties/launchSettings.json (100%) rename {SanitizedHtmlLiteral => Controls/SanitizedHtmlLiteral}/src/DotVVM.Contrib.Samples/Startup.cs (100%) rename {SanitizedHtmlLiteral => Controls/SanitizedHtmlLiteral}/src/DotVVM.Contrib.Samples/ViewModels/DefaultViewModel.cs (100%) rename {SanitizedHtmlLiteral => Controls/SanitizedHtmlLiteral}/src/DotVVM.Contrib.Samples/ViewModels/MasterViewModel.cs (100%) rename {SanitizedHtmlLiteral => Controls/SanitizedHtmlLiteral}/src/DotVVM.Contrib.Samples/ViewModels/Sample1ViewModel.cs (100%) rename {SanitizedHtmlLiteral => Controls/SanitizedHtmlLiteral}/src/DotVVM.Contrib.Samples/Views/Sample1.dothtml (100%) rename {SanitizedHtmlLiteral => Controls/SanitizedHtmlLiteral}/src/DotVVM.Contrib.Samples/Views/_default.dothtml (100%) rename {SanitizedHtmlLiteral => Controls/SanitizedHtmlLiteral}/src/DotVVM.Contrib.Samples/Views/_master.dotmaster (100%) rename {SanitizedHtmlLiteral => Controls/SanitizedHtmlLiteral}/src/DotVVM.Contrib.Samples/Web.config (100%) rename {SanitizedHtmlLiteral => Controls/SanitizedHtmlLiteral}/src/DotVVM.Contrib.SanitizedHtmlLiteral.sln (100%) rename {SanitizedHtmlLiteral => Controls/SanitizedHtmlLiteral}/src/DotVVM.Contrib.Tests/ComponentTests.cs (100%) rename {SanitizedHtmlLiteral => Controls/SanitizedHtmlLiteral}/src/DotVVM.Contrib.Tests/Core/AppSeleniumTest.cs (100%) rename {SanitizedHtmlLiteral => Controls/SanitizedHtmlLiteral}/src/DotVVM.Contrib.Tests/DotVVM.Contrib.Tests.csproj (100%) rename {SanitizedHtmlLiteral => Controls/SanitizedHtmlLiteral}/src/DotVVM.Contrib.Tests/seleniumconfig.json (100%) rename {SanitizedHtmlLiteral => Controls/SanitizedHtmlLiteral}/src/DotVVM.Contrib/DotVVM.Contrib.csproj (97%) rename {SanitizedHtmlLiteral => Controls/SanitizedHtmlLiteral}/src/DotVVM.Contrib/Properties/AssemblyInfo.cs (100%) rename {SanitizedHtmlLiteral => Controls/SanitizedHtmlLiteral}/src/DotVVM.Contrib/SanitizedHtmlLiteral.cs (85%) rename {SanitizedHtmlLiteral => Controls/SanitizedHtmlLiteral}/src/DotVVM.Contrib/SanitizedHtmlLiteralConfigurationExtensions.cs (100%) rename {SanitizedHtmlLiteral => Controls/SanitizedHtmlLiteral}/src/DotVVM.Contrib/Scripts/DotVVM.Contrib.SanitizedHtmlLiteral.js (100%) rename {SanitizedHtmlLiteral => Controls/SanitizedHtmlLiteral}/src/DotVVM.Contrib/Scripts/HtmlSanitizer.js (100%) delete mode 100644 SanitizedHtmlLiteral/readme.md delete mode 100644 SanitizedHtmlLiteral/src/DotVVM.Contrib/Styles/DotVVM.Contrib.SanitizedHtmlLiteral.css diff --git a/SanitizedHtmlLiteral/.gitignore b/Controls/SanitizedHtmlLiteral/.gitignore similarity index 100% rename from SanitizedHtmlLiteral/.gitignore rename to Controls/SanitizedHtmlLiteral/.gitignore diff --git a/SanitizedHtmlLiteral/.vscode/launch.json b/Controls/SanitizedHtmlLiteral/.vscode/launch.json similarity index 100% rename from SanitizedHtmlLiteral/.vscode/launch.json rename to Controls/SanitizedHtmlLiteral/.vscode/launch.json diff --git a/SanitizedHtmlLiteral/.vscode/tasks.json b/Controls/SanitizedHtmlLiteral/.vscode/tasks.json similarity index 100% rename from SanitizedHtmlLiteral/.vscode/tasks.json rename to Controls/SanitizedHtmlLiteral/.vscode/tasks.json diff --git a/Controls/SanitizedHtmlLiteral/readme.md b/Controls/SanitizedHtmlLiteral/readme.md new file mode 100644 index 00000000..e377cbe2 --- /dev/null +++ b/Controls/SanitizedHtmlLiteral/readme.md @@ -0,0 +1,20 @@ +# SanitizedHtmlLiteral + +The control renders the Html property running it though a HtmlSanitizer. + +On server we use [mganss/HtmlSanitizer](https://github.com/mganss/HtmlSanitizer) and in Javascript we use [jitbit/HtmlSanitizer](https://github.com/jitbit/HtmlSanitizer). + +## Example + +When you have a `Html` property in view model, you can just show it on the page like this: + +```DOTHTML + +``` + +If you don't need to refresh it on client-side, just use a `resource` binding, so we don't have to fetch the Javascript version of the sanitizer: + + +```DOTHTML + +``` diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/DotVVM.Contrib.Samples.csproj b/Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/DotVVM.Contrib.Samples.csproj similarity index 100% rename from SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/DotVVM.Contrib.Samples.csproj rename to Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/DotVVM.Contrib.Samples.csproj diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/DotvvmStartup.cs b/Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/DotvvmStartup.cs similarity index 100% rename from SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/DotvvmStartup.cs rename to Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/DotvvmStartup.cs diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Program.cs b/Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Program.cs similarity index 100% rename from SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Program.cs rename to Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Program.cs diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Properties/launchSettings.json b/Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Properties/launchSettings.json similarity index 100% rename from SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Properties/launchSettings.json rename to Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Properties/launchSettings.json diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Startup.cs b/Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Startup.cs similarity index 100% rename from SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Startup.cs rename to Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Startup.cs diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/ViewModels/DefaultViewModel.cs b/Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/ViewModels/DefaultViewModel.cs similarity index 100% rename from SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/ViewModels/DefaultViewModel.cs rename to Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/ViewModels/DefaultViewModel.cs diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/ViewModels/MasterViewModel.cs b/Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/ViewModels/MasterViewModel.cs similarity index 100% rename from SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/ViewModels/MasterViewModel.cs rename to Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/ViewModels/MasterViewModel.cs diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/ViewModels/Sample1ViewModel.cs b/Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/ViewModels/Sample1ViewModel.cs similarity index 100% rename from SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/ViewModels/Sample1ViewModel.cs rename to Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/ViewModels/Sample1ViewModel.cs diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Views/Sample1.dothtml b/Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Views/Sample1.dothtml similarity index 100% rename from SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Views/Sample1.dothtml rename to Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Views/Sample1.dothtml diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Views/_default.dothtml b/Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Views/_default.dothtml similarity index 100% rename from SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Views/_default.dothtml rename to Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Views/_default.dothtml diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Views/_master.dotmaster b/Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Views/_master.dotmaster similarity index 100% rename from SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Views/_master.dotmaster rename to Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Views/_master.dotmaster diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Web.config b/Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Web.config similarity index 100% rename from SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Web.config rename to Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib.Samples/Web.config diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib.SanitizedHtmlLiteral.sln b/Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib.SanitizedHtmlLiteral.sln similarity index 100% rename from SanitizedHtmlLiteral/src/DotVVM.Contrib.SanitizedHtmlLiteral.sln rename to Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib.SanitizedHtmlLiteral.sln diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib.Tests/ComponentTests.cs b/Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib.Tests/ComponentTests.cs similarity index 100% rename from SanitizedHtmlLiteral/src/DotVVM.Contrib.Tests/ComponentTests.cs rename to Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib.Tests/ComponentTests.cs diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib.Tests/Core/AppSeleniumTest.cs b/Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib.Tests/Core/AppSeleniumTest.cs similarity index 100% rename from SanitizedHtmlLiteral/src/DotVVM.Contrib.Tests/Core/AppSeleniumTest.cs rename to Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib.Tests/Core/AppSeleniumTest.cs diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib.Tests/DotVVM.Contrib.Tests.csproj b/Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib.Tests/DotVVM.Contrib.Tests.csproj similarity index 100% rename from SanitizedHtmlLiteral/src/DotVVM.Contrib.Tests/DotVVM.Contrib.Tests.csproj rename to Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib.Tests/DotVVM.Contrib.Tests.csproj diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib.Tests/seleniumconfig.json b/Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib.Tests/seleniumconfig.json similarity index 100% rename from SanitizedHtmlLiteral/src/DotVVM.Contrib.Tests/seleniumconfig.json rename to Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib.Tests/seleniumconfig.json diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib/DotVVM.Contrib.csproj b/Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib/DotVVM.Contrib.csproj similarity index 97% rename from SanitizedHtmlLiteral/src/DotVVM.Contrib/DotVVM.Contrib.csproj rename to Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib/DotVVM.Contrib.csproj index 9e65f915..84483b6a 100644 --- a/SanitizedHtmlLiteral/src/DotVVM.Contrib/DotVVM.Contrib.csproj +++ b/Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib/DotVVM.Contrib.csproj @@ -23,7 +23,6 @@ - diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib/Properties/AssemblyInfo.cs b/Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib/Properties/AssemblyInfo.cs similarity index 100% rename from SanitizedHtmlLiteral/src/DotVVM.Contrib/Properties/AssemblyInfo.cs rename to Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib/Properties/AssemblyInfo.cs diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib/SanitizedHtmlLiteral.cs b/Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib/SanitizedHtmlLiteral.cs similarity index 85% rename from SanitizedHtmlLiteral/src/DotVVM.Contrib/SanitizedHtmlLiteral.cs rename to Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib/SanitizedHtmlLiteral.cs index 42461403..85130901 100644 --- a/SanitizedHtmlLiteral/src/DotVVM.Contrib/SanitizedHtmlLiteral.cs +++ b/Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib/SanitizedHtmlLiteral.cs @@ -7,11 +7,12 @@ namespace DotVVM.Contrib { /// - /// Renders a ... + /// Renders the contents of property as html. It's sanitized (script tags stripped) using HtmlSanitized library (see NuGet and npm) /// + [ControlMarkupOptions(AllowContent = false)] public class SanitizedHtmlLiteral : DotvvmControl { - [MarkupOptions(AllowBinding = true)] + [MarkupOptions(AllowBinding = true, Required = true)] public string Html { get { return (string)GetValue(HtmlProperty); } diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib/SanitizedHtmlLiteralConfigurationExtensions.cs b/Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib/SanitizedHtmlLiteralConfigurationExtensions.cs similarity index 100% rename from SanitizedHtmlLiteral/src/DotVVM.Contrib/SanitizedHtmlLiteralConfigurationExtensions.cs rename to Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib/SanitizedHtmlLiteralConfigurationExtensions.cs diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib/Scripts/DotVVM.Contrib.SanitizedHtmlLiteral.js b/Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib/Scripts/DotVVM.Contrib.SanitizedHtmlLiteral.js similarity index 100% rename from SanitizedHtmlLiteral/src/DotVVM.Contrib/Scripts/DotVVM.Contrib.SanitizedHtmlLiteral.js rename to Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib/Scripts/DotVVM.Contrib.SanitizedHtmlLiteral.js diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib/Scripts/HtmlSanitizer.js b/Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib/Scripts/HtmlSanitizer.js similarity index 100% rename from SanitizedHtmlLiteral/src/DotVVM.Contrib/Scripts/HtmlSanitizer.js rename to Controls/SanitizedHtmlLiteral/src/DotVVM.Contrib/Scripts/HtmlSanitizer.js diff --git a/SanitizedHtmlLiteral/readme.md b/SanitizedHtmlLiteral/readme.md deleted file mode 100644 index afe6543a..00000000 --- a/SanitizedHtmlLiteral/readme.md +++ /dev/null @@ -1,21 +0,0 @@ -# SanitizedHtmlLiteral - -TODO: what does the control do - -## Sample 1: Something - -You can do this: - -```DOTHTML - -``` - -
    - -## Sample 2: Something Else - -You can do also this: - -```DOTHTML - -``` \ No newline at end of file diff --git a/SanitizedHtmlLiteral/src/DotVVM.Contrib/Styles/DotVVM.Contrib.SanitizedHtmlLiteral.css b/SanitizedHtmlLiteral/src/DotVVM.Contrib/Styles/DotVVM.Contrib.SanitizedHtmlLiteral.css deleted file mode 100644 index 5f282702..00000000 --- a/SanitizedHtmlLiteral/src/DotVVM.Contrib/Styles/DotVVM.Contrib.SanitizedHtmlLiteral.css +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file