xurca
xurca

Reputation: 2426

asp.net mvc exclude css file from bundle

I have such bundle

bundles.Add(new StyleBundle("~/Content/themes/default/css")
       .IncludeDirectory("~/Content/themes/Default", "*.css"));

but I want to exclude one CSS file from it.

Is it possible to make this without specifying each CSS file in bundle?

Upvotes: 26

Views: 10511

Answers (4)

Ilya Chernomordik
Ilya Chernomordik

Reputation: 30185

I have improved the good suggestion by Jon Malcolm (and some updates by Satpal here) to fix few shortcomings that it had:

1) It breaks the default behavior of the bundles with ".min." files

2) It does not allow search patterns, but only files to be excluded

using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Optimization;


public static class BundleExtentions
{
    public static Bundle IncludeDirectoryWithExclusion(this Bundle bundle, string directoryVirtualPath, string searchPattern, bool includeSubDirectories, params string[] excludePatterns)
    {
        string folderPath = HttpContext.Current.Server.MapPath(directoryVirtualPath);

        SearchOption searchOption = includeSubDirectories
                                        ? SearchOption.AllDirectories
                                        : SearchOption.TopDirectoryOnly;

        HashSet<string> excludedFiles = GetFilesToExclude(folderPath, searchOption, excludePatterns);
        IEnumerable<string> resultFiles = Directory.GetFiles(folderPath, searchPattern, searchOption)
                                                    .Where(file => !excludedFiles.Contains(file) && !file.Contains(".min."));

        foreach (string resultFile in resultFiles)
        {
            bundle.Include(directoryVirtualPath + resultFile.Replace(folderPath, "")
                    .Replace("\\", "/"));
        }

        return bundle;
    }

    private static HashSet<string> GetFilesToExclude(string path, SearchOption searchOptions, params string[] excludePatterns)
    {
        var result = new HashSet<string>();

        foreach (string pattern in excludePatterns)
        {
            result.UnionWith(Directory.GetFiles(path, pattern, searchOptions));
        }

        return result;
    }
}

An example usage that I have is to include all the libraries from the lib folder starting with angular, but excluding all the locale scripts (because only one will be added based on the language in a separate bundle later):

bundles.Add(new Bundle("~/bundles/scripts")
                .Include("~/wwwroot/lib/angular/angular.js") // Has to be first
                .IncludeDirectoryWithExclusion("~/wwwroot/lib", "*.js", true, "*.locale.*.js"));

This will behave properly if you have both angular.min.js and angular.js and add unminified version in debug and using the existing .min.js in the release.

Upvotes: 4

CoffeeCode
CoffeeCode

Reputation: 4314

Try using IgnoreList.Ignore; bundles.IgnoreList.Ignore(...).

Upvotes: 38

Jeff Camera
Jeff Camera

Reputation: 5544

Here's another extension method that overloads the existing IncludeDirectory methods and supports searching subdirectories.

public static class BundleExtensions
{
    public static Bundle IncludeDirectory(
        this Bundle bundle,
        string directoryVirtualPath,
        string searchPattern,
        params string[] filesToExclude)
    {
        return IncludeDirectory(bundle, directoryVirtualPath, searchPattern, false, filesToExclude);
    }
    public static Bundle IncludeDirectory(
        this Bundle bundle,
        string directoryVirtualPath,
        string searchPattern,
        bool searchSubdirectories,
        params string[] filesToExclude)
    {
        var physicalPath = HttpContext.Current.Server.MapPath(directoryVirtualPath);
        return bundle.Include(Directory
            .EnumerateFiles(physicalPath, searchPattern, searchSubdirectories ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly)
            .Select(physicalFileName => physicalFileName.Replace(physicalPath, directoryVirtualPath).Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar))
            .Where(virtualFileName => !filesToExclude.Contains(virtualFileName))
            .ToArray());
    }
}

Upvotes: 1

Jon Malcolm
Jon Malcolm

Reputation: 461

An extension method could be what you need here:

public static class BundleExtentions
{
    public static Bundle IncludeDirectoryWithExclusion(this StyleBundle bundle, string directoryVirtualPath, string searchPattern, params string[] toExclude)
    {
        var folderPath = HttpContext.Current.Server.MapPath(directoryVirtualPath);

        foreach (var file in Directory.GetFiles(folderPath, searchPattern))
        {
            if (!String.IsNullOrEmpty(Array.Find(toExclude, s => s.ToLower() == file.ToLower())))
            {
                continue;
            }     

            bundle.IncludeFile(directoryVirtualPath + "/" + file);
        }

        return bundle;
}

And then usage should be:

bundles.Add(new StyleBundle("~/Content/themes/default/css")
   .IncludeDirectoryWithExclusion("~/Content/themes/Default", "*.css", "file-you-dont-want.css"));

I'm not at a PC at the moment so the above is un-tested but should give you a template for your solution.

Upvotes: 13

Related Questions