51 votes

Répertoire MVC4 Less Bundle @import

Je suis en train d'utiliser MVC4 regroupement de regrouper certains de mes moins de fichiers, mais il semble que le chemin d'importation que j'utilise est à l'arrêt. Ma structure de répertoire est:

static/
    less/
        mixins.less
        admin/
            user.less

Dans de l'utilisateur.moins, je suis d'essayer d'importer des mixin.de moins en utilisant ce:

@import "../mixins.less";

Cette habitude de travailler pour moi avant lors de l'utilisation de crépitant avec sans point, mais maintenant, j'ai remarqué ELMAH devenais folle à moi, disant ceci:

System.IO.FileNotFoundException: 
    You are importing a file ending in .less that cannot be found.
File name: '../mixins.less'

Suis-je censé utiliser un autre @import avec MVC4?

Quelques informations supplémentaires

Voici la moins classe et mondial.asax.cs code que j'utilise pour tenter ceci:

LessMinify.cs

...
public class LessMinify : CssMinify
{
    public LessMinify() {}

    public override void Process(BundleContext context, BundleResponse response)
    {
        response.Content = Less.Parse(response.Content);
        base.Process(context, response);
    }
}
...

Global.asax.cs

...
DynamicFolderBundle lessFB = 
    new DynamicFolderBundle("less", new LessMinify(), "*.less");

BundleTable.Bundles.Add(lessFB);

Bundle AdminLess = new Bundle("~/AdminLessBundle", new LessMinify());
...
AdminLess.AddFile("~/static/less/admin/user.less");
BundleTable.Bundles.Add(AdminLess);
...

41voto

Ben Cull Points 3588

J'ai écrit un rapide billet de blog sur l'Aide de MOINS de CSS Avec MVC4 d'Optimisation Web.

Essentiellement, il se résume à l'aide de la BundleTransformer.Moins de Package Nuget et l'évolution de votre BundleConfig.cs.

Testé avec bootstrap.

EDIT: faut mentionner la raison pour laquelle je dis cela, j'ai aussi couru dans le @import structure de répertoire en question, et cette bibliothèque gère correctement.

26voto

Michael Baird Points 1082

Il est le code publié sur GitHub Gist qui fonctionne bien avec @import et sans point: https://gist.github.com/2002958

Je l'ai testé avec Twitter Bootstrap et il fonctionne bien. J'ai créé un projet de démonstration sur GitHub: Mvc4BootstrapLessDemo.

ImportedFilePathResolver.cs

public class ImportedFilePathResolver : IPathResolver
{
    private string currentFileDirectory;
    private string currentFilePath;

    /// <summary>
    /// Initializes a new instance of the <see cref="ImportedFilePathResolver"/> class.
    /// </summary>
    /// <param name="currentFilePath">The path to the currently processed file.</param>
    public ImportedFilePathResolver(string currentFilePath)
    {
        CurrentFilePath = currentFilePath;
    }

    /// <summary>
    /// Gets or sets the path to the currently processed file.
    /// </summary>
    public string CurrentFilePath
    {
        get { return currentFilePath; }
        set
        {
            currentFilePath = value;
            currentFileDirectory = Path.GetDirectoryName(value);
        }
    }

    /// <summary>
    /// Returns the absolute path for the specified improted file path.
    /// </summary>
    /// <param name="filePath">The imported file path.</param>
    public string GetFullPath(string filePath)
    {
        filePath = filePath.Replace('\\', '/').Trim();

        if(filePath.StartsWith("~"))
        {
            filePath = VirtualPathUtility.ToAbsolute(filePath);
        }

        if(filePath.StartsWith("/"))
        {
            filePath = HostingEnvironment.MapPath(filePath);
        }
        else if(!Path.IsPathRooted(filePath))
        {
            filePath = Path.Combine(currentFileDirectory, filePath);
        }

        return filePath;
    }
}

LessMinify.cs

public class LessMinify : IBundleTransform
{
    /// <summary>
    /// Processes the specified bundle of LESS files.
    /// </summary>
    /// <param name="bundle">The LESS bundle.</param>
    public void Process(BundleContext context, BundleResponse bundle)
    {
        if(bundle == null)
        {
            throw new ArgumentNullException("bundle");
        }

        context.HttpContext.Response.Cache.SetLastModifiedFromFileDependencies();

        var lessParser = new Parser();
        ILessEngine lessEngine = CreateLessEngine(lessParser);

        var content = new StringBuilder(bundle.Content.Length);

        foreach(FileInfo file in bundle.Files)
        {
            SetCurrentFilePath(lessParser, file.FullName);
            string source = File.ReadAllText(file.FullName);
            content.Append(lessEngine.TransformToCss(source, file.FullName));
            content.AppendLine();

            AddFileDependencies(lessParser);
        }

        bundle.Content = content.ToString();
        bundle.ContentType = "text/css";
        //base.Process(context, bundle);
    }

    /// <summary>
    /// Creates an instance of LESS engine.
    /// </summary>
    /// <param name="lessParser">The LESS parser.</param>
    private ILessEngine CreateLessEngine(Parser lessParser)
    {
        var logger = new AspNetTraceLogger(LogLevel.Debug, new Http());
        return new LessEngine(lessParser, logger, false);
    }

    /// <summary>
    /// Adds imported files to the collection of files on which the current response is dependent.
    /// </summary>
    /// <param name="lessParser">The LESS parser.</param>
    private void AddFileDependencies(Parser lessParser)
    {
        IPathResolver pathResolver = GetPathResolver(lessParser);

        foreach(string importedFilePath in lessParser.Importer.Imports)
        {
            string fullPath = pathResolver.GetFullPath(importedFilePath);
            HttpContext.Current.Response.AddFileDependency(fullPath);
        }

        lessParser.Importer.Imports.Clear();
    }

    /// <summary>
    /// Returns an <see cref="IPathResolver"/> instance used by the specified LESS lessParser.
    /// </summary>
    /// <param name="lessParser">The LESS prser.</param>
    private IPathResolver GetPathResolver(Parser lessParser)
    {
        var importer = lessParser.Importer as Importer;
        if(importer != null)
        {
            var fileReader = importer.FileReader as FileReader;
            if(fileReader != null)
            {
                return fileReader.PathResolver;
            }
        }

        return null;
    }

    /// <summary>
    /// Informs the LESS parser about the path to the currently processed file. 
    /// This is done by using custom <see cref="IPathResolver"/> implementation.
    /// </summary>
    /// <param name="lessParser">The LESS parser.</param>
    /// <param name="currentFilePath">The path to the currently processed file.</param>
    private void SetCurrentFilePath(Parser lessParser, string currentFilePath)
    {
        var importer = lessParser.Importer as Importer;
        if(importer != null)
        {
            var fileReader = importer.FileReader as FileReader;

            if(fileReader == null)
            {
                importer.FileReader = fileReader = new FileReader();
            }

            var pathResolver = fileReader.PathResolver as ImportedFilePathResolver;

            if(pathResolver != null)
            {
                pathResolver.CurrentFilePath = currentFilePath;
            }
            else
            {
               fileReader.PathResolver = new ImportedFilePathResolver(currentFilePath);
            }
        }
        else
        {
            throw new InvalidOperationException("Unexpected importer type on dotless parser");
        }


    }
}

21voto

awrigley Points 6468

Additif à Ben Réforme de la réponse:

Je sais que cela "devrait être un commentaire de Ben Réforme de la poste", mais il ajoute un petit plus qui serait impossible pour ajouter un commentaire. Donc votez-moi vers le bas si vous devez. Ou près de moi.

Ben du blog fait tout, sauf qu'il n'indiquez pas de minification.

Afin d'installer le BundleTransformer.Moins de paquet comme Ben suggère et puis, si vous voulez minification de votre css, procédez de la manière suivante (dans ~/App_Start/BundleConfig.cs):

var cssTransformer = new CssTransformer();
var jsTransformer = new JsTransformer();
var nullOrderer = new NullOrderer();

var css = new Bundle("~/bundles/css")
    .Include("~/Content/site.less");
css.Transforms.Add(cssTransformer);
css.Transforms.Add(new CssMinify());
css.Orderer = nullOrderer;

bundles.Add(css);

L'ajout d'une ligne est:

css.Transforms.Add(new CssMinify());

CssMinify est System.Web.Optimizations

Je suis tellement soulagée de contourner les @import problème et le fichier résultant .moins d'extension ne trouve pas que je n'aime pas qui vote moi vers le bas.

Si, au contraire, vous vous sentez l'envie de voter pour cette réponse, veuillez nous donner votre vote à Ben.

Donc il.

17voto

Chris Peterson Points 366

Un moyen de contourner le problème que j’ai trouvé très utile consiste à définir le répertoire avant d’exécuter Less.Parse dans LessMinify.Process (). Voici comment je l'ai fait:

 public class LessTransform : IBundleTransform
    {
        private string _path;

        public LessTransform(string path)
        {
            _path = path;
        }

        public void Process(BundleContext context, BundleResponse response)
        {
            Directory.SetCurrentDirectory(_path);

            response.Content = Less.Parse(response.Content);
            response.ContentType = "text/css";
        }
    }
 

Puis en passant dans le chemin lors de la création de l’objet le moins transformé comme ceci:

 lessBundle.Transforms.Add(
    new LessTransform(HttpRuntime.AppDomainAppPath + "/Content/Less")
);
 

J'espère que cela t'aides.

4voto

TheRealQuagmire Points 371

Le problème est que le DynamicFolderBundle lit tous les fichiers et passe le combiné contenu de la LessMinify.

Tout @importations n'ont pas de référence à l'emplacement du fichier provient.

Pour résoudre cela, j'ai eu à placer tous les "moins" des fichiers en un seul emplacement.

Ensuite, vous avez à comprendre l'ordre des fichiers de devenir important. En tant que tel, j'ai commencé à renommer le fichier avec un numéro (par exemple: "0 CONSTANTES.moins", "1 MIXIN.moins", ce qui signifie qu'ils sont chargés au-dessus de la sortie combinée avant d'aller dans le LessMinify.

si vous déboguez votre LessMinify et afficher la réponse.Contenu que vous verrez le combiné moins de sortie!

Espérons que cette aide

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X