Refactored bundling

pull/301/head
Halil ibrahim Kalkan 7 years ago
parent 12c57c4c58
commit 052128c041

@ -0,0 +1,58 @@
using System;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling.TagHelpers
{
public abstract class AbpBundleItemTagHelper<TTagHelper, TTagHelperService> : AbpTagHelper<TTagHelper, TTagHelperService>, IBundleItemTagHelper
where TTagHelper : AbpTagHelper<TTagHelper, TTagHelperService>, IBundleItemTagHelper
where TTagHelperService: AbpTagHelperResourceItemService<TTagHelper>
{
/// <summary>
/// A file path.
/// </summary>
public string Src { get; set; }
/// <summary>
/// A bundle contributor type.
/// </summary>
public Type Type { get; set; }
protected AbpBundleItemTagHelper(TTagHelperService service)
: base(service)
{
}
public string GetNameOrNull()
{
if (Type != null)
{
return Type.FullName;
}
if (Src != null)
{
return Src
.RemovePreFix("/")
.RemovePostFix(StringComparison.OrdinalIgnoreCase, ".js")
.Replace("/", ".");
}
throw new AbpException("abp-script tag helper requires to set either src or type!");
}
public BundleTagHelperItem CreateBundleTagHelperItem()
{
if (Type != null)
{
return new BundleTagHelperItem(Type);
}
if (Src != null)
{
return new BundleTagHelperItem(Src);
}
throw new AbpException("abp-script tag helper requires to set either src or type!");
}
}
}

@ -0,0 +1,22 @@
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling.TagHelpers
{
public abstract class AbpBundleTagHelperBase<TTagHelper, TService> : AbpTagHelper<TTagHelper, TService>, IBundleTagHelper
where TTagHelper : AbpTagHelper<TTagHelper, TService>
where TService : class, IAbpTagHelperService<TTagHelper>
{
public string Name { get; set; }
protected AbpBundleTagHelperBase(TService service)
: base(service)
{
}
public virtual string GetNameOrNull()
{
return Name;
}
}
}

@ -8,29 +8,29 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling.TagHelpers
public abstract class AbpBundleTagHelperServiceBase<TTagHelper> : AbpTagHelperService<TTagHelper>
where TTagHelper : TagHelper, IBundleTagHelper
{
protected AbpTagHelperResourceHelper ResourceHelper { get; }
protected AbpTagHelperResourceService ResourceService { get; }
protected AbpBundleTagHelperServiceBase(AbpTagHelperResourceHelper resourceHelper)
protected AbpBundleTagHelperServiceBase(AbpTagHelperResourceService resourceService)
{
ResourceHelper = resourceHelper;
ResourceService = resourceService;
}
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
await ResourceHelper.ProcessAsync(
await ResourceService.ProcessAsync(
context,
output,
TagHelper.GetNameOrNull(),
await GetBundleItems(context, output)
await GetBundleItems(context, output),
TagHelper.GetNameOrNull()
);
}
protected virtual async Task<List<BundleTagHelperItem>> GetBundleItems(TagHelperContext context, TagHelperOutput output)
{
var fileList = new List<BundleTagHelperItem>();
context.Items[AbpTagHelperConsts.ContextBundleItemListKey] = fileList;
await output.GetChildContentAsync(); //TODO: Suppress child execution!
return fileList;
var bundleItems = new List<BundleTagHelperItem>();
context.Items[AbpTagHelperConsts.ContextBundleItemListKey] = bundleItems;
await output.GetChildContentAsync(); //TODO: Is there a way of executing children without getting content?
return bundleItems;
}
}
}

@ -1,21 +1,14 @@
using Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling.TagHelpers
{
[HtmlTargetElement("abp-script-bundle", TagStructure = TagStructure.NormalOrSelfClosing)]
public class AbpScriptBundleTagHelper : AbpTagHelper<AbpScriptBundleTagHelper, AbpScriptBundleTagHelperService>, IBundleTagHelper
public class AbpScriptBundleTagHelper : AbpBundleTagHelperBase<AbpScriptBundleTagHelper, AbpScriptBundleTagHelperService>, IBundleTagHelper
{
public string Name { get; set; }
public AbpScriptBundleTagHelper(AbpScriptBundleTagHelperService service)
: base(service)
{
}
public string GetNameOrNull()
{
return Name;
}
}
}

@ -1,8 +1,10 @@
namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling.TagHelpers
using Volo.Abp.AspNetCore.Mvc.UI.Bundling.TagHelpers.Internal;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling.TagHelpers
{
public class AbpScriptBundleTagHelperService : AbpBundleTagHelperServiceBase<AbpScriptBundleTagHelper>
{
public AbpScriptBundleTagHelperService(AbpTagHelperScriptHelper resourceHelper)
public AbpScriptBundleTagHelperService(AbpTagHelperScriptService resourceHelper)
: base(resourceHelper)
{
}

@ -1,59 +1,14 @@
using System;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers;
using Microsoft.AspNetCore.Razor.TagHelpers;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling.TagHelpers
{
[HtmlTargetElement("abp-script", TagStructure = TagStructure.NormalOrSelfClosing)]
public class AbpScriptTagHelper : AbpTagHelper<AbpScriptTagHelper, AbpScriptTagHelperService>, IBundleTagHelper
public class AbpScriptTagHelper : AbpBundleItemTagHelper<AbpScriptTagHelper, AbpScriptTagHelperService>, IBundleItemTagHelper
{
/// <summary>
/// A file path.
/// </summary>
public string Src { get; set; }
/// <summary>
/// A bundle contributor type.
/// </summary>
public Type Type { get; set; }
public AbpScriptTagHelper(AbpScriptTagHelperService service)
: base(service)
{
}
public string GetNameOrNull()
{
if (Type != null)
{
return Type.FullName;
}
if (Src != null)
{
return Src
.RemovePreFix("/")
.RemovePostFix(StringComparison.OrdinalIgnoreCase, ".js")
.Replace("/", ".");
}
throw new AbpException("abp-script tag helper requires to set either src or type!");
}
public BundleTagHelperItem CreateBundleTagHelperItem()
{
if (Type != null)
{
return new BundleTagHelperItem(Type);
}
if (Src != null)
{
return new BundleTagHelperItem(Src);
}
throw new AbpException("abp-script tag helper requires to set either src or type!");
}
}
}

@ -1,39 +1,12 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bundling.TagHelpers.Internal;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling.TagHelpers
{
public class AbpScriptTagHelperService : AbpTagHelperService<AbpScriptTagHelper>
public class AbpScriptTagHelperService : AbpTagHelperResourceItemService<AbpScriptTagHelper>
{
protected AbpTagHelperScriptHelper ResourceHelper { get; }
public AbpScriptTagHelperService(AbpTagHelperScriptHelper resourceHelper)
{
ResourceHelper = resourceHelper;
}
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
public AbpScriptTagHelperService(AbpTagHelperScriptService resourceService)
: base(resourceService)
{
var tagHelperItems = context.Items.GetOrDefault(AbpTagHelperConsts.ContextBundleItemListKey) as List<BundleTagHelperItem>;
if (tagHelperItems != null)
{
output.SuppressOutput();
tagHelperItems.Add(TagHelper.CreateBundleTagHelperItem());
}
else
{
await ResourceHelper.ProcessAsync(
context,
output,
TagHelper.GetNameOrNull(),
new List<BundleTagHelperItem>
{
TagHelper.CreateBundleTagHelperItem()
}
);
}
}
}
}

@ -1,23 +1,13 @@
using Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling.TagHelpers
{
//TODO: Move to Volo.Abp.AspNetCore.Mvc.UI package.
[HtmlTargetElement("abp-style-bundle", TagStructure = TagStructure.NormalOrSelfClosing)]
public class AbpStyleBundleTagHelper : AbpTagHelper<AbpStyleBundleTagHelper, AbpStyleBundleTagHelperService>, IBundleTagHelper
public class AbpStyleBundleTagHelper : AbpBundleTagHelperBase<AbpStyleBundleTagHelper, AbpStyleBundleTagHelperService>, IBundleTagHelper
{
public string Name { get; set; }
public AbpStyleBundleTagHelper(AbpStyleBundleTagHelperService service)
: base(service)
{
}
public string GetNameOrNull()
{
return Name;
}
}
}

@ -2,7 +2,7 @@
{
public class AbpStyleBundleTagHelperService : AbpBundleTagHelperServiceBase<AbpStyleBundleTagHelper>
{
public AbpStyleBundleTagHelperService(AbpTagHelperStyleHelper resourceHelper)
public AbpStyleBundleTagHelperService(AbpTagHelperStyleService resourceHelper)
: base(resourceHelper)
{
}

@ -1,59 +1,14 @@
using System;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers;
using Microsoft.AspNetCore.Razor.TagHelpers;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling.TagHelpers
{
[HtmlTargetElement("abp-style", TagStructure = TagStructure.NormalOrSelfClosing)]
public class AbpStyleTagHelper : AbpTagHelper<AbpStyleTagHelper, AbpStyleTagHelperService>, IBundleTagHelper
public class AbpStyleTagHelper : AbpBundleItemTagHelper<AbpStyleTagHelper, AbpStyleTagHelperService>, IBundleItemTagHelper
{
/// <summary>
/// A file path.
/// </summary>
public string Src { get; set; }
/// <summary>
/// A bundle contributor type.
/// </summary>
public Type Type { get; set; }
public AbpStyleTagHelper(AbpStyleTagHelperService service)
: base(service)
{
}
public string GetNameOrNull()
{
if (Type != null)
{
return Type.FullName;
}
if (Src != null)
{
return Src
.RemovePreFix("/")
.RemovePostFix(StringComparison.OrdinalIgnoreCase, ".css")
.Replace("/", ".");
}
throw new AbpException("abp-style tag helper requires to set either src or type!");
}
public BundleTagHelperItem CreateBundleTagHelperItem()
{
if (Type != null)
{
return new BundleTagHelperItem(Type);
}
if (Src != null)
{
return new BundleTagHelperItem(Src);
}
throw new AbpException("abp-style tag helper requires to set either src or type!");
}
}
}

@ -1,39 +1,10 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling.TagHelpers
namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling.TagHelpers
{
public class AbpStyleTagHelperService : AbpTagHelperService<AbpStyleTagHelper>
public class AbpStyleTagHelperService : AbpTagHelperResourceItemService<AbpStyleTagHelper>
{
protected AbpTagHelperStyleHelper ResourceHelper { get; }
public AbpStyleTagHelperService(AbpTagHelperStyleHelper resourceHelper)
public AbpStyleTagHelperService(AbpTagHelperStyleService resourceService)
: base(resourceService)
{
ResourceHelper = resourceHelper;
}
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
var tagHelperItems = context.Items.GetOrDefault(AbpTagHelperConsts.ContextBundleItemListKey) as List<BundleTagHelperItem>;
if (tagHelperItems != null)
{
output.SuppressOutput();
tagHelperItems.Add(TagHelper.CreateBundleTagHelperItem());
}
else
{
await ResourceHelper.ProcessAsync(
context,
output,
TagHelper.GetNameOrNull(),
new List<BundleTagHelperItem>
{
TagHelper.CreateBundleTagHelperItem()
}
);
}
}
}
}

@ -1,125 +0,0 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.VirtualFileSystem;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling.TagHelpers
{
public abstract class AbpTagHelperResourceHelper : ITransientDependency
{
protected IBundleManager BundleManager { get; }
protected IHybridWebRootFileProvider WebRootFileProvider { get; }
protected AbpTagHelperResourceHelper(
IBundleManager bundleManager,
IHybridWebRootFileProvider webRootFileProvider)
{
BundleManager = bundleManager;
WebRootFileProvider = webRootFileProvider;
}
public virtual async Task ProcessAsync(
TagHelperContext context,
TagHelperOutput output,
string bundleName,
List<BundleTagHelperItem> files)
{
output.TagName = null;
if (bundleName.IsNullOrEmpty())
{
bundleName = GenerateBundleName(files);
}
CreateBundle(bundleName, files);
var bundleFiles = GetBundleFiles(bundleName);
output.Content.Clear();
foreach (var bundleFile in bundleFiles)
{
var file = WebRootFileProvider.GetFileInfo(bundleFile);
if (file == null)
{
throw new AbpException($"Could not find the bundle file from {nameof(IHybridWebRootFileProvider)}");
}
AddHtmlTag(context, output, bundleFile + "?_v=" + file.LastModified.UtcTicks);
}
}
protected abstract void CreateBundle(string bundleName, List<BundleTagHelperItem> bundleItems);
protected abstract IReadOnlyList<string> GetBundleFiles(string bundleName);
protected abstract void AddHtmlTag(TagHelperContext context, TagHelperOutput output, string file);
protected virtual string GenerateBundleName(List<BundleTagHelperItem> bundleItems)
{
return bundleItems.JoinAsString("|").ToMd5();
}
}
public class AbpTagHelperScriptHelper : AbpTagHelperResourceHelper
{
public AbpTagHelperScriptHelper(
IBundleManager bundleManager,
IHybridWebRootFileProvider webRootFileProvider
) : base(
bundleManager,
webRootFileProvider)
{
}
protected override void CreateBundle(string bundleName, List<BundleTagHelperItem> bundleItems)
{
BundleManager.CreateScriptBundle(
bundleName,
configuration => bundleItems.ForEach(bi => bi.AddToConfiguration(configuration))
);
}
protected override IReadOnlyList<string> GetBundleFiles(string bundleName)
{
return BundleManager.GetScriptBundleFiles(bundleName);
}
protected override void AddHtmlTag(TagHelperContext context, TagHelperOutput output, string file)
{
output.Content.AppendHtml($"<script src=\"{file}\" type=\"text/javascript\"></script>{Environment.NewLine}");
}
}
public class AbpTagHelperStyleHelper : AbpTagHelperResourceHelper
{
public AbpTagHelperStyleHelper(
IBundleManager bundleManager,
IHybridWebRootFileProvider webRootFileProvider
) : base(
bundleManager,
webRootFileProvider)
{
}
protected override void CreateBundle(string bundleName, List<BundleTagHelperItem> bundleItems)
{
BundleManager.CreateStyleBundle(
bundleName,
configuration => bundleItems.ForEach(bi => bi.AddToConfiguration(configuration))
);
}
protected override IReadOnlyList<string> GetBundleFiles(string bundleName)
{
return BundleManager.GetStyleBundleFiles(bundleName);
}
protected override void AddHtmlTag(TagHelperContext context, TagHelperOutput output, string file)
{
output.Content.AppendHtml($"<link rel=\"stylesheet\" type=\"text/css\" href=\"{file}\" />{Environment.NewLine}");
}
}
}

@ -0,0 +1,40 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling.TagHelpers
{
public abstract class AbpTagHelperResourceItemService<TTagHelper> : AbpTagHelperService<TTagHelper>
where TTagHelper : TagHelper, IBundleItemTagHelper
{
protected AbpTagHelperResourceService ResourceService { get; }
protected AbpTagHelperResourceItemService(AbpTagHelperResourceService resourceService)
{
ResourceService = resourceService;
}
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
var tagHelperItems = context.Items.GetOrDefault(AbpTagHelperConsts.ContextBundleItemListKey) as List<BundleTagHelperItem>;
if (tagHelperItems != null)
{
output.SuppressOutput();
tagHelperItems.Add(TagHelper.CreateBundleTagHelperItem());
}
else
{
await ResourceService.ProcessAsync(
context,
output,
new List<BundleTagHelperItem>
{
TagHelper.CreateBundleTagHelperItem()
},
TagHelper.GetNameOrNull()
);
}
}
}
}

@ -0,0 +1,7 @@
namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling.TagHelpers
{
public interface IBundleItemTagHelper : IBundleTagHelper
{
BundleTagHelperItem CreateBundleTagHelperItem();
}
}

@ -0,0 +1,73 @@
using JetBrains.Annotations;
using Microsoft.AspNetCore.Razor.TagHelpers;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.AspNetCore.VirtualFileSystem;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling.TagHelpers
{
public abstract class AbpTagHelperResourceService : ITransientDependency
{
protected IBundleManager BundleManager { get; }
protected IHybridWebRootFileProvider WebRootFileProvider { get; }
protected AbpTagHelperResourceService(
IBundleManager bundleManager,
IHybridWebRootFileProvider webRootFileProvider)
{
BundleManager = bundleManager;
WebRootFileProvider = webRootFileProvider;
}
public virtual Task ProcessAsync(
[NotNull] TagHelperContext context,
[NotNull] TagHelperOutput output,
[NotNull] List<BundleTagHelperItem> bundleItems,
[CanBeNull] string bundleName = null)
{
Check.NotNull(context, nameof(context));
Check.NotNull(output, nameof(output));
Check.NotNull(bundleItems, nameof(bundleItems));
output.TagName = null;
if (bundleName.IsNullOrEmpty())
{
bundleName = GenerateBundleName(bundleItems);
}
CreateBundle(bundleName, bundleItems);
var bundleFiles = GetBundleFiles(bundleName);
output.Content.Clear();
foreach (var bundleFile in bundleFiles)
{
var file = WebRootFileProvider.GetFileInfo(bundleFile);
if (file == null)
{
throw new AbpException($"Could not find the bundle file from {nameof(IHybridWebRootFileProvider)}");
}
AddHtmlTag(context, output, bundleFile + "?_v=" + file.LastModified.UtcTicks);
}
return Task.CompletedTask;
}
protected abstract void CreateBundle(string bundleName, List<BundleTagHelperItem> bundleItems);
protected abstract IReadOnlyList<string> GetBundleFiles(string bundleName);
protected abstract void AddHtmlTag(TagHelperContext context, TagHelperOutput output, string file);
protected virtual string GenerateBundleName(List<BundleTagHelperItem> bundleItems)
{
return bundleItems.JoinAsString("|").ToMd5();
}
}
}

@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.VirtualFileSystem;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling.TagHelpers.Internal
{
public class AbpTagHelperScriptService : AbpTagHelperResourceService
{
public AbpTagHelperScriptService(
IBundleManager bundleManager,
IHybridWebRootFileProvider webRootFileProvider
) : base(
bundleManager,
webRootFileProvider)
{
}
protected override void CreateBundle(string bundleName, List<BundleTagHelperItem> bundleItems)
{
BundleManager.CreateScriptBundle(
bundleName,
configuration => bundleItems.ForEach(bi => bi.AddToConfiguration(configuration))
);
}
protected override IReadOnlyList<string> GetBundleFiles(string bundleName)
{
return BundleManager.GetScriptBundleFiles(bundleName);
}
protected override void AddHtmlTag(TagHelperContext context, TagHelperOutput output, string file)
{
output.Content.AppendHtml($"<script src=\"{file}\" type=\"text/javascript\"></script>{Environment.NewLine}");
}
}
}

@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.VirtualFileSystem;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling.TagHelpers
{
public class AbpTagHelperStyleService : AbpTagHelperResourceService
{
public AbpTagHelperStyleService(
IBundleManager bundleManager,
IHybridWebRootFileProvider webRootFileProvider
) : base(
bundleManager,
webRootFileProvider)
{
}
protected override void CreateBundle(string bundleName, List<BundleTagHelperItem> bundleItems)
{
BundleManager.CreateStyleBundle(
bundleName,
configuration => bundleItems.ForEach(bi => bi.AddToConfiguration(configuration))
);
}
protected override IReadOnlyList<string> GetBundleFiles(string bundleName)
{
return BundleManager.GetStyleBundleFiles(bundleName);
}
protected override void AddHtmlTag(TagHelperContext context, TagHelperOutput output, string file)
{
output.Content.AppendHtml($"<link rel=\"stylesheet\" type=\"text/css\" href=\"{file}\" />{Environment.NewLine}");
}
}
}
Loading…
Cancel
Save