diff --git a/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Bundling/AbpBundleFileTagHelper.cs b/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Bundling/AbpBundleFileTagHelper.cs new file mode 100644 index 0000000000..34e1eefb9a --- /dev/null +++ b/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Bundling/AbpBundleFileTagHelper.cs @@ -0,0 +1,17 @@ +using Microsoft.AspNetCore.Razor.TagHelpers; + +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Bundling +{ + [HtmlTargetElement("abp-bundle-file", TagStructure = TagStructure.NormalOrSelfClosing, ParentTag = "abp-style-bundle")] + [HtmlTargetElement("abp-bundle-file", TagStructure = TagStructure.NormalOrSelfClosing, ParentTag = "abp-script-bundle")] + public class AbpBundleFileTagHelper : AbpTagHelper + { + public string Src { get; set; } + + public AbpBundleFileTagHelper(AbpBundleFileTagHelperService service) + : base(service) + { + + } + } +} \ No newline at end of file diff --git a/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Bundling/AbpBundleFileTagHelperService.cs b/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Bundling/AbpBundleFileTagHelperService.cs new file mode 100644 index 0000000000..92db2b5eb3 --- /dev/null +++ b/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Bundling/AbpBundleFileTagHelperService.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; +using Microsoft.AspNetCore.Razor.TagHelpers; + +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Bundling +{ + public class AbpBundleFileTagHelperService : AbpTagHelperService + { + public const string ContextFileListKey = "AbpBundleFileTagHelperService.BundleFiles"; + + public override void Process(TagHelperContext context, TagHelperOutput output) + { + output.SuppressOutput(); + + var files = (List)context.Items[ContextFileListKey]; + files.Add(TagHelper.Src); + } + } +} \ No newline at end of file diff --git a/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Bundling/AbpScriptBundleTagHelper.cs b/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Bundling/AbpScriptBundleTagHelper.cs new file mode 100644 index 0000000000..5d64230981 --- /dev/null +++ b/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Bundling/AbpScriptBundleTagHelper.cs @@ -0,0 +1,15 @@ +using Microsoft.AspNetCore.Razor.TagHelpers; + +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Bundling +{ + [HtmlTargetElement("abp-script-bundle", TagStructure = TagStructure.NormalOrSelfClosing)] + public class AbpScriptBundleTagHelper : AbpTagHelper + { + public string Name { get; set; } + + public AbpScriptBundleTagHelper(AbpScriptBundleTagHelperService service) + : base(service) + { + } + } +} \ No newline at end of file diff --git a/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Bundling/AbpScriptBundleTagHelperService.cs b/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Bundling/AbpScriptBundleTagHelperService.cs new file mode 100644 index 0000000000..b75c936148 --- /dev/null +++ b/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Bundling/AbpScriptBundleTagHelperService.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Razor.TagHelpers; +using Volo.Abp.AspNetCore.Mvc.UI.Bundling; + +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Bundling +{ + public class AbpScriptBundleTagHelperService : AbpTagHelperService + { + private readonly IBundleManager _bundleManager; + + public AbpScriptBundleTagHelperService(IBundleManager bundleManager) + { + _bundleManager = bundleManager; + } + + public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) + { + output.TagName = null; + + var bundleName = TagHelper.Name; + var files = await GetFileList(context, output); + if (bundleName.IsNullOrEmpty()) + { + bundleName = GenerateBundleName(context, output, files); + } + + _bundleManager.CreateDynamicScriptBundle( + bundleName, + configuration => configuration.AddFiles(files.ToArray()) + ); + + var bundleFiles = _bundleManager.GetScriptBundleFiles(bundleName); + await output.GetChildContentAsync(); //TODO: Suppress child execution! + output.Content.Clear(); + AddLinkTags(context, output, bundleFiles); + } + + protected virtual void AddLinkTags(TagHelperContext context, TagHelperOutput output, List files) + { + foreach (var file in files) + { + output.Content.AppendHtml($"{Environment.NewLine}"); + } + } + + protected virtual string GenerateBundleName(TagHelperContext context, TagHelperOutput output, List fileList) + { + return fileList.JoinAsString("|").ToMd5(); + } + + protected virtual async Task> GetFileList(TagHelperContext context, TagHelperOutput output) + { + var fileList = new List(); + context.Items[AbpBundleFileTagHelperService.ContextFileListKey] = fileList; + await output.GetChildContentAsync(); + return fileList; + } + } +} \ No newline at end of file diff --git a/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Bundling/AbpStyleBundleTagHelper.cs b/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Bundling/AbpStyleBundleTagHelper.cs new file mode 100644 index 0000000000..866c78a19f --- /dev/null +++ b/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Bundling/AbpStyleBundleTagHelper.cs @@ -0,0 +1,18 @@ +using Microsoft.AspNetCore.Razor.TagHelpers; +using Volo.Abp.Threading; + +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Bundling +{ + //TODO: Move to Volo.Abp.AspNetCore.Mvc.UI package. + + [HtmlTargetElement("abp-style-bundle", TagStructure = TagStructure.NormalOrSelfClosing)] + public class AbpStyleBundleTagHelper : AbpTagHelper + { + public string Name { get; set; } + + public AbpStyleBundleTagHelper(AbpStyleBundleTagHelperService service) + : base(service) + { + } + } +} diff --git a/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Bundling/AbpStyleBundleTagHelperService.cs b/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Bundling/AbpStyleBundleTagHelperService.cs new file mode 100644 index 0000000000..32758ba1a7 --- /dev/null +++ b/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Bundling/AbpStyleBundleTagHelperService.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Razor.TagHelpers; +using Volo.Abp.AspNetCore.Mvc.UI.Bundling; + +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Bundling +{ + public class AbpStyleBundleTagHelperService : AbpTagHelperService + { + private readonly IBundleManager _bundleManager; + + public AbpStyleBundleTagHelperService(IBundleManager bundleManager) + { + _bundleManager = bundleManager; + } + + public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) + { + output.TagName = null; + + var bundleName = TagHelper.Name; + var files = await GetFileList(context, output); + if (bundleName.IsNullOrEmpty()) + { + bundleName = GenerateBundleName(context, output, files); + } + + _bundleManager.CreateDynamicStyleBundle( + bundleName, + configuration => configuration.AddFiles(files.ToArray()) + ); + + var bundleFiles = _bundleManager.GetStyleBundleFiles(bundleName); + await output.GetChildContentAsync(); //TODO: Suppress child execution! + output.Content.Clear(); + AddLinkTags(context, output, bundleFiles); + } + + protected virtual void AddLinkTags(TagHelperContext context, TagHelperOutput output, List files) + { + foreach (var file in files) + { + output.Content.AppendHtml( + $"{Environment.NewLine}"); + } + } + + protected virtual string GenerateBundleName(TagHelperContext context, TagHelperOutput output, List fileList) + { + return fileList.JoinAsString("|").ToMd5(); + } + + protected virtual async Task> GetFileList(TagHelperContext context, TagHelperOutput output) + { + var fileList = new List(); + context.Items[AbpBundleFileTagHelperService.ContextFileListKey] = fileList; + await output.GetChildContentAsync(); + return fileList; + } + } +} \ No newline at end of file diff --git a/src/Volo.Abp.AspNetCore.Mvc.UI/UI/Bundling/BundleCollection.cs b/src/Volo.Abp.AspNetCore.Mvc.UI/UI/Bundling/BundleCollection.cs index ae6b3c8c78..efbed2dd1d 100644 --- a/src/Volo.Abp.AspNetCore.Mvc.UI/UI/Bundling/BundleCollection.cs +++ b/src/Volo.Abp.AspNetCore.Mvc.UI/UI/Bundling/BundleCollection.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling { @@ -34,9 +35,16 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling return _bundleContributors[bundleName]; } - public BundleConfiguration GetOrAdd(string bundleName) + public BundleConfiguration GetOrAdd(string bundleName, Action configureAction = null) { - return _bundleContributors.GetOrAdd(bundleName, () => new BundleConfiguration(bundleName)); + return _bundleContributors.GetOrAdd( + bundleName, + () => + { + var configuration = new BundleConfiguration(bundleName); + configureAction?.Invoke(configuration); + return configuration; + }); } public List GetFiles(string bundleName) diff --git a/src/Volo.Abp.AspNetCore.Mvc.UI/UI/Bundling/BundleManager.cs b/src/Volo.Abp.AspNetCore.Mvc.UI/UI/Bundling/BundleManager.cs index f07e94a6ef..fb15685df6 100644 --- a/src/Volo.Abp.AspNetCore.Mvc.UI/UI/Bundling/BundleManager.cs +++ b/src/Volo.Abp.AspNetCore.Mvc.UI/UI/Bundling/BundleManager.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Concurrent; using System.Collections.Generic; using Microsoft.AspNetCore.Hosting; @@ -48,5 +49,17 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling ) }; } + + public void CreateDynamicStyleBundle(string bundleName, Action configureAction) + { + //TODO: How to handle concurrency! + _options.StyleBundles.GetOrAdd(bundleName, configureAction); + } + + public void CreateDynamicScriptBundle(string bundleName, Action configureAction) + { + //TODO: How to handle concurrency! + _options.ScriptBundles.GetOrAdd(bundleName, configureAction); + } } } \ No newline at end of file diff --git a/src/Volo.Abp.AspNetCore.Mvc.UI/UI/Bundling/IBundleManager.cs b/src/Volo.Abp.AspNetCore.Mvc.UI/UI/Bundling/IBundleManager.cs index 1920e39838..263eecba84 100644 --- a/src/Volo.Abp.AspNetCore.Mvc.UI/UI/Bundling/IBundleManager.cs +++ b/src/Volo.Abp.AspNetCore.Mvc.UI/UI/Bundling/IBundleManager.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling @@ -7,5 +8,9 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling List GetStyleBundleFiles(string bundleName); List GetScriptBundleFiles(string bundleName); + + void CreateDynamicStyleBundle(string bundleName, Action configureAction); + + void CreateDynamicScriptBundle(string bundleName, Action configureAction); } } \ No newline at end of file