/// <summary>
        /// Adds all files in a single directory to a fileListsByAssetType
        /// </summary>
        /// <param name="fileListsByAssetType"></param>
        /// <param name="dirPath"></param>
        private void AddRequiredFilesSingleDirectory(FileListsByAssetType fileListsByAssetType, AssetPath dirPath)
        {
            string absolutePath = dirPath.AbsolutePath;
            IEnumerable<string> filePaths = Directory.EnumerateFiles(absolutePath);

            // Need to first process the nuspec files, and then the asset files.
            // This because the asset files may depend on the files pointed at by the nuspec files.
            for (int i = 0; i < 2; i++)
            {
                foreach (string filePath in filePaths)
                {
                    if (i == 0)
                    {
                        if (NuspecFile.IsNuspecFile(filePath))
                        {
                            fileListsByAssetType.Append(GetDependencies(filePath, dirPath));
                        }
                    }
                    else
                    {
                        AssetType? assetType = AssetTypeOfFile(filePath);
                        if (assetType != null)
                        {
                            fileListsByAssetType.Add(dirPath.AbsolutePathToAssetPath(filePath), assetType.Value);
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Adds a directory with assets (script files, etc.) to the stored list of asset directories.
        /// </summary>
        /// <param name="dirPath"></param>
        public static void AddAssetDirectory(AssetPath dirPath)
        {
            List<AssetPath> assetDirectoryList = (List<AssetPath>)HttpContext.Current.Items[AssetDirectoryItemKey];
            if (assetDirectoryList == null)
            {
                assetDirectoryList = new List<AssetPath>();
                HttpContext.Current.Items[AssetDirectoryItemKey] = assetDirectoryList;
            }

            assetDirectoryList.Add(dirPath);
        }
示例#3
0
        /// <summary>
        /// Same as GetRequiredFilesForDirectory, but uncached.
        /// </summary>
        /// <param name="dirPath">
        /// Path to the directory.
        /// </param>
        /// <returns></returns>
        private FileListsByAssetType GetRequiredFilesForDirectoryUnchached(AssetPath dirPath)
        {
            FileListsByAssetType fileListsByAssetType = new FileListsByAssetType();

            // Note: parentDirs will contain dirPath itself.
            //
            // dirPath.ParentDirs will give you something like
            // ~/Views/Shared/EditorTemplates/HomeAddress
            // ~/Views/Shared/EditorTemplates
            // ~/Views/Shared
            // However, the longer directory tends to have the more specific files. If there is a dependency between files in these
            // directories, it would be from more specific to less specific, not the other way around. So process the directories in
            // reverse order, so CSS and JS files in more common directories are loaded first.

            IEnumerable <AssetPath> parentDirs = dirPath.ParentDirs("Views").Reverse();

            foreach (AssetPath parentDir in parentDirs)
            {
                AddRequiredFilesSingleDirectory(fileListsByAssetType, parentDir);
            }

            return(fileListsByAssetType);
        }
示例#4
0
        /// <summary>
        /// Takes a file path and returns a string formatted like this:
        /// 
        /// * files with no Area, with controller Shared, and that live in a directory with a name starting with _Layout:
        ///   @___@
        ///   
        /// * files with no Area, with controller Shared, but don't live in a directory with a name starting with _Layout:
        ///   @___@@
        ///   
        /// * files with an Area, with controller Shared, and that live in a directory with a name starting with _Layout:
        ///   [Area]___@
        ///   
        /// * files with an Area, with controller Shared, but don't live in a directory with a name starting with _Layout:
        ///   [Area]___@@
        ///   
        /// * all other files, with no area
        ///   @___[Controller]
        ///   
        /// * all other files, with an area
        ///   [Area]___[Controller]
        /// 
        /// Note that alphabetically, @ sorts before any letter or digit.
        /// Also, @___@@ sorts after @___@.
        /// 
        /// The method assumes that the file path is root relative, and follows MVC conventions:
        /// 
        /// * path with an Area:
        ///   ~/Areas/TestArea/Views/home/index/indexspecific.css
        /// 
        /// * path without an Area:
        ///   ~/Views/home/index/indexspecific.css
        /// 
        /// If the file path doesn't adhere to this, the method returns 
        /// @
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public static string FilePathSortKey(AssetPath assetPath)
        {
            string filePath = assetPath.RootRelativePath;

            if (!filePath.StartsWith("~/"))
            {
                throw new Exception(string.Format("FilePathSortKey - filePath {0} does not start with ~/", filePath));
            }

            string[] filePathComponents = filePath.Split(new char[] { '/' });

            // Note that the first element in filePathComponents will be the ~
            // The last element is the file name itself.

            string area = "@";
            int nbrComponents = filePathComponents.Length;
            int controllerIdx = 2;

            if (string.CompareOrdinal(filePathComponents[1], "Areas") == 0)
            {
                if ((nbrComponents < 6) || (string.CompareOrdinal(filePathComponents[3], "Views") != 0))
                {
                    return "@";
                }

                area = filePathComponents[2];
                controllerIdx = 4;
            }
            else if (string.CompareOrdinal(filePathComponents[1], "Views") == 0)
            {
                if (nbrComponents < 4)
                {
                    return "@";
                }
            }
            else
            {
                return "@";
            }

            string controller = filePathComponents[controllerIdx];
            if (string.CompareOrdinal(controller, "Shared") == 0)
            {
                controller = "@";
            }

            string postfix = "@";
            int postControllerDirectoryIdx = (controllerIdx + 1);
            if (nbrComponents > postControllerDirectoryIdx)
            {
                string postControllerDirectory = filePathComponents[postControllerDirectoryIdx].ToLower();
                if (postControllerDirectory.StartsWith("_layout"))
                {
                    postfix = "";
                }
            }

            string sortKey = area + "___" + controller + postfix;

            return sortKey;
        }
示例#5
0
        /// <summary>
        /// Adds all files in a single directory to a fileListsByAssetType
        /// </summary>
        /// <param name="fileListsByAssetType"></param>
        /// <param name="dirPath"></param>
        private void AddRequiredFilesSingleDirectory(FileListsByAssetType fileListsByAssetType, AssetPath dirPath)
        {
            string absolutePath = dirPath.AbsolutePath;

            string[] filePaths = Directory.EnumerateFiles(absolutePath).ToArray();

            // Need to first process the nuspec files, and then the asset files.
            // This because the asset files may depend on the files pointed at by the nuspec files.
            for (int i = 0; i < 2; i++)
            {
                foreach (string filePath in filePaths)
                {
                    if (i == 0)
                    {
                        if (NuspecFile.IsNuspecFile(filePath))
                        {
                            fileListsByAssetType.Append(GetDependencies(filePath, dirPath));
                        }
                    }
                    else
                    {
                        AssetType?assetType = AssetTypeOfFile(filePath);
                        if (assetType != null)
                        {
                            fileListsByAssetType.Add(dirPath.AbsolutePathToAssetPath(filePath), assetType.Value);
                        }
                    }
                }
            }
        }
 /// <summary>
 /// Takes the path to a directory and returns the files in that directory, the files in the parent directories (down to the Views or ~ dir), 
 /// and all the files
 /// that that directory depends on (via .nuspec files).
 /// 
 /// It does not go into sub directories.
 /// 
 /// Uses caching to reduce trips to the file system.
 /// </summary>
 /// <param name="dirPath">
 /// Path to the directory. 
 /// </param>
 /// <returns>
 /// The required files, split by asset type.
 /// </returns>
 public FileListsByAssetType GetRequiredFilesForDirectory(AssetPath dirPath)
 {
     string absolutePath = dirPath.AbsolutePath;
     var fileListsByAssetType = _cacheHelper.Get(absolutePath, () => GetRequiredFilesForDirectoryUnchached(dirPath), new[] { absolutePath });
     return fileListsByAssetType;
 }
        /// <summary>
        /// Same as GetRequiredFilesForDirectory, but uncached.
        /// </summary>
        /// <param name="dirPath">
        /// Path to the directory. 
        /// </param>
        /// <returns></returns>
        private FileListsByAssetType GetRequiredFilesForDirectoryUnchached(AssetPath dirPath)
        {
            FileListsByAssetType fileListsByAssetType = new FileListsByAssetType();

            // Note: parentDirs will contain dirPath itself.
            //
            // dirPath.ParentDirs will give you something like
            /// ~/Views/Shared/EditorTemplates/HomeAddress
            /// ~/Views/Shared/EditorTemplates
            /// ~/Views/Shared
            // However, the longer directory tends to have the more specific files. If there is a dependency between files in these
            // directories, it would be from more specific to less specific, not the other way around. So process the directories in
            // reverse order, so CSS and JS files in more common directories are loaded first.

            IEnumerable<AssetPath> parentDirs = dirPath.ParentDirs("Views").Reverse();
            foreach (AssetPath parentDir in parentDirs)
            {
                AddRequiredFilesSingleDirectory(fileListsByAssetType, parentDir);
            }

            return fileListsByAssetType;
        }
        /// <summary>
        /// Reads the dependencies in a Nuspec file. These are directories.
        /// Accumulates the assets in those directories to in a FileListsByAssetType.
        /// This is then returned.
        /// 
        /// This method calls the dependency resolver concurrently.
        /// </summary>
        /// <param name="absoluteNuspecPath">
        /// Path of the nuspec file
        /// </param>
        /// <param name="nuspecFileDirPath">
        /// The directory where the nuspec file is located.
        /// </param>
        /// <returns></returns>
        private FileListsByAssetType GetDependencies(string absoluteNuspecPath, AssetPath nuspecFileDirPath)
        {
            FileListsByAssetType fileListsByAssetType = new FileListsByAssetType();

            var nuspecFile = new NuspecFile(absoluteNuspecPath);
            List<AssetPath> dependencyAssetPaths = nuspecFile.DependencyIds.Select(d => nuspecFileDirPath.Create(d)).ToList();

            // Call the dependency resolver concurrently for each dependency
            foreach (AssetPath dependencyAssetPath in dependencyAssetPaths)
            {
                fileListsByAssetType.Append(GetRequiredFilesForDirectory(dependencyAssetPath));
            }

            return fileListsByAssetType;
        }
示例#9
0
        /// <summary>
        /// Takes a file path and returns a string formatted like this:
        ///
        /// * files with no Area, with controller Shared, and that live in a directory with a name starting with _Layout:
        ///   @___@
        ///
        /// * files with no Area, with controller Shared, but don't live in a directory with a name starting with _Layout:
        ///   @___@@
        ///
        /// * files with an Area, with controller Shared, and that live in a directory with a name starting with _Layout:
        ///   [Area]___@
        ///
        /// * files with an Area, with controller Shared, but don't live in a directory with a name starting with _Layout:
        ///   [Area]___@@
        ///
        /// * all other files, with no area
        ///   @___[Controller]
        ///
        /// * all other files, with an area
        ///   [Area]___[Controller]
        ///
        /// Note that alphabetically, @ sorts before any letter or digit.
        /// Also, @___@@ sorts after @___@.
        ///
        /// The method assumes that the file path is root relative, and follows MVC conventions:
        ///
        /// * path with an Area:
        ///   ~/Areas/TestArea/Views/home/index/indexspecific.css
        ///
        /// * path without an Area:
        ///   ~/Views/home/index/indexspecific.css
        ///
        /// If the file path doesn't adhere to this, the method returns
        /// @
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public static string FilePathSortKey(AssetPath assetPath)
        {
            string filePath = assetPath.RootRelativePath;

            if (!filePath.StartsWith("~/"))
            {
                throw new Exception(string.Format("FilePathSortKey - filePath {0} does not start with ~/", filePath));
            }

            string[] filePathComponents = filePath.Split(new char[] { '/' });

            // Note that the first element in filePathComponents will be the ~
            // The last element is the file name itself.

            string area          = "@";
            int    nbrComponents = filePathComponents.Length;
            int    controllerIdx = 2;

            if (string.CompareOrdinal(filePathComponents[1], "Areas") == 0)
            {
                if ((nbrComponents < 6) || (string.CompareOrdinal(filePathComponents[3], "Views") != 0))
                {
                    return("@");
                }

                area          = filePathComponents[2];
                controllerIdx = 4;
            }
            else if (string.CompareOrdinal(filePathComponents[1], "Views") == 0)
            {
                if (nbrComponents < 4)
                {
                    return("@");
                }
            }
            else
            {
                return("@");
            }

            string controller = filePathComponents[controllerIdx];

            if (string.CompareOrdinal(controller, "Shared") == 0)
            {
                controller = "@";
            }

            string postfix = "@";
            int    postControllerDirectoryIdx = (controllerIdx + 1);

            if (nbrComponents > postControllerDirectoryIdx)
            {
                string postControllerDirectory = filePathComponents[postControllerDirectoryIdx].ToLower();
                if (postControllerDirectory.StartsWith("_layout"))
                {
                    postfix = "";
                }
            }

            string sortKey = area + "___" + controller + postfix;

            return(sortKey);
        }