Skip to content

Instantly share code, notes, and snippets.

@SebastianStehle
Created September 23, 2015 11:55
Show Gist options
  • Save SebastianStehle/aedbba3304baa8e9d491 to your computer and use it in GitHub Desktop.
Save SebastianStehle/aedbba3304baa8e9d491 to your computer and use it in GitHub Desktop.
using Microsoft.AspNet.FileProviders;
using Microsoft.AspNet.Hosting;
using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
using Microsoft.Framework.Runtime;
using System;
using System.IO;
using System.Text;
namespace BundleHelpers
{
public abstract class BundleTagHelper : TagHelper
{
public const string AttributeBase = "base";
public const string AttributeFile = "file";
public const string AttributeBundle = "bundle";
public const string AttributeMinified = "minified";
private readonly IApplicationEnvironment applicationEnvironment;
private readonly IHostingEnvironment hostingEnvironment;
[HtmlAttributeName(AttributeBase)]
public string Base { get; set; }
[HtmlAttributeName(AttributeFile)]
public string File { get; set; }
[HtmlAttributeName(AttributeBundle)]
public bool UseBundle { get; set; }
[HtmlAttributeName(AttributeMinified)]
public bool UseMinified { get; set; }
[HtmlAttributeNotBound]
[ViewContext]
protected ViewContext Context { get; set; }
protected abstract bool AppendVersion { get; }
protected abstract string MinExtension { get; }
protected abstract string Extension { get; }
protected BundleTagHelper(IApplicationEnvironment applicationEnvironment, IHostingEnvironment hostingEnvironment)
{
this.applicationEnvironment = applicationEnvironment;
this.hostingEnvironment = hostingEnvironment;
}
protected abstract string BuildTag(string file);
public override void Process(TagHelperContext context, TagHelperOutput output)
{
string file = File;
if (!string.IsNullOrWhiteSpace(file))
{
file = HtmlFileHelper.ReplaceCultureTag(file);
if (file.EndsWith(".bundle", StringComparison.OrdinalIgnoreCase))
{
if (!UseBundle)
{
AppendBundleFiles(output, file);
}
else
{
AppendBundledFile(output, file);
}
}
else
{
AppendSimpleFile(output, file);
}
output.TagName = string.Empty;
}
base.Process(context, output);
}
private void AppendBundleFiles(TagHelperOutput output, string file)
{
StringBuilder mvcHtmlStringBuilder = new StringBuilder();
mvcHtmlStringBuilder.Append("<!-- BUNDLE START: ");
mvcHtmlStringBuilder.Append(file);
mvcHtmlStringBuilder.AppendLine("-->");
int slashIndex = file.LastIndexOf('/');
string directory = MakeAbsolutePath((slashIndex >= 0 ? file.Substring(0, slashIndex) : file).Trim('/'));
IFileInfo bundleFile = hostingEnvironment.WebRootFileProvider.GetFileInfo(NormalizePath(file));
if (bundleFile.Exists)
{
using (Stream stream = bundleFile.CreateReadStream())
{
using (StreamReader reader = new StreamReader(stream))
{
string includedPath;
while ((includedPath = reader.ReadLine()) != null)
{
if (includedPath.StartsWith("//= include", StringComparison.OrdinalIgnoreCase))
{
includedPath = includedPath.Replace("//= include ", string.Empty);
includedPath = includedPath.TrimStart('/');
includedPath = directory + "/" + includedPath;
includedPath = AdjustContentPath(includedPath);
string tag = BuildTag(includedPath);
mvcHtmlStringBuilder.AppendLine(tag);
}
}
}
}
}
mvcHtmlStringBuilder.Append("<!-- BUNDLE END: ");
mvcHtmlStringBuilder.Append(file);
mvcHtmlStringBuilder.AppendLine("-->");
output.PostContent.Append(mvcHtmlStringBuilder.ToString());
}
private void AppendBundledFile(TagHelperOutput output, string file)
{
file = file.Replace(".bundle", Extension);
file = AdjustContentPath(file);
string tag = BuildTag(file);
output.PostContent.Append(tag);
}
private void AppendSimpleFile(TagHelperOutput output, string file)
{
file = AdjustContentPath(file);
string tag = BuildTag(file);
output.PostContent.Append(tag);
}
protected internal virtual string NormalizePath(string path)
{
if (path.StartsWith("~/", StringComparison.Ordinal))
{
return path.Substring(1).Replace('\\', '/');
}
if (path.StartsWith("~\\", StringComparison.Ordinal))
{
return path;
}
return path.Replace('\\', '/');
}
private string AdjustContentPath(string path)
{
if (UseMinified && !string.IsNullOrWhiteSpace(MinExtension) && !path.EndsWith(MinExtension, StringComparison.OrdinalIgnoreCase))
{
path = path.Replace(Extension, MinExtension);
}
if (AppendVersion)
{
path += "?v=" + applicationEnvironment.Version;
}
path = MakeAbsolutePath(path);
return path;
}
private string MakeAbsolutePath(string path)
{
string basePath = Base;
if (string.IsNullOrWhiteSpace(basePath))
{
basePath = Context.HttpContext.Request.PathBase;
}
if (!basePath.EndsWith("/", StringComparison.OrdinalIgnoreCase))
{
basePath = basePath + "/";
}
path = basePath + path.TrimStart('/', '~').ToLowerInvariant();
return path;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment