diff --git a/framework/Volo.Abp.sln b/framework/Volo.Abp.sln
index 67d2fa2573..b3af9241c4 100644
--- a/framework/Volo.Abp.sln
+++ b/framework/Volo.Abp.sln
@@ -383,6 +383,16 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.AspNetCore.Compone
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.AspNetCore.Mvc.UI.Bundling.Abstractions", "src\Volo.Abp.AspNetCore.Mvc.UI.Bundling.Abstractions\Volo.Abp.AspNetCore.Mvc.UI.Bundling.Abstractions.csproj", "{E9CE58DB-0789-4D18-8B63-474F7D7B14B4}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.TextTemplating.Abstractions", "src\Volo.Abp.TextTemplating.Abstractions\Volo.Abp.TextTemplating.Abstractions.csproj", "{184E859A-282D-44D7-B8E9-FEA874644013}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.TextTemplating.Scriban", "src\Volo.Abp.TextTemplating.Scriban\Volo.Abp.TextTemplating.Scriban.csproj", "{228723E6-FA6D-406B-B8F8-C9BCC547AF8E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.TextTemplating.Razor", "src\Volo.Abp.TextTemplating.Razor\Volo.Abp.TextTemplating.Razor.csproj", "{42EA6F06-2D78-4D18-8AC4-8F2AB7E6DA19}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.TextTemplating.Razor.Tests", "test\Volo.Abp.TextTemplating.Razor.Tests\Volo.Abp.TextTemplating.Razor.Tests.csproj", "{C996F458-98FB-483D-9306-4701290E2FC1}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.TextTemplating.Scriban.Tests", "test\Volo.Abp.TextTemplating.Scriban.Tests\Volo.Abp.TextTemplating.Scriban.Tests.csproj", "{75D8DADB-3FA9-4C1D-B23A-DBFD08133B7C}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -1141,6 +1151,26 @@ Global
{E9CE58DB-0789-4D18-8B63-474F7D7B14B4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E9CE58DB-0789-4D18-8B63-474F7D7B14B4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E9CE58DB-0789-4D18-8B63-474F7D7B14B4}.Release|Any CPU.Build.0 = Release|Any CPU
+ {184E859A-282D-44D7-B8E9-FEA874644013}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {184E859A-282D-44D7-B8E9-FEA874644013}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {184E859A-282D-44D7-B8E9-FEA874644013}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {184E859A-282D-44D7-B8E9-FEA874644013}.Release|Any CPU.Build.0 = Release|Any CPU
+ {228723E6-FA6D-406B-B8F8-C9BCC547AF8E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {228723E6-FA6D-406B-B8F8-C9BCC547AF8E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {228723E6-FA6D-406B-B8F8-C9BCC547AF8E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {228723E6-FA6D-406B-B8F8-C9BCC547AF8E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {42EA6F06-2D78-4D18-8AC4-8F2AB7E6DA19}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {42EA6F06-2D78-4D18-8AC4-8F2AB7E6DA19}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {42EA6F06-2D78-4D18-8AC4-8F2AB7E6DA19}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {42EA6F06-2D78-4D18-8AC4-8F2AB7E6DA19}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C996F458-98FB-483D-9306-4701290E2FC1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C996F458-98FB-483D-9306-4701290E2FC1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C996F458-98FB-483D-9306-4701290E2FC1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C996F458-98FB-483D-9306-4701290E2FC1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {75D8DADB-3FA9-4C1D-B23A-DBFD08133B7C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {75D8DADB-3FA9-4C1D-B23A-DBFD08133B7C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {75D8DADB-3FA9-4C1D-B23A-DBFD08133B7C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {75D8DADB-3FA9-4C1D-B23A-DBFD08133B7C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -1334,6 +1364,11 @@ Global
{863C18F9-2407-49F9-9ADC-F6229AF3B385} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{B4B6B7DE-9798-4007-B1DF-7EE7929E392A} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{E9CE58DB-0789-4D18-8B63-474F7D7B14B4} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
+ {184E859A-282D-44D7-B8E9-FEA874644013} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
+ {228723E6-FA6D-406B-B8F8-C9BCC547AF8E} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
+ {42EA6F06-2D78-4D18-8AC4-8F2AB7E6DA19} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
+ {C996F458-98FB-483D-9306-4701290E2FC1} = {447C8A77-E5F0-4538-8687-7383196D04EA}
+ {75D8DADB-3FA9-4C1D-B23A-DBFD08133B7C} = {447C8A77-E5F0-4538-8687-7383196D04EA}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5}
diff --git a/framework/src/Volo.Abp.TextTemplating.Abstractions/FodyWeavers.xml b/framework/src/Volo.Abp.TextTemplating.Abstractions/FodyWeavers.xml
new file mode 100644
index 0000000000..be0de3a908
--- /dev/null
+++ b/framework/src/Volo.Abp.TextTemplating.Abstractions/FodyWeavers.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.TextTemplating.Abstractions/FodyWeavers.xsd b/framework/src/Volo.Abp.TextTemplating.Abstractions/FodyWeavers.xsd
new file mode 100644
index 0000000000..3f3946e282
--- /dev/null
+++ b/framework/src/Volo.Abp.TextTemplating.Abstractions/FodyWeavers.xsd
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.
+
+
+
+
+ A comma-separated list of error codes that can be safely ignored in assembly verification.
+
+
+
+
+ 'false' to turn off automatic generation of the XML Schema file.
+
+
+
+
+
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.TextTemplating.Abstractions/Volo.Abp.TextTemplating.Abstractions.csproj b/framework/src/Volo.Abp.TextTemplating.Abstractions/Volo.Abp.TextTemplating.Abstractions.csproj
new file mode 100644
index 0000000000..649bdc2912
--- /dev/null
+++ b/framework/src/Volo.Abp.TextTemplating.Abstractions/Volo.Abp.TextTemplating.Abstractions.csproj
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
+
+
diff --git a/framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/AbpTextTemplatingAbstractionsModule.cs b/framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/AbpTextTemplatingAbstractionsModule.cs
new file mode 100644
index 0000000000..bb76b299b2
--- /dev/null
+++ b/framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/AbpTextTemplatingAbstractionsModule.cs
@@ -0,0 +1,46 @@
+using System;
+using System.Collections.Generic;
+using Microsoft.Extensions.DependencyInjection;
+using Volo.Abp.Localization;
+using Volo.Abp.Modularity;
+using Volo.Abp.VirtualFileSystem;
+
+namespace Volo.Abp.TextTemplating
+{
+ [DependsOn(
+ typeof(AbpVirtualFileSystemModule),
+ typeof(AbpLocalizationAbstractionsModule)
+ )]
+ public class AbpTextTemplatingAbstractionsModule : AbpModule
+ {
+ public override void PreConfigureServices(ServiceConfigurationContext context)
+ {
+ AutoAddProvidersAndContributors(context.Services);
+ }
+
+ private static void AutoAddProvidersAndContributors(IServiceCollection services)
+ {
+ var definitionProviders = new List();
+ var contentContributors = new List();
+
+ services.OnRegistred(context =>
+ {
+ if (typeof(ITemplateDefinitionProvider).IsAssignableFrom(context.ImplementationType))
+ {
+ definitionProviders.Add(context.ImplementationType);
+ }
+
+ if (typeof(ITemplateContentContributor).IsAssignableFrom(context.ImplementationType))
+ {
+ contentContributors.Add(context.ImplementationType);
+ }
+ });
+
+ services.Configure(options =>
+ {
+ options.DefinitionProviders.AddIfNotContains(definitionProviders);
+ options.ContentContributors.AddIfNotContains(contentContributors);
+ });
+ }
+ }
+}
diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/AbpTextTemplatingOptions.cs b/framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/AbpTextTemplatingOptions.cs
similarity index 100%
rename from framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/AbpTextTemplatingOptions.cs
rename to framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/AbpTextTemplatingOptions.cs
diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/ITemplateContentContributor.cs b/framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/ITemplateContentContributor.cs
similarity index 100%
rename from framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/ITemplateContentContributor.cs
rename to framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/ITemplateContentContributor.cs
diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/ITemplateContentProvider.cs b/framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/ITemplateContentProvider.cs
similarity index 100%
rename from framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/ITemplateContentProvider.cs
rename to framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/ITemplateContentProvider.cs
diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/ITemplateDefinitionContext.cs b/framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/ITemplateDefinitionContext.cs
similarity index 100%
rename from framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/ITemplateDefinitionContext.cs
rename to framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/ITemplateDefinitionContext.cs
diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/ITemplateDefinitionManager.cs b/framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/ITemplateDefinitionManager.cs
similarity index 100%
rename from framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/ITemplateDefinitionManager.cs
rename to framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/ITemplateDefinitionManager.cs
diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/ITemplateDefinitionProvider.cs b/framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/ITemplateDefinitionProvider.cs
similarity index 100%
rename from framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/ITemplateDefinitionProvider.cs
rename to framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/ITemplateDefinitionProvider.cs
diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/ITemplateRenderer.cs b/framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/ITemplateRenderer.cs
similarity index 100%
rename from framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/ITemplateRenderer.cs
rename to framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/ITemplateRenderer.cs
diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateContentContributorContext.cs b/framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/TemplateContentContributorContext.cs
similarity index 100%
rename from framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateContentContributorContext.cs
rename to framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/TemplateContentContributorContext.cs
diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateContentProvider.cs b/framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/TemplateContentProvider.cs
similarity index 100%
rename from framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateContentProvider.cs
rename to framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/TemplateContentProvider.cs
diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateDefinition.cs b/framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/TemplateDefinition.cs
similarity index 100%
rename from framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateDefinition.cs
rename to framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/TemplateDefinition.cs
diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateDefinitionContext.cs b/framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/TemplateDefinitionContext.cs
similarity index 100%
rename from framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateDefinitionContext.cs
rename to framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/TemplateDefinitionContext.cs
diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateDefinitionExtensions.cs b/framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/TemplateDefinitionExtensions.cs
similarity index 100%
rename from framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateDefinitionExtensions.cs
rename to framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/TemplateDefinitionExtensions.cs
diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateDefinitionManager.cs b/framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/TemplateDefinitionManager.cs
similarity index 100%
rename from framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateDefinitionManager.cs
rename to framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/TemplateDefinitionManager.cs
diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateDefinitionProvider.cs b/framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/TemplateDefinitionProvider.cs
similarity index 100%
rename from framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateDefinitionProvider.cs
rename to framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/TemplateDefinitionProvider.cs
diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/VirtualFiles/FileInfoLocalizedTemplateContentReader.cs b/framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/VirtualFiles/FileInfoLocalizedTemplateContentReader.cs
similarity index 100%
rename from framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/VirtualFiles/FileInfoLocalizedTemplateContentReader.cs
rename to framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/VirtualFiles/FileInfoLocalizedTemplateContentReader.cs
diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/VirtualFiles/ILocalizedTemplateContentReader.cs b/framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/VirtualFiles/ILocalizedTemplateContentReader.cs
similarity index 100%
rename from framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/VirtualFiles/ILocalizedTemplateContentReader.cs
rename to framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/VirtualFiles/ILocalizedTemplateContentReader.cs
diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/VirtualFiles/ILocalizedTemplateContentReaderFactory.cs b/framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/VirtualFiles/ILocalizedTemplateContentReaderFactory.cs
similarity index 100%
rename from framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/VirtualFiles/ILocalizedTemplateContentReaderFactory.cs
rename to framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/VirtualFiles/ILocalizedTemplateContentReaderFactory.cs
diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/VirtualFiles/LocalizedTemplateContentReaderFactory.cs b/framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/VirtualFiles/LocalizedTemplateContentReaderFactory.cs
similarity index 96%
rename from framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/VirtualFiles/LocalizedTemplateContentReaderFactory.cs
rename to framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/VirtualFiles/LocalizedTemplateContentReaderFactory.cs
index 981d1f8819..cc189e1b3b 100644
--- a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/VirtualFiles/LocalizedTemplateContentReaderFactory.cs
+++ b/framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/VirtualFiles/LocalizedTemplateContentReaderFactory.cs
@@ -64,7 +64,8 @@ namespace Volo.Abp.TextTemplating.VirtualFiles
if (fileInfo.IsDirectory)
{
- var folderReader = new VirtualFolderLocalizedTemplateContentReader();
+ //TODO: Configure file extensions.
+ var folderReader = new VirtualFolderLocalizedTemplateContentReader(new[] {".tpl", ".cshtml"});
await folderReader.ReadContentsAsync(VirtualFileProvider, virtualPath);
return folderReader;
}
diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/VirtualFiles/NullLocalizedTemplateContentReader.cs b/framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/VirtualFiles/NullLocalizedTemplateContentReader.cs
similarity index 100%
rename from framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/VirtualFiles/NullLocalizedTemplateContentReader.cs
rename to framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/VirtualFiles/NullLocalizedTemplateContentReader.cs
diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/VirtualFiles/VirtualFileTemplateContentContributor.cs b/framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/VirtualFiles/VirtualFileTemplateContentContributor.cs
similarity index 100%
rename from framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/VirtualFiles/VirtualFileTemplateContentContributor.cs
rename to framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/VirtualFiles/VirtualFileTemplateContentContributor.cs
diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/VirtualFiles/VirtualFolderLocalizedTemplateContentReader.cs b/framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/VirtualFiles/VirtualFolderLocalizedTemplateContentReader.cs
similarity index 80%
rename from framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/VirtualFiles/VirtualFolderLocalizedTemplateContentReader.cs
rename to framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/VirtualFiles/VirtualFolderLocalizedTemplateContentReader.cs
index 6fc7ff4847..27458d02cc 100644
--- a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/VirtualFiles/VirtualFolderLocalizedTemplateContentReader.cs
+++ b/framework/src/Volo.Abp.TextTemplating.Abstractions/Volo/Abp/TextTemplating/VirtualFiles/VirtualFolderLocalizedTemplateContentReader.cs
@@ -9,6 +9,12 @@ namespace Volo.Abp.TextTemplating.VirtualFiles
public class VirtualFolderLocalizedTemplateContentReader : ILocalizedTemplateContentReader
{
private Dictionary _dictionary;
+ private readonly string[] _fileExtension;
+
+ public VirtualFolderLocalizedTemplateContentReader(string[] fileExtension)
+ {
+ _fileExtension = fileExtension;
+ }
public async Task ReadContentsAsync(
IVirtualFileProvider virtualFileProvider,
@@ -29,7 +35,7 @@ namespace Volo.Abp.TextTemplating.VirtualFiles
continue;
}
- _dictionary.Add(file.Name.RemovePostFix(".tpl"), await file.ReadAsStringAsync());
+ _dictionary.Add(file.Name.RemovePostFix(_fileExtension), await file.ReadAsStringAsync());
}
}
diff --git a/framework/src/Volo.Abp.TextTemplating.Razor/FodyWeavers.xml b/framework/src/Volo.Abp.TextTemplating.Razor/FodyWeavers.xml
new file mode 100644
index 0000000000..be0de3a908
--- /dev/null
+++ b/framework/src/Volo.Abp.TextTemplating.Razor/FodyWeavers.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.TextTemplating.Razor/FodyWeavers.xsd b/framework/src/Volo.Abp.TextTemplating.Razor/FodyWeavers.xsd
new file mode 100644
index 0000000000..3f3946e282
--- /dev/null
+++ b/framework/src/Volo.Abp.TextTemplating.Razor/FodyWeavers.xsd
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.
+
+
+
+
+ A comma-separated list of error codes that can be safely ignored in assembly verification.
+
+
+
+
+ 'false' to turn off automatic generation of the XML Schema file.
+
+
+
+
+
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.TextTemplating.Razor/Volo.Abp.TextTemplating.Razor.csproj b/framework/src/Volo.Abp.TextTemplating.Razor/Volo.Abp.TextTemplating.Razor.csproj
new file mode 100644
index 0000000000..f4d16e630c
--- /dev/null
+++ b/framework/src/Volo.Abp.TextTemplating.Razor/Volo.Abp.TextTemplating.Razor.csproj
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/AbpRazorTemplateConsts.cs b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/AbpRazorTemplateConsts.cs
new file mode 100644
index 0000000000..7701a89630
--- /dev/null
+++ b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/AbpRazorTemplateConsts.cs
@@ -0,0 +1,9 @@
+namespace Volo.Abp.TextTemplating.Razor
+{
+ public static class AbpRazorTemplateConsts
+ {
+ public const string DefaultNameSpace = "Abp.Razor";
+ public const string DefaultClassName = "Template";
+ public const string TypeName = DefaultNameSpace + "." + DefaultClassName;
+ }
+}
diff --git a/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/AbpTextTemplatingRazorModule.cs b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/AbpTextTemplatingRazorModule.cs
new file mode 100644
index 0000000000..318a356b93
--- /dev/null
+++ b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/AbpTextTemplatingRazorModule.cs
@@ -0,0 +1,12 @@
+using Volo.Abp.Modularity;
+
+namespace Volo.Abp.TextTemplating.Razor
+{
+ [DependsOn(
+ typeof(AbpTextTemplatingAbstractionsModule)
+ )]
+ public class AbpTextTemplatingRazorModule : AbpModule
+ {
+
+ }
+}
diff --git a/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/CSharpCompiler.cs b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/CSharpCompiler.cs
new file mode 100644
index 0000000000..5c6bc2d190
--- /dev/null
+++ b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/CSharpCompiler.cs
@@ -0,0 +1,107 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.Extensions.Options;
+using Volo.Abp.DependencyInjection;
+
+namespace Volo.Abp.TextTemplating.Razor
+{
+ public class CSharpCompiler : ISingletonDependency
+ {
+ protected CSharpCompilerOptions Options { get; }
+
+ public CSharpCompiler(IOptions options)
+ {
+ Options = options.Value;
+ }
+
+ private static IEnumerable DefaultReferences => new List()
+ {
+ Assembly.Load("netstandard"),
+ Assembly.Load("System.Private.CoreLib"),
+ Assembly.Load("System.Runtime"),
+ Assembly.Load("System.Collections"),
+ Assembly.Load("System.ComponentModel"),
+ Assembly.Load("System.Linq"),
+ Assembly.Load("System.Linq.Expressions"),
+ Assembly.Load("Microsoft.Extensions.DependencyInjection"),
+ Assembly.Load("Microsoft.Extensions.DependencyInjection.Abstractions"),
+ Assembly.Load("Microsoft.Extensions.Localization"),
+ Assembly.Load("Microsoft.Extensions.Localization.Abstractions"),
+
+ typeof(CSharpCompiler).Assembly
+ }
+ .Select(x => MetadataReference.CreateFromFile(x.Location))
+ .ToImmutableList();
+
+ public virtual Stream CreateAssembly(string code, string assemblyName, List references = null, CSharpCompilationOptions options = null)
+ {
+ var defaultReferences = DefaultReferences.Concat(Options.References);
+ try
+ {
+ var compilation = CSharpCompilation.Create(
+ assemblyName,
+ syntaxTrees: new[] { CreateSyntaxTree(code) },
+ references: references != null ? defaultReferences.Concat(references) : defaultReferences,
+ options ?? GetCompilationOptions());
+
+ using (var memoryStream = new MemoryStream())
+ {
+ var result = compilation.Emit(memoryStream);
+
+ if (!result.Success)
+ {
+ var error = new StringBuilder();
+ error.AppendLine("Build failed");
+ foreach (var diagnostic in result.Diagnostics)
+ {
+ error.AppendLine(diagnostic.ToString());
+ }
+
+ throw new Exception(error.ToString());
+ }
+
+ memoryStream.Seek(0, SeekOrigin.Begin);
+ var assemblyStream = new MemoryStream();
+ memoryStream.CopyTo(assemblyStream);
+
+ return assemblyStream;
+ }
+ }
+ catch (Exception e)
+ {
+ var error = new StringBuilder();
+ error.AppendLine("CreateAssembly failed");
+ error.AppendLine(e.Message);
+ throw new Exception(error.ToString());
+ }
+ }
+
+ protected virtual SyntaxTree CreateSyntaxTree(string code)
+ {
+ return CSharpSyntaxTree.ParseText(code);
+ }
+
+ protected virtual CSharpCompilationOptions GetCompilationOptions()
+ {
+ var csharpCompilationOptions = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary);
+
+ // Disable 1702 until roslyn turns this off by default
+ csharpCompilationOptions = csharpCompilationOptions.WithSpecificDiagnosticOptions(
+ new Dictionary
+ {
+ {"CS1701", ReportDiagnostic.Suppress}, // Binding redirects
+ {"CS1702", ReportDiagnostic.Suppress},
+ {"CS1705", ReportDiagnostic.Suppress}
+ });
+
+ return csharpCompilationOptions.WithOptimizationLevel(OptimizationLevel.Release);
+ }
+ }
+}
diff --git a/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/CSharpCompilerOptions.cs b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/CSharpCompilerOptions.cs
new file mode 100644
index 0000000000..d419b83fca
--- /dev/null
+++ b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/CSharpCompilerOptions.cs
@@ -0,0 +1,15 @@
+using System.Collections.Generic;
+using Microsoft.CodeAnalysis;
+
+namespace Volo.Abp.TextTemplating.Razor
+{
+ public class CSharpCompilerOptions
+ {
+ public List References { get; }
+
+ public CSharpCompilerOptions()
+ {
+ References = new List();
+ }
+ }
+}
diff --git a/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/DefaultCompiledViewProvider.cs b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/DefaultCompiledViewProvider.cs
new file mode 100644
index 0000000000..ff954b3b99
--- /dev/null
+++ b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/DefaultCompiledViewProvider.cs
@@ -0,0 +1,64 @@
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.IO;
+using System.Reflection;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Razor.Language;
+using Volo.Abp.DependencyInjection;
+
+namespace Volo.Abp.TextTemplating.Razor
+{
+ public class DefaultCompiledViewProvider : ICompiledViewProvider, ITransientDependency
+ {
+ private static readonly ConcurrentDictionary CachedAssembles = new ConcurrentDictionary();
+
+ private readonly CSharpCompiler _cSharpCompiler;
+ private readonly IRazorProjectEngineFactory _razorProjectEngineFactory;
+ private readonly ITemplateContentProvider _templateContentProvider;
+
+ public DefaultCompiledViewProvider(
+ IRazorProjectEngineFactory razorProjectEngineFactory,
+ CSharpCompiler cSharpCompiler,
+ ITemplateContentProvider templateContentProvider)
+ {
+ _razorProjectEngineFactory = razorProjectEngineFactory;
+ _cSharpCompiler = cSharpCompiler;
+ _templateContentProvider = templateContentProvider;
+ }
+
+ public virtual async Task GetAssemblyAsync(TemplateDefinition templateDefinition)
+ {
+ async Task CreateAssembly(string content)
+ {
+ using (var assemblyStream = await GetAssemblyStreamAsync(templateDefinition, content))
+ {
+ return Assembly.Load(await assemblyStream.GetAllBytesAsync());
+ }
+ }
+
+ var templateContent = await _templateContentProvider.GetContentOrNullAsync(templateDefinition);
+ return CachedAssembles.GetOrAdd((templateDefinition.Name + templateContent).ToMd5(), await CreateAssembly(templateContent));
+ }
+
+ protected virtual async Task GetAssemblyStreamAsync(TemplateDefinition templateDefinition, string templateContent)
+ {
+ var razorProjectEngine = await _razorProjectEngineFactory.CreateAsync(builder =>
+ {
+ builder.SetNamespace(AbpRazorTemplateConsts.DefaultNameSpace);
+ builder.ConfigureClass((document, node) =>
+ {
+ node.ClassName = AbpRazorTemplateConsts.DefaultClassName;
+ });
+ });
+
+ var codeDocument = razorProjectEngine.Process(
+ RazorSourceDocument.Create(templateContent, templateDefinition.Name), null,
+ new List(), new List());
+
+ var cSharpDocument = codeDocument.GetCSharpDocument();
+
+ return _cSharpCompiler.CreateAssembly(cSharpDocument.GeneratedCode, templateDefinition.Name);
+ }
+ }
+}
diff --git a/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/DefaultRazorProjectEngineFactory.cs b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/DefaultRazorProjectEngineFactory.cs
new file mode 100644
index 0000000000..c402a26bb2
--- /dev/null
+++ b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/DefaultRazorProjectEngineFactory.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Razor.Language;
+using Volo.Abp.DependencyInjection;
+
+namespace Volo.Abp.TextTemplating.Razor
+{
+ public class DefaultRazorProjectEngineFactory : IRazorProjectEngineFactory, ITransientDependency
+ {
+ public virtual async Task CreateAsync(Action configure = null)
+ {
+ return RazorProjectEngine.Create(await CreateRazorConfigurationAsync(), EmptyProjectFileSystem.Empty, configure);
+ }
+
+ protected virtual Task CreateRazorConfigurationAsync()
+ {
+ return Task.FromResult(RazorConfiguration.Default);
+ }
+ }
+}
diff --git a/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/EmptyProjectFileSystem.cs b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/EmptyProjectFileSystem.cs
new file mode 100644
index 0000000000..496e86e977
--- /dev/null
+++ b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/EmptyProjectFileSystem.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.AspNetCore.Razor.Language;
+
+namespace Volo.Abp.TextTemplating.Razor
+{
+ internal class EmptyProjectFileSystem : RazorProjectFileSystem
+ {
+ internal static readonly RazorProjectFileSystem Empty = new EmptyProjectFileSystem();
+
+ public override IEnumerable EnumerateItems(string basePath)
+ {
+ NormalizeAndEnsureValidPath(basePath);
+ return Enumerable.Empty();
+ }
+
+ [Obsolete("Use GetItem(string path, string fileKind) instead.")]
+ public override RazorProjectItem GetItem(string path)
+ {
+ return GetItem(path, fileKind: null);
+ }
+
+ public override RazorProjectItem GetItem(string path, string fileKind)
+ {
+ NormalizeAndEnsureValidPath(path);
+ return new NotFoundProjectItem(string.Empty, path, fileKind);
+ }
+ }
+}
diff --git a/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/ICompiledViewProvider.cs b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/ICompiledViewProvider.cs
new file mode 100644
index 0000000000..a0bc2043aa
--- /dev/null
+++ b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/ICompiledViewProvider.cs
@@ -0,0 +1,10 @@
+using System.Reflection;
+using System.Threading.Tasks;
+
+namespace Volo.Abp.TextTemplating.Razor
+{
+ public interface ICompiledViewProvider
+ {
+ Task GetAssemblyAsync(TemplateDefinition templateDefinition);
+ }
+}
diff --git a/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/IRazorProjectEngineFactory.cs b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/IRazorProjectEngineFactory.cs
new file mode 100644
index 0000000000..138a78b72f
--- /dev/null
+++ b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/IRazorProjectEngineFactory.cs
@@ -0,0 +1,11 @@
+using System;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Razor.Language;
+
+namespace Volo.Abp.TextTemplating.Razor
+{
+ public interface IRazorProjectEngineFactory
+ {
+ Task CreateAsync(Action configure = null);
+ }
+}
diff --git a/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/IRazorTemplatePage.cs b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/IRazorTemplatePage.cs
new file mode 100644
index 0000000000..fc386c3353
--- /dev/null
+++ b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/IRazorTemplatePage.cs
@@ -0,0 +1,34 @@
+using System;
+using System.Collections.Generic;
+using System.Text.Encodings.Web;
+using System.Threading.Tasks;
+using Microsoft.Extensions.Localization;
+
+namespace Volo.Abp.TextTemplating.Razor
+{
+ public interface IRazorTemplatePage : IRazorTemplatePage
+ {
+ TModel Model { get; set; }
+ }
+
+ public interface IRazorTemplatePage
+ {
+ IServiceProvider ServiceProvider { get; set; }
+
+ IStringLocalizer Localizer { get; set; }
+
+ HtmlEncoder HtmlEncoder { get; set; }
+
+ JavaScriptEncoder JavaScriptEncoder { get; set; }
+
+ UrlEncoder UrlEncoder { get; set; }
+
+ Dictionary GlobalContext { get; set; }
+
+ string Body { get; set; }
+
+ Task ExecuteAsync();
+
+ Task GetOutputAsync();
+ }
+}
diff --git a/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/NotFoundProjectItem.cs b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/NotFoundProjectItem.cs
new file mode 100644
index 0000000000..735522bd09
--- /dev/null
+++ b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/NotFoundProjectItem.cs
@@ -0,0 +1,28 @@
+using System;
+using System.IO;
+using Microsoft.AspNetCore.Razor.Language;
+
+namespace Volo.Abp.TextTemplating.Razor
+{
+ internal class NotFoundProjectItem : RazorProjectItem
+ {
+ public NotFoundProjectItem(string basePath, string path, string fileKind)
+ {
+ BasePath = basePath;
+ FilePath = path;
+ FileKind = fileKind ?? FileKinds.GetFileKindFromFilePath(path);
+ }
+
+ public override string BasePath { get; }
+
+ public override string FilePath { get; }
+
+ public override string FileKind { get; }
+
+ public override bool Exists => false;
+
+ public override string PhysicalPath => throw new NotSupportedException();
+
+ public override Stream Read() => throw new NotSupportedException();
+ }
+}
diff --git a/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/RazorTemplatePageBase.cs b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/RazorTemplatePageBase.cs
new file mode 100644
index 0000000000..9854775a25
--- /dev/null
+++ b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/RazorTemplatePageBase.cs
@@ -0,0 +1,177 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Text.Encodings.Web;
+using System.Threading.Tasks;
+using Microsoft.Extensions.Localization;
+
+namespace Volo.Abp.TextTemplating.Razor
+{
+ public abstract class RazorTemplatePageBase : RazorTemplatePageBase, IRazorTemplatePage
+ {
+ public TModel Model { get; set; }
+ }
+
+ public abstract class RazorTemplatePageBase : IRazorTemplatePage
+ {
+ public Dictionary GlobalContext { get; set; }
+
+ public IServiceProvider ServiceProvider { get; set; }
+
+ public IStringLocalizer Localizer { get; set; }
+
+ public HtmlEncoder HtmlEncoder { get; set; }
+
+ public JavaScriptEncoder JavaScriptEncoder { get; set; }
+
+ public UrlEncoder UrlEncoder { get; set; }
+
+ public string Body { get; set; }
+
+ private readonly StringBuilder _stringBuilder = new StringBuilder();
+
+ private AttributeInfo _attributeInfo;
+
+ public virtual void WriteLiteral(string literal = null)
+ {
+ _stringBuilder.Append(literal);
+ }
+
+ public virtual void Write(object obj = null)
+ {
+ _stringBuilder.Append(obj);
+ }
+
+ public virtual void BeginWriteAttribute(string name, string prefix, int prefixOffset, string suffix, int suffixOffset, int attributeValuesCount)
+ {
+ _attributeInfo = new AttributeInfo(name, prefix, prefixOffset, suffix, suffixOffset, attributeValuesCount);
+ WriteLiteral(prefix);
+ }
+
+ public virtual void WriteAttributeValue(string prefix, int prefixOffset, object value, int valueOffset, int valueLength, bool isLiteral)
+ {
+ if (_attributeInfo.AttributeValuesCount == 1)
+ {
+ if (IsBoolFalseOrNullValue(prefix, value))
+ {
+ // Value is either null or the bool 'false' with no prefix; don't render the attribute.
+ _attributeInfo.Suppressed = true;
+ return;
+ }
+
+ // We are not omitting the attribute. Write the prefix.
+ WriteLiteral(_attributeInfo.Prefix);
+
+ if (IsBoolTrueWithEmptyPrefixValue(prefix, value))
+ {
+ // The value is just the bool 'true', write the attribute name instead of the string 'True'.
+ value = _attributeInfo.Name;
+ }
+ }
+
+ // This block handles two cases.
+ // 1. Single value with prefix.
+ // 2. Multiple values with or without prefix.
+ if (value != null)
+ {
+ if (!string.IsNullOrEmpty(prefix))
+ {
+ WriteLiteral(prefix);
+ }
+
+ WriteUnprefixedAttributeValue(value, isLiteral);
+ }
+
+ _stringBuilder.Append(prefix);
+ _stringBuilder.Append(value);
+ }
+
+ public virtual void EndWriteAttribute()
+ {
+ if (!_attributeInfo.Suppressed)
+ {
+ WriteLiteral(_attributeInfo.Suffix);
+ }
+ }
+
+ public virtual Task ExecuteAsync()
+ {
+ return Task.CompletedTask;
+ }
+
+ public virtual Task GetOutputAsync()
+ {
+ return Task.FromResult(_stringBuilder.ToString());
+ }
+
+ private void WriteUnprefixedAttributeValue(object value, bool isLiteral)
+ {
+ var stringValue = value as string;
+
+ // The extra branching here is to ensure that we call the Write*To(string) overload where possible.
+ if (isLiteral && stringValue != null)
+ {
+ WriteLiteral(stringValue);
+ }
+ else if (isLiteral)
+ {
+ //WriteLiteral(value);
+ _stringBuilder.Append(value);
+ }
+ else if (stringValue != null)
+ {
+ Write(stringValue);
+ }
+ else
+ {
+ Write(value);
+ }
+ }
+
+ private bool IsBoolFalseOrNullValue(string prefix, object value)
+ {
+ return string.IsNullOrEmpty(prefix) && (value == null || (value is bool b && !b));
+ }
+
+ private bool IsBoolTrueWithEmptyPrefixValue(string prefix, object value)
+ {
+ // If the value is just the bool 'true', use the attribute name as the value.
+ return string.IsNullOrEmpty(prefix) && (value is bool b && b);
+ }
+
+ private struct AttributeInfo
+ {
+ public AttributeInfo(
+ string name,
+ string prefix,
+ int prefixOffset,
+ string suffix,
+ int suffixOffset,
+ int attributeValuesCount)
+ {
+ Name = name;
+ Prefix = prefix;
+ PrefixOffset = prefixOffset;
+ Suffix = suffix;
+ SuffixOffset = suffixOffset;
+ AttributeValuesCount = attributeValuesCount;
+
+ Suppressed = false;
+ }
+
+ public int AttributeValuesCount { get; }
+
+ public string Name { get; }
+
+ public string Prefix { get; }
+
+ public int PrefixOffset { get; }
+
+ public string Suffix { get; }
+
+ public int SuffixOffset { get; }
+
+ public bool Suppressed { get; set; }
+ }
+ }
+}
diff --git a/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/RazorTemplateRenderer.cs b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/RazorTemplateRenderer.cs
new file mode 100644
index 0000000000..6ec926b398
--- /dev/null
+++ b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/RazorTemplateRenderer.cs
@@ -0,0 +1,168 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text.Encodings.Web;
+using System.Threading.Tasks;
+using JetBrains.Annotations;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Localization;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.Localization;
+
+namespace Volo.Abp.TextTemplating.Razor
+{
+ [Dependency(ReplaceServices = true)]
+ public class RazorTemplateRenderer : ITemplateRenderer, ITransientDependency
+ {
+ private readonly IServiceScopeFactory _serviceScopeFactory;
+ private readonly ICompiledViewProvider _compiledViewProvider;
+ private readonly ITemplateDefinitionManager _templateDefinitionManager;
+ private readonly IStringLocalizerFactory _stringLocalizerFactory;
+
+ public RazorTemplateRenderer(
+ IServiceScopeFactory serviceScopeFactory,
+ ICompiledViewProvider compiledViewProvider,
+ ITemplateDefinitionManager templateDefinitionManager,
+ IStringLocalizerFactory stringLocalizerFactory)
+ {
+ _serviceScopeFactory = serviceScopeFactory;
+ _templateDefinitionManager = templateDefinitionManager;
+ _stringLocalizerFactory = stringLocalizerFactory;
+ _compiledViewProvider = compiledViewProvider;
+ }
+
+ public virtual async Task RenderAsync(
+ [NotNull] string templateName,
+ [CanBeNull] object model = null,
+ [CanBeNull] string cultureName = null,
+ [CanBeNull] Dictionary globalContext = null)
+ {
+ Check.NotNullOrWhiteSpace(templateName, nameof(templateName));
+
+ if (globalContext == null)
+ {
+ globalContext = new Dictionary();
+ }
+
+ if (cultureName == null)
+ {
+ return await RenderInternalAsync(
+ templateName,
+ null,
+ globalContext,
+ model
+ );
+ }
+ else
+ {
+ using (CultureHelper.Use(cultureName))
+ {
+ return await RenderInternalAsync(
+ templateName,
+ null,
+ globalContext,
+ model
+ );
+ }
+ }
+ }
+
+ protected virtual async Task RenderInternalAsync(
+ string templateName,
+ string body,
+ Dictionary globalContext,
+ object model = null)
+ {
+ var templateDefinition = _templateDefinitionManager.Get(templateName);
+
+ var renderedContent = await RenderSingleTemplateAsync(
+ templateDefinition,
+ body,
+ globalContext,
+ model
+ );
+
+ if (templateDefinition.Layout != null)
+ {
+ renderedContent = await RenderInternalAsync(
+ templateDefinition.Layout,
+ renderedContent,
+ globalContext
+ );
+ }
+
+ return renderedContent;
+ }
+
+ protected virtual async Task RenderSingleTemplateAsync(
+ TemplateDefinition templateDefinition,
+ string body,
+ Dictionary globalContext,
+ object model = null)
+ {
+ return await RenderTemplateContentWithRazorAsync(
+ templateDefinition,
+ body,
+ globalContext,
+ model
+ );
+ }
+
+ protected virtual async Task RenderTemplateContentWithRazorAsync(
+ TemplateDefinition templateDefinition,
+ string body,
+ Dictionary globalContext,
+ object model = null)
+ {
+ var assembly = await _compiledViewProvider.GetAssemblyAsync(templateDefinition);
+ var templateType = assembly.GetType(AbpRazorTemplateConsts.TypeName);
+ var template = (IRazorTemplatePage) Activator.CreateInstance(templateType);
+
+ using (var scope = _serviceScopeFactory.CreateScope())
+ {
+ var modelType = templateType
+ .GetInterfaces()
+ .Where(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IRazorTemplatePage<>))
+ .Select(x => x.GenericTypeArguments.FirstOrDefault())
+ .FirstOrDefault();
+
+ if (modelType != null)
+ {
+ GetType().GetMethod(nameof(SetModel), BindingFlags.Instance | BindingFlags.NonPublic)
+ ?.MakeGenericMethod(modelType).Invoke(this, new[] {template, model});
+ }
+
+ template.ServiceProvider = scope.ServiceProvider;
+ template.Localizer = GetLocalizerOrNull(templateDefinition);
+ template.HtmlEncoder = scope.ServiceProvider.GetService();
+ template.JavaScriptEncoder = scope.ServiceProvider.GetService();
+ template.UrlEncoder = scope.ServiceProvider.GetService();
+ template.Body = body;
+ template.GlobalContext = globalContext;
+
+ await template.ExecuteAsync();
+
+ return await template.GetOutputAsync();
+ }
+ }
+
+ private void SetModel(IRazorTemplatePage razorTemplatePage, object model = null)
+ {
+ if (razorTemplatePage is IRazorTemplatePage razorTemplatePageWithModel)
+ {
+ razorTemplatePageWithModel.Model = (TModel)model;
+ }
+ }
+
+ private IStringLocalizer GetLocalizerOrNull(TemplateDefinition templateDefinition)
+ {
+ if (templateDefinition.LocalizationResource != null)
+ {
+ return _stringLocalizerFactory.Create(templateDefinition.LocalizationResource);
+ }
+
+ return _stringLocalizerFactory.CreateDefaultOrNull();
+ }
+ }
+}
diff --git a/framework/src/Volo.Abp.TextTemplating.Scriban/FodyWeavers.xml b/framework/src/Volo.Abp.TextTemplating.Scriban/FodyWeavers.xml
new file mode 100644
index 0000000000..be0de3a908
--- /dev/null
+++ b/framework/src/Volo.Abp.TextTemplating.Scriban/FodyWeavers.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.TextTemplating.Scriban/FodyWeavers.xsd b/framework/src/Volo.Abp.TextTemplating.Scriban/FodyWeavers.xsd
new file mode 100644
index 0000000000..3f3946e282
--- /dev/null
+++ b/framework/src/Volo.Abp.TextTemplating.Scriban/FodyWeavers.xsd
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.
+
+
+
+
+ A comma-separated list of error codes that can be safely ignored in assembly verification.
+
+
+
+
+ 'false' to turn off automatic generation of the XML Schema file.
+
+
+
+
+
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.TextTemplating.Scriban/Volo.Abp.TextTemplating.Scriban.csproj b/framework/src/Volo.Abp.TextTemplating.Scriban/Volo.Abp.TextTemplating.Scriban.csproj
new file mode 100644
index 0000000000..b4b0d66789
--- /dev/null
+++ b/framework/src/Volo.Abp.TextTemplating.Scriban/Volo.Abp.TextTemplating.Scriban.csproj
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/framework/src/Volo.Abp.TextTemplating.Scriban/Volo/Abp/TextTemplating/Scriban/AbpTextTemplatingScribanModule.cs b/framework/src/Volo.Abp.TextTemplating.Scriban/Volo/Abp/TextTemplating/Scriban/AbpTextTemplatingScribanModule.cs
new file mode 100644
index 0000000000..789b9e376f
--- /dev/null
+++ b/framework/src/Volo.Abp.TextTemplating.Scriban/Volo/Abp/TextTemplating/Scriban/AbpTextTemplatingScribanModule.cs
@@ -0,0 +1,12 @@
+using Volo.Abp.Modularity;
+
+namespace Volo.Abp.TextTemplating.Scriban
+{
+ [DependsOn(
+ typeof(AbpTextTemplatingAbstractionsModule)
+ )]
+ public class AbpTextTemplatingScribanModule : AbpModule
+ {
+
+ }
+}
diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateLocalizer.cs b/framework/src/Volo.Abp.TextTemplating.Scriban/Volo/Abp/TextTemplating/Scriban/ScribanTemplateLocalizer.cs
similarity index 91%
rename from framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateLocalizer.cs
rename to framework/src/Volo.Abp.TextTemplating.Scriban/Volo/Abp/TextTemplating/Scriban/ScribanTemplateLocalizer.cs
index 4e4a1e4833..e280cd194a 100644
--- a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateLocalizer.cs
+++ b/framework/src/Volo.Abp.TextTemplating.Scriban/Volo/Abp/TextTemplating/Scriban/ScribanTemplateLocalizer.cs
@@ -7,13 +7,13 @@ using Scriban;
using Scriban.Runtime;
using Scriban.Syntax;
-namespace Volo.Abp.TextTemplating
+namespace Volo.Abp.TextTemplating.Scriban
{
- public class TemplateLocalizer : IScriptCustomFunction
+ public class ScribanTemplateLocalizer : IScriptCustomFunction
{
private readonly IStringLocalizer _localizer;
- public TemplateLocalizer(IStringLocalizer localizer)
+ public ScribanTemplateLocalizer(IStringLocalizer localizer)
{
_localizer = localizer;
}
diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateRenderer.cs b/framework/src/Volo.Abp.TextTemplating.Scriban/Volo/Abp/TextTemplating/Scriban/ScribanTemplateRenderer.cs
similarity index 94%
rename from framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateRenderer.cs
rename to framework/src/Volo.Abp.TextTemplating.Scriban/Volo/Abp/TextTemplating/Scriban/ScribanTemplateRenderer.cs
index 1d89dc3b68..3fdd667a82 100644
--- a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateRenderer.cs
+++ b/framework/src/Volo.Abp.TextTemplating.Scriban/Volo/Abp/TextTemplating/Scriban/ScribanTemplateRenderer.cs
@@ -1,23 +1,21 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.Extensions.Localization;
-using Microsoft.Extensions.Options;
using Scriban;
using Scriban.Runtime;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Localization;
-namespace Volo.Abp.TextTemplating
+namespace Volo.Abp.TextTemplating.Scriban
{
- public class TemplateRenderer : ITemplateRenderer, ITransientDependency
+ public class ScribanTemplateRenderer : ITemplateRenderer, ITransientDependency
{
private readonly ITemplateContentProvider _templateContentProvider;
private readonly ITemplateDefinitionManager _templateDefinitionManager;
private readonly IStringLocalizerFactory _stringLocalizerFactory;
- public TemplateRenderer(
+ public ScribanTemplateRenderer(
ITemplateContentProvider templateContentProvider,
ITemplateDefinitionManager templateDefinitionManager,
IStringLocalizerFactory stringLocalizerFactory)
@@ -140,7 +138,7 @@ namespace Volo.Abp.TextTemplating
var localizer = GetLocalizerOrNull(templateDefinition);
if (localizer != null)
{
- scriptObject.SetValue("L", new TemplateLocalizer(localizer), true);
+ scriptObject.SetValue("L", new ScribanTemplateLocalizer(localizer), true);
}
context.PushGlobal(scriptObject);
diff --git a/framework/src/Volo.Abp.TextTemplating/Volo.Abp.TextTemplating.csproj b/framework/src/Volo.Abp.TextTemplating/Volo.Abp.TextTemplating.csproj
index 506b086a88..3af0ba984d 100644
--- a/framework/src/Volo.Abp.TextTemplating/Volo.Abp.TextTemplating.csproj
+++ b/framework/src/Volo.Abp.TextTemplating/Volo.Abp.TextTemplating.csproj
@@ -5,22 +5,11 @@
netstandard2.0
- Volo.Abp.TextTemplating
- Volo.Abp.TextTemplating
- $(AssetTargetFallback);portable-net45+win8+wp8+wpa81;
- false
- false
- false
-
-
-
-
-
-
+
diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/AbpTextTemplatingModule.cs b/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/AbpTextTemplatingModule.cs
index 8d76391829..6b0ad6fb11 100644
--- a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/AbpTextTemplatingModule.cs
+++ b/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/AbpTextTemplatingModule.cs
@@ -1,46 +1,9 @@
-using System;
-using System.Collections.Generic;
-using Microsoft.Extensions.DependencyInjection;
-using Volo.Abp.Localization;
-using Volo.Abp.Modularity;
-using Volo.Abp.VirtualFileSystem;
+using Volo.Abp.Modularity;
namespace Volo.Abp.TextTemplating
{
- [DependsOn(
- typeof(AbpVirtualFileSystemModule),
- typeof(AbpLocalizationAbstractionsModule)
- )]
public class AbpTextTemplatingModule : AbpModule
{
- public override void PreConfigureServices(ServiceConfigurationContext context)
- {
- AutoAddProvidersAndContributors(context.Services);
- }
- private static void AutoAddProvidersAndContributors(IServiceCollection services)
- {
- var definitionProviders = new List();
- var contentContributors = new List();
-
- services.OnRegistred(context =>
- {
- if (typeof(ITemplateDefinitionProvider).IsAssignableFrom(context.ImplementationType))
- {
- definitionProviders.Add(context.ImplementationType);
- }
-
- if (typeof(ITemplateContentContributor).IsAssignableFrom(context.ImplementationType))
- {
- contentContributors.Add(context.ImplementationType);
- }
- });
-
- services.Configure(options =>
- {
- options.DefinitionProviders.AddIfNotContains(definitionProviders);
- options.ContentContributors.AddIfNotContains(contentContributors);
- });
- }
}
}
diff --git a/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo.Abp.TextTemplating.Razor.Tests.csproj b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo.Abp.TextTemplating.Razor.Tests.csproj
new file mode 100644
index 0000000000..ca26b60a4b
--- /dev/null
+++ b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo.Abp.TextTemplating.Razor.Tests.csproj
@@ -0,0 +1,23 @@
+
+
+
+
+
+ net5.0
+
+
+
+
+
+ Always
+
+
+
+
+
+
+
+
+
+
+
diff --git a/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/RazorLocalizedTemplateContentReaderFactory_Tests.cs b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/RazorLocalizedTemplateContentReaderFactory_Tests.cs
new file mode 100644
index 0000000000..53eaf0fc80
--- /dev/null
+++ b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/RazorLocalizedTemplateContentReaderFactory_Tests.cs
@@ -0,0 +1,26 @@
+using System;
+using System.IO;
+using Microsoft.Extensions.FileProviders;
+using Volo.Abp.TextTemplating.VirtualFiles;
+
+namespace Volo.Abp.TextTemplating.Razor
+{
+ public class RazorLocalizedTemplateContentReaderFactory_Tests : LocalizedTemplateContentReaderFactory_Tests
+ {
+ public RazorLocalizedTemplateContentReaderFactory_Tests()
+ {
+ LocalizedTemplateContentReaderFactory = new LocalizedTemplateContentReaderFactory(
+ new PhysicalFileVirtualFileProvider(
+ new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(),
+ "Volo", "Abp", "TextTemplating", "Razor"))));
+
+ WelcomeEmailEnglishContent = "@inherits Volo.Abp.TextTemplating.Razor.RazorTemplatePageBase" +
+ Environment.NewLine +
+ "Welcome @Model.Name to the abp.io!";
+
+ WelcomeEmailTurkishContent = "@inherits Volo.Abp.TextTemplating.Razor.RazorTemplatePageBase" +
+ Environment.NewLine +
+ "Merhaba @Model.Name, abp.io'ya hoşgeldiniz!";
+ }
+ }
+}
diff --git a/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/RazorTemplateDefinitionTests.cs b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/RazorTemplateDefinitionTests.cs
new file mode 100644
index 0000000000..53c40b5ea8
--- /dev/null
+++ b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/RazorTemplateDefinitionTests.cs
@@ -0,0 +1,7 @@
+namespace Volo.Abp.TextTemplating.Razor
+{
+ public class RazorTemplateDefinitionTests : TemplateDefinitionTests
+ {
+
+ }
+}
diff --git a/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/RazorTemplateRenderer_Tests.cs b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/RazorTemplateRenderer_Tests.cs
new file mode 100644
index 0000000000..07da572c1e
--- /dev/null
+++ b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/RazorTemplateRenderer_Tests.cs
@@ -0,0 +1,145 @@
+using System.Threading.Tasks;
+using Shouldly;
+using Xunit;
+
+namespace Volo.Abp.TextTemplating.Razor
+{
+ public class RazorTemplateRenderer_Tests : AbpTextTemplatingTestBase
+ {
+ private readonly ITemplateRenderer _templateRenderer;
+
+ public RazorTemplateRenderer_Tests()
+ {
+ _templateRenderer = GetRequiredService();
+ }
+
+ [Fact]
+ public async Task Should_Get_Rendered_Localized_Template_Content_With_Different_Cultures()
+ {
+ (await _templateRenderer.RenderAsync(
+ TestTemplates.WelcomeEmail,
+ model: new WelcomeEmailModel()
+ {
+ Name = "John"
+ },
+ cultureName: "en"
+ )).ShouldBe("Welcome John to the abp.io!");
+
+ (await _templateRenderer.RenderAsync(
+ TestTemplates.WelcomeEmail,
+ model: new WelcomeEmailModel()
+ {
+ Name = "John"
+ },
+ cultureName: "tr"
+ )).ShouldBe("Merhaba John, abp.io'ya hoşgeldiniz!");
+
+ //"en-US" fallbacks to "en" since "en-US" doesn't exists and "en" is the fallback culture
+ (await _templateRenderer.RenderAsync(
+ TestTemplates.WelcomeEmail,
+ model: new WelcomeEmailModel()
+ {
+ Name = "John"
+ },
+ cultureName: "en-US"
+ )).ShouldBe("Welcome John to the abp.io!");
+
+ //"fr" fallbacks to "en" since "fr" doesn't exists and "en" is the default culture
+ (await _templateRenderer.RenderAsync(
+ TestTemplates.WelcomeEmail,
+ model: new WelcomeEmailModel()
+ {
+ Name = "John"
+ },
+ cultureName: "fr"
+ )).ShouldBe("Welcome John to the abp.io!");
+ }
+
+ [Fact]
+ public async Task Should_Get_Rendered_Localized_Template_Content_With_Stronly_Typed_Model()
+ {
+ (await _templateRenderer.RenderAsync(
+ TestTemplates.WelcomeEmail,
+ model: new WelcomeEmailModel("John"),
+ cultureName: "en"
+ )).ShouldBe("Welcome John to the abp.io!");
+ }
+
+ [Fact]
+ public async Task Should_Get_Rendered_Inline_Localized_Template()
+ {
+ (await _templateRenderer.RenderAsync(
+ TestTemplates.ForgotPasswordEmail,
+ new ForgotPasswordEmailModel("John"),
+ cultureName: "en"
+ )).ShouldBe("*BEGIN*Hello John, how are you?. Please click to the following link to get an email to reset your password!*END*");
+
+ (await _templateRenderer.RenderAsync(
+ TestTemplates.ForgotPasswordEmail,
+ new ForgotPasswordEmailModel("John"),
+ cultureName: "tr"
+ )).ShouldBe("*BEGIN*Merhaba John, nasılsın?. Please click to the following link to get an email to reset your password!*END*");
+ }
+
+ [Fact]
+ public async Task Should_Get_Localized_Numbers()
+ {
+ (await _templateRenderer.RenderAsync(
+ TestTemplates.ShowDecimalNumber,
+ new ShowDecimalNumberModel(123.45M),
+ cultureName: "en"
+ )).ShouldBe("*BEGIN*123.45*END*");
+
+ (await _templateRenderer.RenderAsync(
+ TestTemplates.ShowDecimalNumber,
+ new ShowDecimalNumberModel(123.45M),
+ cultureName: "de"
+ )).ShouldBe("*BEGIN*123,45*END*");
+ }
+
+ public class WelcomeEmailModel
+ {
+ public string Name { get; set; }
+
+ public WelcomeEmailModel()
+ {
+
+ }
+
+ public WelcomeEmailModel(string name)
+ {
+ Name = name;
+ }
+ }
+
+ public class ForgotPasswordEmailModel
+ {
+ public string Name { get; set; }
+
+ public ForgotPasswordEmailModel()
+ {
+
+ }
+
+ public ForgotPasswordEmailModel(string name)
+ {
+ Name = name;
+ }
+ }
+
+ public class ShowDecimalNumberModel
+ {
+ public decimal Amount { get; set; }
+
+ public ShowDecimalNumberModel()
+ {
+
+ }
+
+ public ShowDecimalNumberModel(decimal amount)
+ {
+ Amount = amount;
+ }
+ }
+ }
+}
diff --git a/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/RazorTestTemplateDefinitionProvider.cs b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/RazorTestTemplateDefinitionProvider.cs
new file mode 100644
index 0000000000..5fdd0a786b
--- /dev/null
+++ b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/RazorTestTemplateDefinitionProvider.cs
@@ -0,0 +1,20 @@
+namespace Volo.Abp.TextTemplating.Razor
+{
+ public class RazorTestTemplateDefinitionProvider : TemplateDefinitionProvider
+ {
+ public override void Define(ITemplateDefinitionContext context)
+ {
+ context.GetOrNull(TestTemplates.WelcomeEmail)?
+ .WithVirtualFilePath("/SampleTemplates/WelcomeEmail", false);
+
+ context.GetOrNull(TestTemplates.ForgotPasswordEmail)?
+ .WithVirtualFilePath("/SampleTemplates/ForgotPasswordEmail.cshtml", true);
+
+ context.GetOrNull(TestTemplates.TestTemplateLayout1)?
+ .WithVirtualFilePath("/SampleTemplates/TestTemplateLayout1.cshtml", true);
+
+ context.GetOrNull(TestTemplates.ShowDecimalNumber)?
+ .WithVirtualFilePath("/SampleTemplates/ShowDecimalNumber.cshtml", true);
+ }
+ }
+}
diff --git a/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/RazorTextTemplatingTestModule.cs b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/RazorTextTemplatingTestModule.cs
new file mode 100644
index 0000000000..6832f88dfa
--- /dev/null
+++ b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/RazorTextTemplatingTestModule.cs
@@ -0,0 +1,26 @@
+using Microsoft.CodeAnalysis;
+using Volo.Abp.Modularity;
+using Volo.Abp.VirtualFileSystem;
+
+namespace Volo.Abp.TextTemplating.Razor
+{
+ [DependsOn(
+ typeof(AbpTextTemplatingRazorModule),
+ typeof(AbpTextTemplatingTestModule)
+ )]
+ public class RazorTextTemplatingTestModule : AbpModule
+ {
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ Configure(options =>
+ {
+ options.FileSets.AddEmbedded("Volo.Abp.TextTemplating.Razor");
+ });
+
+ Configure(options =>
+ {
+ options.References.Add(MetadataReference.CreateFromFile(typeof(RazorTextTemplatingTestModule).Assembly.Location));
+ });
+ }
+ }
+}
diff --git a/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/RazorVirtualFileTemplateContributor_Tests.cs b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/RazorVirtualFileTemplateContributor_Tests.cs
new file mode 100644
index 0000000000..5634ccfa2c
--- /dev/null
+++ b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/RazorVirtualFileTemplateContributor_Tests.cs
@@ -0,0 +1,23 @@
+using System;
+using Volo.Abp.TextTemplating.VirtualFiles;
+
+namespace Volo.Abp.TextTemplating.Razor
+{
+ public class RazorVirtualFileTemplateContributor_Tests : VirtualFileTemplateContributor_Tests
+ {
+ public RazorVirtualFileTemplateContributor_Tests()
+ {
+ WelcomeEmailEnglishContent = "@inherits Volo.Abp.TextTemplating.Razor.RazorTemplatePageBase" +
+ Environment.NewLine +
+ "Welcome @Model.Name to the abp.io!";
+
+ WelcomeEmailTurkishContent = "@inherits Volo.Abp.TextTemplating.Razor.RazorTemplatePageBase" +
+ Environment.NewLine +
+ "Merhaba @Model.Name, abp.io'ya hoşgeldiniz!";
+
+ ForgotPasswordEmailEnglishContent = "@inherits Volo.Abp.TextTemplating.Razor.RazorTemplatePageBase" +
+ Environment.NewLine +
+ "@Localizer[\"HelloText\", Model.Name], @Localizer[\"HowAreYou\"]. Please click to the following link to get an email to reset your password!";
+ }
+ }
+}
diff --git a/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/SampleTemplates/ForgotPasswordEmail.cshtml b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/SampleTemplates/ForgotPasswordEmail.cshtml
new file mode 100644
index 0000000000..e02bc728ab
--- /dev/null
+++ b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/SampleTemplates/ForgotPasswordEmail.cshtml
@@ -0,0 +1,2 @@
+@inherits Volo.Abp.TextTemplating.Razor.RazorTemplatePageBase
+@Localizer["HelloText", Model.Name], @Localizer["HowAreYou"]. Please click to the following link to get an email to reset your password!
\ No newline at end of file
diff --git a/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/SampleTemplates/ShowDecimalNumber.cshtml b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/SampleTemplates/ShowDecimalNumber.cshtml
new file mode 100644
index 0000000000..d309dc5a2b
--- /dev/null
+++ b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/SampleTemplates/ShowDecimalNumber.cshtml
@@ -0,0 +1,2 @@
+@inherits Volo.Abp.TextTemplating.Razor.RazorTemplatePageBase
+@Model.Amount
\ No newline at end of file
diff --git a/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/SampleTemplates/TestTemplateLayout1.cshtml b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/SampleTemplates/TestTemplateLayout1.cshtml
new file mode 100644
index 0000000000..4d3bc7b7c2
--- /dev/null
+++ b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/SampleTemplates/TestTemplateLayout1.cshtml
@@ -0,0 +1,2 @@
+@inherits Volo.Abp.TextTemplating.Razor.RazorTemplatePageBase
+*BEGIN*@Body*END*
\ No newline at end of file
diff --git a/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/SampleTemplates/WelcomeEmail/en.cshtml b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/SampleTemplates/WelcomeEmail/en.cshtml
new file mode 100644
index 0000000000..410bfe1240
--- /dev/null
+++ b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/SampleTemplates/WelcomeEmail/en.cshtml
@@ -0,0 +1,2 @@
+@inherits Volo.Abp.TextTemplating.Razor.RazorTemplatePageBase
+Welcome @Model.Name to the abp.io!
\ No newline at end of file
diff --git a/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/SampleTemplates/WelcomeEmail/tr.cshtml b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/SampleTemplates/WelcomeEmail/tr.cshtml
new file mode 100644
index 0000000000..7ea3c8802a
--- /dev/null
+++ b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/SampleTemplates/WelcomeEmail/tr.cshtml
@@ -0,0 +1,2 @@
+@inherits Volo.Abp.TextTemplating.Razor.RazorTemplatePageBase
+Merhaba @Model.Name, abp.io'ya hoşgeldiniz!
\ No newline at end of file
diff --git a/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo.Abp.TextTemplating.Scriban.Tests.csproj b/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo.Abp.TextTemplating.Scriban.Tests.csproj
new file mode 100644
index 0000000000..d17a4d46fa
--- /dev/null
+++ b/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo.Abp.TextTemplating.Scriban.Tests.csproj
@@ -0,0 +1,23 @@
+
+
+
+
+
+ net5.0
+
+
+
+
+
+ Always
+
+
+
+
+
+
+
+
+
+
+
diff --git a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/SampleTemplates/ForgotPasswordEmail.tpl b/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/SampleTemplates/ForgotPasswordEmail.tpl
similarity index 100%
rename from framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/SampleTemplates/ForgotPasswordEmail.tpl
rename to framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/SampleTemplates/ForgotPasswordEmail.tpl
diff --git a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/SampleTemplates/ShowDecimalNumber.tpl b/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/SampleTemplates/ShowDecimalNumber.tpl
similarity index 100%
rename from framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/SampleTemplates/ShowDecimalNumber.tpl
rename to framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/SampleTemplates/ShowDecimalNumber.tpl
diff --git a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/SampleTemplates/TestTemplateLayout1.tpl b/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/SampleTemplates/TestTemplateLayout1.tpl
similarity index 100%
rename from framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/SampleTemplates/TestTemplateLayout1.tpl
rename to framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/SampleTemplates/TestTemplateLayout1.tpl
diff --git a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/SampleTemplates/WelcomeEmail/en.tpl b/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/SampleTemplates/WelcomeEmail/en.tpl
similarity index 100%
rename from framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/SampleTemplates/WelcomeEmail/en.tpl
rename to framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/SampleTemplates/WelcomeEmail/en.tpl
diff --git a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/SampleTemplates/WelcomeEmail/tr.tpl b/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/SampleTemplates/WelcomeEmail/tr.tpl
similarity index 100%
rename from framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/SampleTemplates/WelcomeEmail/tr.tpl
rename to framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/SampleTemplates/WelcomeEmail/tr.tpl
diff --git a/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/ScribanLocalizedTemplateContentReaderFactory_Tests.cs b/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/ScribanLocalizedTemplateContentReaderFactory_Tests.cs
new file mode 100644
index 0000000000..1757bdaa17
--- /dev/null
+++ b/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/ScribanLocalizedTemplateContentReaderFactory_Tests.cs
@@ -0,0 +1,20 @@
+using System.IO;
+using Microsoft.Extensions.FileProviders;
+using Volo.Abp.TextTemplating.VirtualFiles;
+
+namespace Volo.Abp.TextTemplating.Scriban
+{
+ public class ScribanLocalizedTemplateContentReaderFactory_Tests : LocalizedTemplateContentReaderFactory_Tests
+ {
+ public ScribanLocalizedTemplateContentReaderFactory_Tests()
+ {
+ LocalizedTemplateContentReaderFactory = new LocalizedTemplateContentReaderFactory(
+ new PhysicalFileVirtualFileProvider(
+ new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(),
+ "Volo", "Abp", "TextTemplating", "Scriban"))));
+
+ WelcomeEmailEnglishContent = "Welcome {{model.name}} to the abp.io!";
+ WelcomeEmailTurkishContent = "Merhaba {{model.name}}, abp.io'ya hoşgeldiniz!";
+ }
+ }
+}
diff --git a/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/ScribanTemplateDefinitionTests.cs b/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/ScribanTemplateDefinitionTests.cs
new file mode 100644
index 0000000000..e454af36ef
--- /dev/null
+++ b/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/ScribanTemplateDefinitionTests.cs
@@ -0,0 +1,7 @@
+namespace Volo.Abp.TextTemplating.Scriban
+{
+ public class ScribanTemplateDefinitionTests : TemplateDefinitionTests
+ {
+
+ }
+}
diff --git a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TemplateRenderer_Tests.cs b/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/ScribanTemplateRenderer_Tests.cs
similarity index 95%
rename from framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TemplateRenderer_Tests.cs
rename to framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/ScribanTemplateRenderer_Tests.cs
index ca4ae3e3fd..a076301919 100644
--- a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TemplateRenderer_Tests.cs
+++ b/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/ScribanTemplateRenderer_Tests.cs
@@ -3,13 +3,13 @@ using System.Threading.Tasks;
using Shouldly;
using Xunit;
-namespace Volo.Abp.TextTemplating
+namespace Volo.Abp.TextTemplating.Scriban
{
- public class TemplateRenderer_Tests : AbpTextTemplatingTestBase
+ public class ScribanTemplateRenderer_Tests : AbpTextTemplatingTestBase
{
private readonly ITemplateRenderer _templateRenderer;
- public TemplateRenderer_Tests()
+ public ScribanTemplateRenderer_Tests()
{
_templateRenderer = GetRequiredService();
}
@@ -91,7 +91,7 @@ namespace Volo.Abp.TextTemplating
cultureName: "tr"
)).ShouldBe("*BEGIN*Merhaba John, nasılsın?. Please click to the following link to get an email to reset your password!*END*");
}
-
+
[Fact]
public async Task Should_Get_Localized_Numbers()
{
diff --git a/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/ScribanTestTemplateDefinitionProvider.cs b/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/ScribanTestTemplateDefinitionProvider.cs
new file mode 100644
index 0000000000..956c376fd0
--- /dev/null
+++ b/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/ScribanTestTemplateDefinitionProvider.cs
@@ -0,0 +1,20 @@
+namespace Volo.Abp.TextTemplating.Scriban
+{
+ public class ScribanTestTemplateDefinitionProvider : TemplateDefinitionProvider
+ {
+ public override void Define(ITemplateDefinitionContext context)
+ {
+ context.GetOrNull(TestTemplates.WelcomeEmail)?
+ .WithVirtualFilePath("/SampleTemplates/WelcomeEmail", false);
+
+ context.GetOrNull(TestTemplates.ForgotPasswordEmail)?
+ .WithVirtualFilePath("/SampleTemplates/ForgotPasswordEmail.tpl", true);
+
+ context.GetOrNull(TestTemplates.TestTemplateLayout1)?
+ .WithVirtualFilePath("/SampleTemplates/TestTemplateLayout1.tpl", true);
+
+ context.GetOrNull(TestTemplates.ShowDecimalNumber)?
+ .WithVirtualFilePath("/SampleTemplates/ShowDecimalNumber.tpl", true);
+ }
+ }
+}
diff --git a/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/ScribanTextTemplatingTestModule.cs b/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/ScribanTextTemplatingTestModule.cs
new file mode 100644
index 0000000000..2ed2e51b56
--- /dev/null
+++ b/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/ScribanTextTemplatingTestModule.cs
@@ -0,0 +1,20 @@
+using Volo.Abp.Modularity;
+using Volo.Abp.VirtualFileSystem;
+
+namespace Volo.Abp.TextTemplating.Scriban
+{
+ [DependsOn(
+ typeof(AbpTextTemplatingScribanModule),
+ typeof(AbpTextTemplatingTestModule)
+ )]
+ public class ScribanTextTemplatingTestModule : AbpModule
+ {
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ Configure(options =>
+ {
+ options.FileSets.AddEmbedded("Volo.Abp.TextTemplating.Scriban");
+ });
+ }
+ }
+}
diff --git a/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/ScribanVirtualFileTemplateContributor_Tests.cs b/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/ScribanVirtualFileTemplateContributor_Tests.cs
new file mode 100644
index 0000000000..026b8abe59
--- /dev/null
+++ b/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/ScribanVirtualFileTemplateContributor_Tests.cs
@@ -0,0 +1,14 @@
+using Volo.Abp.TextTemplating.VirtualFiles;
+
+namespace Volo.Abp.TextTemplating.Scriban
+{
+ public class ScribanVirtualFileTemplateContributor_Tests : VirtualFileTemplateContributor_Tests
+ {
+ public ScribanVirtualFileTemplateContributor_Tests()
+ {
+ WelcomeEmailEnglishContent = "Welcome {{model.name}} to the abp.io!";
+ WelcomeEmailTurkishContent = "Merhaba {{model.name}}, abp.io'ya hoşgeldiniz!";
+ ForgotPasswordEmailEnglishContent = "{{L \"HelloText\" model.name}}, {{L \"HowAreYou\" }}. Please click to the following link to get an email to reset your password!";
+ }
+ }
+}
diff --git a/framework/test/Volo.Abp.TextTemplating.Tests/Volo.Abp.TextTemplating.Tests.csproj b/framework/test/Volo.Abp.TextTemplating.Tests/Volo.Abp.TextTemplating.Tests.csproj
index 555c2934b0..65983605be 100644
--- a/framework/test/Volo.Abp.TextTemplating.Tests/Volo.Abp.TextTemplating.Tests.csproj
+++ b/framework/test/Volo.Abp.TextTemplating.Tests/Volo.Abp.TextTemplating.Tests.csproj
@@ -10,15 +10,12 @@
-
- Always
-
-
+
diff --git a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/AbpTextTemplatingOptions_Tests.cs b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/AbpTextTemplatingOptions_Tests.cs
index 294596c693..591f6c9caf 100644
--- a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/AbpTextTemplatingOptions_Tests.cs
+++ b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/AbpTextTemplatingOptions_Tests.cs
@@ -4,7 +4,7 @@ using Xunit;
namespace Volo.Abp.TextTemplating
{
- public class AbpTextTemplatingOptions_Tests : AbpTextTemplatingTestBase
+ public class AbpTextTemplatingOptions_Tests : AbpTextTemplatingTestBase
{
private readonly AbpTextTemplatingOptions _options;
@@ -21,4 +21,4 @@ namespace Volo.Abp.TextTemplating
.ShouldContain(typeof(TestTemplateDefinitionProvider));
}
}
-}
\ No newline at end of file
+}
diff --git a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/AbpTextTemplatingTestBase.cs b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/AbpTextTemplatingTestBase.cs
index ca5dc20445..24f8bad395 100644
--- a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/AbpTextTemplatingTestBase.cs
+++ b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/AbpTextTemplatingTestBase.cs
@@ -1,8 +1,10 @@
-using Volo.Abp.Testing;
+using Volo.Abp.Modularity;
+using Volo.Abp.Testing;
namespace Volo.Abp.TextTemplating
{
- public abstract class AbpTextTemplatingTestBase : AbpIntegratedTest
+ public abstract class AbpTextTemplatingTestBase : AbpIntegratedTest
+ where TStartupModule : IAbpModule
{
protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options)
{
diff --git a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/AbpTextTemplatingTestModule.cs b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/AbpTextTemplatingTestModule.cs
index 8e8b69e116..74174ea690 100644
--- a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/AbpTextTemplatingTestModule.cs
+++ b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/AbpTextTemplatingTestModule.cs
@@ -7,7 +7,7 @@ using Volo.Abp.VirtualFileSystem;
namespace Volo.Abp.TextTemplating
{
[DependsOn(
- typeof(AbpTextTemplatingModule),
+ typeof(AbpTextTemplatingAbstractionsModule),
typeof(AbpTestBaseModule),
typeof(AbpAutofacModule),
typeof(AbpLocalizationModule)
diff --git a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TemplateDefinitionTests.cs b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TemplateDefinitionTests.cs
index 51c78cc13e..6fd97cd2d4 100644
--- a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TemplateDefinitionTests.cs
+++ b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TemplateDefinitionTests.cs
@@ -1,25 +1,27 @@
using Shouldly;
+using Volo.Abp.Modularity;
using Xunit;
namespace Volo.Abp.TextTemplating
{
- public class TemplateDefinitionTests : AbpTextTemplatingTestBase
+ public abstract class TemplateDefinitionTests : AbpTextTemplatingTestBase
+ where TStartupModule : IAbpModule
{
- private readonly ITemplateDefinitionManager _templateDefinitionManager;
+ protected readonly ITemplateDefinitionManager TemplateDefinitionManager;
- public TemplateDefinitionTests()
+ protected TemplateDefinitionTests()
{
- _templateDefinitionManager = GetRequiredService();
+ TemplateDefinitionManager = GetRequiredService();
}
[Fact]
public void Should_Retrieve_Template_Definition_By_Name()
{
- var welcomeEmailTemplate = _templateDefinitionManager.Get(TestTemplates.WelcomeEmail);
+ var welcomeEmailTemplate = TemplateDefinitionManager.Get(TestTemplates.WelcomeEmail);
welcomeEmailTemplate.Name.ShouldBe(TestTemplates.WelcomeEmail);
welcomeEmailTemplate.IsInlineLocalized.ShouldBeFalse();
- var forgotPasswordEmailTemplate = _templateDefinitionManager.Get(TestTemplates.ForgotPasswordEmail);
+ var forgotPasswordEmailTemplate = TemplateDefinitionManager.Get(TestTemplates.ForgotPasswordEmail);
forgotPasswordEmailTemplate.Name.ShouldBe(TestTemplates.ForgotPasswordEmail);
forgotPasswordEmailTemplate.IsInlineLocalized.ShouldBeTrue();
}
@@ -27,15 +29,15 @@ namespace Volo.Abp.TextTemplating
[Fact]
public void Should_Get_Null_If_Template_Not_Found()
{
- var definition = _templateDefinitionManager.GetOrNull("undefined-template");
+ var definition = TemplateDefinitionManager.GetOrNull("undefined-template");
definition.ShouldBeNull();
}
[Fact]
public void Should_Retrieve_All_Template_Definitions()
{
- var definitions = _templateDefinitionManager.GetAll();
+ var definitions = TemplateDefinitionManager.GetAll();
definitions.Count.ShouldBeGreaterThan(1);
}
}
-}
\ No newline at end of file
+}
diff --git a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TestTemplateDefinitionProvider.cs b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TestTemplateDefinitionProvider.cs
index 9db711d70c..289bf1b04f 100644
--- a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TestTemplateDefinitionProvider.cs
+++ b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TestTemplateDefinitionProvider.cs
@@ -10,7 +10,7 @@ namespace Volo.Abp.TextTemplating
new TemplateDefinition(
TestTemplates.WelcomeEmail,
defaultCultureName: "en"
- ).WithVirtualFilePath("/SampleTemplates/WelcomeEmail", false)
+ )
);
context.Add(
@@ -18,22 +18,22 @@ namespace Volo.Abp.TextTemplating
TestTemplates.ForgotPasswordEmail,
localizationResource: typeof(TestLocalizationSource),
layout: TestTemplates.TestTemplateLayout1
- ).WithVirtualFilePath("/SampleTemplates/ForgotPasswordEmail.tpl", true)
+ )
);
context.Add(
new TemplateDefinition(
TestTemplates.TestTemplateLayout1,
isLayout: true
- ).WithVirtualFilePath("/SampleTemplates/TestTemplateLayout1.tpl", true)
+ )
);
-
+
context.Add(
new TemplateDefinition(
TestTemplates.ShowDecimalNumber,
localizationResource: typeof(TestLocalizationSource),
layout: TestTemplates.TestTemplateLayout1
- ).WithVirtualFilePath("/SampleTemplates/ShowDecimalNumber.tpl", true)
+ )
);
}
}
diff --git a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/VirtualFiles/LocalizedTemplateContentReaderFactory_Tests.cs b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/VirtualFiles/LocalizedTemplateContentReaderFactory_Tests.cs
index 63e526ac1d..7a56997031 100644
--- a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/VirtualFiles/LocalizedTemplateContentReaderFactory_Tests.cs
+++ b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/VirtualFiles/LocalizedTemplateContentReaderFactory_Tests.cs
@@ -1,37 +1,36 @@
-using System.IO;
-using System.Threading.Tasks;
+using System.Threading.Tasks;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Primitives;
using Shouldly;
+using Volo.Abp.Modularity;
using Volo.Abp.VirtualFileSystem;
using Xunit;
namespace Volo.Abp.TextTemplating.VirtualFiles
{
- public class LocalizedTemplateContentReaderFactory_Tests: AbpTextTemplatingTestBase
+ public abstract class LocalizedTemplateContentReaderFactory_Tests : AbpTextTemplatingTestBase
+ where TStartupModule : IAbpModule
{
- private readonly ITemplateDefinitionManager _templateDefinitionManager;
+ protected readonly ITemplateDefinitionManager TemplateDefinitionManager;
+ protected LocalizedTemplateContentReaderFactory LocalizedTemplateContentReaderFactory;
+ protected string WelcomeEmailEnglishContent;
+ protected string WelcomeEmailTurkishContent;
- public LocalizedTemplateContentReaderFactory_Tests()
+ protected LocalizedTemplateContentReaderFactory_Tests()
{
- _templateDefinitionManager = GetRequiredService();
+ TemplateDefinitionManager = GetRequiredService();
}
[Fact]
public async Task Create_Should_Work_With_PhysicalFileProvider()
{
- var localizedTemplateContentReaderFactory = new LocalizedTemplateContentReaderFactory(
- new PhysicalFileVirtualFileProvider(
- new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(),
- "Volo", "Abp", "TextTemplating"))));
+ var reader = await LocalizedTemplateContentReaderFactory.CreateAsync(TemplateDefinitionManager.Get(TestTemplates.WelcomeEmail));
- var reader = await localizedTemplateContentReaderFactory.CreateAsync(_templateDefinitionManager.Get(TestTemplates.WelcomeEmail));
-
- reader.GetContentOrNull("en").ShouldBe("Welcome {{model.name}} to the abp.io!");
- reader.GetContentOrNull("tr").ShouldBe("Merhaba {{model.name}}, abp.io'ya hoşgeldiniz!");
+ reader.GetContentOrNull("en").ShouldBe(WelcomeEmailEnglishContent);
+ reader.GetContentOrNull("tr").ShouldBe(WelcomeEmailTurkishContent);
}
- class PhysicalFileVirtualFileProvider : IVirtualFileProvider
+ public class PhysicalFileVirtualFileProvider : IVirtualFileProvider
{
private readonly PhysicalFileProvider _physicalFileProvider;
diff --git a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/VirtualFiles/VirtualFileTemplateContributor_Tests.cs b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/VirtualFiles/VirtualFileTemplateContributor_Tests.cs
index e5c7138118..4862e61203 100644
--- a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/VirtualFiles/VirtualFileTemplateContributor_Tests.cs
+++ b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/VirtualFiles/VirtualFileTemplateContributor_Tests.cs
@@ -1,45 +1,50 @@
using System.Threading.Tasks;
using Shouldly;
+using Volo.Abp.Modularity;
using Xunit;
namespace Volo.Abp.TextTemplating.VirtualFiles
{
- public class VirtualFileTemplateContributor_Tests : AbpTextTemplatingTestBase
+ public abstract class VirtualFileTemplateContributor_Tests : AbpTextTemplatingTestBase
+ where TStartupModule : IAbpModule
{
- private readonly ITemplateDefinitionManager _templateDefinitionManager;
- private readonly VirtualFileTemplateContentContributor _virtualFileTemplateContentContributor;
+ protected readonly ITemplateDefinitionManager TemplateDefinitionManager;
+ protected readonly VirtualFileTemplateContentContributor VirtualFileTemplateContentContributor;
+ protected string WelcomeEmailEnglishContent;
+ protected string WelcomeEmailTurkishContent;
+ protected string ForgotPasswordEmailEnglishContent;
- public VirtualFileTemplateContributor_Tests()
+ protected VirtualFileTemplateContributor_Tests()
{
- _templateDefinitionManager = GetRequiredService();
- _virtualFileTemplateContentContributor = GetRequiredService();
+ TemplateDefinitionManager = GetRequiredService();
+ VirtualFileTemplateContentContributor = GetRequiredService();
}
[Fact]
public async Task Should_Get_Localized_Content_By_Culture()
{
- (await _virtualFileTemplateContentContributor.GetOrNullAsync(
- new TemplateContentContributorContext(_templateDefinitionManager.Get(TestTemplates.WelcomeEmail),
+ (await VirtualFileTemplateContentContributor.GetOrNullAsync(
+ new TemplateContentContributorContext(TemplateDefinitionManager.Get(TestTemplates.WelcomeEmail),
ServiceProvider,
"en")))
- .ShouldBe("Welcome {{model.name}} to the abp.io!");
+ .ShouldBe(WelcomeEmailEnglishContent);
- (await _virtualFileTemplateContentContributor.GetOrNullAsync(
- new TemplateContentContributorContext(_templateDefinitionManager.Get(TestTemplates.WelcomeEmail),
+ (await VirtualFileTemplateContentContributor.GetOrNullAsync(
+ new TemplateContentContributorContext(TemplateDefinitionManager.Get(TestTemplates.WelcomeEmail),
ServiceProvider,
"tr")))
- .ShouldBe("Merhaba {{model.name}}, abp.io'ya hoşgeldiniz!");
+ .ShouldBe(WelcomeEmailTurkishContent);
}
[Fact]
public async Task Should_Get_Non_Localized_Template_Content()
{
- (await _virtualFileTemplateContentContributor.GetOrNullAsync(
+ (await VirtualFileTemplateContentContributor.GetOrNullAsync(
new TemplateContentContributorContext(
- _templateDefinitionManager.Get(TestTemplates.ForgotPasswordEmail),
+ TemplateDefinitionManager.Get(TestTemplates.ForgotPasswordEmail),
ServiceProvider,
null)))
- .ShouldBe("{{L \"HelloText\" model.name}}, {{L \"HowAreYou\" }}. Please click to the following link to get an email to reset your password!");
+ .ShouldBe(ForgotPasswordEmailEnglishContent);
}
}
}
diff --git a/nupkg/common.ps1 b/nupkg/common.ps1
index c0e82e3486..e4ab829402 100644
--- a/nupkg/common.ps1
+++ b/nupkg/common.ps1
@@ -138,7 +138,10 @@ $projects = (
"framework/src/Volo.Abp.Sms.Aliyun",
"framework/src/Volo.Abp.Specifications",
"framework/src/Volo.Abp.TestBase",
+ "framework/src/Volo.Abp.TextTemplating.Abstractions",
"framework/src/Volo.Abp.TextTemplating",
+ "framework/src/Volo.Abp.TextTemplating.Razor",
+ "framework/src/Volo.Abp.TextTemplating.Scriban",
"framework/src/Volo.Abp.Threading",
"framework/src/Volo.Abp.Timing",
"framework/src/Volo.Abp.UI",