/// <summary>Gets a unique hash for the input spec.</summary>
 /// <param name="context">The context.</param>
 /// <param name="inputSpec">The input spec.</param>
 /// <returns>The unique hash>.</returns>
 private static string GetInputSpecHash(IWebGreaseContext context, InputSpec inputSpec)
 {
     return
         (inputSpec.GetFiles(context.Configuration.SourceDirectory)
          .ToDictionary(f => f.MakeRelativeToDirectory(context.Configuration.SourceDirectory), context.GetFileHash)
          .ToJson());
 }
Exemple #2
0
        /// <summary>Initializes a new instance of the <see cref="WebGreaseContext"/> class.</summary>
        /// <param name="parentContext">The parent context.</param>
        /// <param name="configFile">The config file.</param>
        public WebGreaseContext(IWebGreaseContext parentContext, FileInfo configFile)
        {
            var configuration = new WebGreaseConfiguration(parentContext.Configuration, configFile);

            configuration.Validate();

            if (configuration.Global.TreatWarningsAsErrors != null && parentContext.Log != null)
            {
                parentContext.Log.TreatWarningsAsErrors = configuration.Global.TreatWarningsAsErrors == true;
            }

            var parentWebGreaseContext = parentContext as WebGreaseContext;

            if (parentWebGreaseContext != null)
            {
                this.threadedMeasureResults = parentWebGreaseContext.threadedMeasureResults;
            }

            this.Initialize(
                configuration,
                parentContext.Log,
                parentContext.Cache,
                parentContext.Preprocessing,
                parentContext.SessionStartTime,
                parentContext.Measure);
        }
        /// <summary>Initializes a new instance of the <see cref="WebGreaseSectionKey"/> class.</summary>
        /// <param name="context">The context.</param>
        /// <param name="category">The id.</param>
        /// <param name="cacheVarByContentItem">The cache var by content item.</param>
        /// <param name="cacheVarBySetting">The cache var by setting.</param>
        /// <param name="cacheVarByFileSet">The cache var by file set.</param>
        /// <param name="uniqueKey">The unique Key.</param>
        public WebGreaseSectionKey(IWebGreaseContext context, string category, ContentItem cacheVarByContentItem, object cacheVarBySetting, IFileSet cacheVarByFileSet, string uniqueKey = null)
        {
            this.Category = category;
            this.Value    = uniqueKey;
            if (string.IsNullOrWhiteSpace(uniqueKey))
            {
                var varyByFiles    = new List <CacheVaryByFile>();
                var varyBySettings = new List <string>();

                if (cacheVarByContentItem != null)
                {
                    varyByFiles.Add(CacheVaryByFile.FromFile(context, cacheVarByContentItem));
                    varyBySettings.Add(cacheVarByContentItem.ResourcePivotKeys.ToJson());
                }

                if (cacheVarByFileSet != null)
                {
                    varyBySettings.Add(cacheVarByFileSet.ToJson());
                }

                if (context.Configuration.Overrides != null)
                {
                    varyBySettings.Add(context.Configuration.Overrides.UniqueKey);
                }

                varyBySettings.Add(cacheVarBySetting.ToJson(true));

                this.Value = CacheSectionFileVersionKey + Delimiter + category + Delimiter + string.Join(Delimiter, varyByFiles.Select(vbf => vbf.Hash).Concat(varyBySettings));
            }
        }
        /// <summary>Begins the section, create a new section and returns it.</summary>
        /// <param name="context">The context.</param>
        /// <param name="cacheCategory">The cache category.</param>
        /// <param name="uniqueKey">The unique Key.</param>
        /// <param name="parentCacheSection">The parent cache section.</param>
        /// <param name="autoLoad">The auto Load.</param>
        /// <returns>The <see cref="CacheSection"/>.</returns>
        public static CacheSection Begin(IWebGreaseContext context, string cacheCategory, string uniqueKey, ICacheSection parentCacheSection = null, bool autoLoad = true)
        {
            var cacheSection = new CacheSection
            {
                parent        = parentCacheSection as CacheSection,
                cacheCategory = cacheCategory,
                context       = context,
                UniqueKey     = uniqueKey
            };

            cacheSection.absolutePath = context.Cache.GetAbsoluteCacheFilePath(cacheSection.cacheCategory, context.GetValueHash(cacheSection.UniqueKey) + ".cache.json");

            if (cacheSection.parent != null)
            {
                cacheSection.parent.AddChildCacheSection(cacheSection);
            }

            EnsureCachePath(context, cacheCategory);

            if (autoLoad)
            {
                cacheSection.Load();
            }

            return(cacheSection);
        }
        /// <summary>Applies the css validation visitors.</summary>
        /// <param name="stylesheetNode">The stylesheet node.</param>
        /// <param name="threadContext">The thread Context.</param>
        /// <returns>The processed node.</returns>
        private AstNode ApplyValidation(AstNode stylesheetNode, IWebGreaseContext threadContext)
        {
            threadContext.SectionedAction(SectionIdParts.MinifyCssActivity, SectionIdParts.Validate).Execute(() =>
            {
                // Step # 1 - Remove the Css properties from Ast which need to be excluded (Bridging)
                if (this.ShouldExcludeProperties)
                {
                    stylesheetNode = stylesheetNode.Accept(new ExcludePropertyVisitor());
                }

                // Step # 2 - Validate for lower case
                if (this.ShouldValidateForLowerCase)
                {
                    stylesheetNode = stylesheetNode.Accept(new ValidateLowercaseVisitor());
                }

                // Step # 3 - Validate for Css hacks which don't work cross browser
                if (this.HackSelectors != null && this.HackSelectors.Any())
                {
                    stylesheetNode = stylesheetNode.Accept(new SelectorValidationOptimizationVisitor(this.HackSelectors, false, true));
                }

                // Step # 4 - Remove any banned selectors which are exposed for page efficiency
                if (this.BannedSelectors != null && this.BannedSelectors.Any())
                {
                    stylesheetNode = stylesheetNode.Accept(new SelectorValidationOptimizationVisitor(this.BannedSelectors, false, false));
                }
            });

            return(stylesheetNode);
        }
 /// <summary>Gets the md5 hash for the current content item.</summary>
 /// <param name="context">The context.</param>
 /// <returns>The md5 hash as a string.</returns>
 internal string GetContentHash(IWebGreaseContext context)
 {
     return(this.contentHash ??
            (this.contentHash = ContentItemType == ContentItemType.Value
             ? context.GetValueHash(this.Content)
             : context.GetFileHash(this.AbsoluteContentPath)));
 }
 /// <summary>Creates a <see cref="CacheVaryByFile"/> from a file.</summary>
 /// <param name="context">The context.</param>
 /// <param name="contentItem">The result file.</param>
 /// <returns>The <see cref="CacheVaryByFile"/>.</returns>
 public static CacheVaryByFile FromFile(IWebGreaseContext context, ContentItem contentItem)
 {
     return(new CacheVaryByFile
     {
         Path = contentItem.RelativeContentPath,
         Hash = contentItem.GetContentHash(context)
     });
 }
        /// <summary>The ensure cache path.</summary>
        /// <param name="context">The context.</param>
        /// <param name="cacheCategory">The cache category.</param>
        private static void EnsureCachePath(IWebGreaseContext context, string cacheCategory)
        {
            var cachePath = context.Cache.GetAbsoluteCacheFilePath(cacheCategory, string.Empty);

            if (!Directory.Exists(cachePath))
            {
                Directory.CreateDirectory(cachePath);
            }
        }
        /// <summary>Assembles the background images</summary>
        /// <param name="stylesheetNode">the style sheet node</param>
        /// <param name="dpi">The dpi.</param>
        /// <param name="threadContext">The thread Context.</param>
        /// <param name="spritedImageContentItems">The sprited Image Content Items.</param>
        /// <returns>The stylesheet node with the sprited images aplied.</returns>
        private AstNode SpriteBackgroundImages(AstNode stylesheetNode, float dpi, IWebGreaseContext threadContext, BlockingCollection <ContentItem> spritedImageContentItems)
        {
            // The image assembly is a 3 step process:
            // 1. Scan the Css followed by Pretty Print
            // 2. Run the image assembly tool
            // 3. Update the Css with generated images followed by Pretty Print
            return(threadContext.SectionedAction(SectionIdParts.MinifyCssActivity, SectionIdParts.Spriting).Execute(() =>
            {
                // Execute the pipeline for image assembly scan
                var scanLog = this.ExecuteImageAssemblyScan(stylesheetNode, threadContext);

                // Execute the pipeline for image assembly tool
                var imageMaps = new List <ImageLog>();
                var count = 0;
                foreach (var scanOutput in scanLog.ImageAssemblyScanOutputs)
                {
                    var spriteResult = this.SpriteImageFromLog(scanOutput, this.ImageAssembleScanDestinationFile + (count == 0 ? string.Empty : "." + count) + ".xml", scanLog.ImageAssemblyAnalysisLog, threadContext, spritedImageContentItems);
                    if (spriteResult != null)
                    {
                        imageMaps.Add(spriteResult);
                        count++;
                    }
                }

                // Step # 8 - Execute the pipeline for image assembly update
                stylesheetNode = this.ExecuteImageAssemblyUpdate(stylesheetNode, imageMaps, dpi);

                if (!string.IsNullOrWhiteSpace(this.ImageSpritingLogPath))
                {
                    scanLog.ImageAssemblyAnalysisLog.Save(this.ImageSpritingLogPath);
                }

                var imageAssemblyAnalysisLog = scanLog.ImageAssemblyAnalysisLog;
                if (this.ErrorOnInvalidSprite && imageAssemblyAnalysisLog.FailedSprites.Any())
                {
                    foreach (var failedSprite in imageAssemblyAnalysisLog.FailedSprites)
                    {
                        var failureMessage = ImageAssemblyAnalysisLog.GetFailureMessage(failedSprite);
                        if (!string.IsNullOrWhiteSpace(failedSprite.Image))
                        {
                            threadContext.Log.Error(
                                "Failed to sprite image {0}\r\nReason:{1}\r\nCss:{2}".InvariantFormat(
                                    failedSprite.Image, failureMessage, failedSprite.AstNode.PrettyPrint()));
                        }
                        else
                        {
                            threadContext.Log.Error(
                                "Failed to sprite:{0}\r\nReason:{1}".InvariantFormat(
                                    failedSprite.Image, failureMessage));
                        }
                    }
                }

                return stylesheetNode;
            }));
        }
        /// <summary>This method will be called to check if the processor believes it can handle the file based on the filename.</summary>
        /// <param name="context">The context.</param>
        /// <param name="contentItem">The full path to the file.</param>
        /// <param name="preprocessConfig">The configuration</param>
        /// <returns>If it thinks it can process it.</returns>
        public bool CanProcess(IWebGreaseContext context, ContentItem contentItem, PreprocessingConfig preprocessConfig = null)
        {
            var sassConfig = GetConfig(preprocessConfig);
            var extension  = Path.GetExtension(contentItem.RelativeContentPath);

            return
                (extension != null &&
                 (extension.EndsWith(sassConfig.SassExtension, StringComparison.OrdinalIgnoreCase) ||
                  extension.EndsWith(sassConfig.ScssExtension, StringComparison.OrdinalIgnoreCase)));
        }
Exemple #11
0
 /// <summary>Resource Manager factory.</summary>
 /// <param name="context">The webgrease context</param>
 /// <param name="inputContentDirectory">The base Resources Directory.</param>
 /// <param name="resourceGroupKey">The resource type.</param>
 /// <param name="applicationDirectoryName">The modules Aggregation Directory Name.</param>
 /// <param name="siteName">The site name</param>
 /// <param name="resourceKeys">The resource keys for which the resources will be compressed.</param>
 /// <param name="outputDirectoryPath">Output folder to write the resource files on hard drive.</param>
 /// <returns>A new instance of Resource Manager class.</returns>
 internal static ResourcesResolver Factory(
     IWebGreaseContext context,
     string inputContentDirectory,
     string resourceGroupKey,
     string applicationDirectoryName,
     string siteName,
     IEnumerable <string> resourceKeys,
     string outputDirectoryPath)
 {
     return(new ResourcesResolver(context, inputContentDirectory, resourceGroupKey, applicationDirectoryName, siteName, resourceKeys, outputDirectoryPath));
 }
        private static bool HasCachedEndResultThatChanged(IWebGreaseContext context, CacheResult r)
        {
            if (r == null)
            {
                return(true);
            }

            var absoluteEndResultPath = Path.Combine(context.Configuration.DestinationDirectory, r.RelativeHashedContentPath ?? r.RelativeContentPath);

            return(!File.Exists(absoluteEndResultPath) || !r.ContentHash.Equals(context.GetFileHash(absoluteEndResultPath)));
        }
Exemple #13
0
        /// <summary>Processes css files for images to merge (sprite)</summary>
        /// <param name="context">The context.</param>
        private static void ExecuteImageSpriting(IWebGreaseContext context)
        {
            // whiles this uses the minification activity, it is only assembling images
            var spriter = new MinifyCssActivity(context)
            {
                ShouldMinify   = false,
                ShouldOptimize = false,
                ShouldAssembleBackgroundImages = true
            };


            foreach (var fileSet in context.Configuration.CssFileSets.Where(file => file.InputSpecs.Any()))
            {
                // for each file set, get the configuration and setup the assembler object.
                var spriteConfig = fileSet.ImageSpriting.GetNamedConfig(context.Configuration.ConfigType);

                if (spriteConfig.ShouldAutoSprite)
                {
                    var outputPath    = GetOutputFolder(fileSet.Output, context.Configuration.DestinationDirectory);
                    var directoryName = string.IsNullOrWhiteSpace(Path.GetExtension(outputPath)) ? outputPath : Path.GetDirectoryName(outputPath);

                    spriter.ShouldAssembleBackgroundImages = spriteConfig.ShouldAutoSprite;
                    spriter.ImageAssemblyPadding           = spriteConfig.ImagePadding;
                    spriter.ImageAssembleReferencesToIgnore.Clear();
                    foreach (var image in spriteConfig.ImagesToIgnore)
                    {
                        spriter.ImageAssembleReferencesToIgnore.Add(image);
                    }

                    // run the spriter on every file in each of the input specs
                    foreach (var source in fileSet.InputSpecs.SelectMany(inputSpec => GetFiles(inputSpec.Path, inputSpec.SearchPattern, inputSpec.SearchOption)))
                    {
                        spriter.SourceFile = source;

                        spriter.DestinationFile       = Path.Combine(directoryName, Path.GetFileName(source));
                        spriter.ImagesOutputDirectory = Path.IsPathRooted(spriteConfig.DestinationImageFolder)
                                                            ? spriteConfig.DestinationImageFolder
                                                            : Path.Combine(directoryName, spriteConfig.DestinationImageFolder);

                        var file         = Path.GetFileNameWithoutExtension(spriter.DestinationFile);
                        var scanFilePath = Path.Combine(directoryName, Path.GetFileNameWithoutExtension(file) + ".scan." + Strings.Css);
                        spriter.ImageAssembleScanDestinationFile = scanFilePath;
                        try
                        {
                            spriter.Execute();
                        }
                        catch (WorkflowException ex)
                        {
                            HandleError(ex.InnerException ?? ex, source);
                        }
                    }
                }
            }
        }
Exemple #14
0
 /// <summary>The handle other content type cache sections.</summary>
 /// <param name="context">The context.</param>
 /// <param name="parentCacheSection">The session cache section.</param>
 /// <param name="sessionCacheData">The session cache data.</param>
 /// <param name="contentTypeSectionId">The content type section id.</param>
 private void HandleOtherContentTypeCacheSections(IWebGreaseContext context, ICacheSection parentCacheSection, SessionCacheData sessionCacheData, string[] contentTypeSectionId)
 {
     if (sessionCacheData != null)
     {
         foreach (var configType in sessionCacheData.ConfigTypes.Keys.Where(ct => !ct.Equals(this.ConfigType, StringComparison.OrdinalIgnoreCase)))
         {
             // TODO: Do a better job at touching all the files used by the last build from another config type.
             var otherContentTypeCacheSection = CacheSection.Begin(context, WebGreaseContext.ToStringId(contentTypeSectionId), sessionCacheData.GetConfigTypeUniqueKey(configType), parentCacheSection);
             otherContentTypeCacheSection.Save();
         }
     }
 }
Exemple #15
0
 /// <summary>The from result file.</summary>
 /// <param name="context">The context.</param>
 /// <param name="cacheCategory">The cache category.</param>
 /// <param name="endResult">The end result.</param>
 /// <param name="fileCategory">The file category.</param>
 /// <param name="contentItem">The result file.</param>
 /// <returns>The <see cref="CacheResult"/>.</returns>
 public static CacheResult FromContentFile(IWebGreaseContext context, string cacheCategory, bool endResult, string fileCategory, ContentItem contentItem)
 {
     return(new CacheResult
     {
         EndResult = endResult,
         FileCategory = fileCategory,
         CachedFilePath = context.Cache.StoreInCache(cacheCategory, contentItem),
         ContentHash = contentItem.GetContentHash(context),
         RelativeContentPath = contentItem.RelativeContentPath,
         RelativeHashedContentPath = contentItem.RelativeHashedContentPath,
     });
 }
Exemple #16
0
        /// <summary>Execute a single config file.</summary>
        /// <param name="sessionContext">The session context.</param>
        /// <param name="configFile">The config file.</param>
        /// <param name="activity">The activity</param>
        /// <param name="fileType">The file types</param>
        /// <param name="measure">If it should measure.</param>
        /// <param name="fullPathToConfigFiles">The full Path To Config Files.</param>
        /// <returns>The success.</returns>
        private static Tuple <bool, int> ExecuteConfigFile(IWebGreaseContext sessionContext, string configFile, ActivityName activity, FileTypes fileType, bool measure, string fullPathToConfigFiles)
        {
            var configFileStart = DateTimeOffset.Now;

            var configFileInfo = new FileInfo(configFile);

            // Creates the context specific to the configuration file
            var fileContext = new WebGreaseContext(sessionContext, configFileInfo);

            var configFileSuccess = true;
            var fileSets          = GetFileSets(fileContext.Configuration, fileType).ToArray();

            if (fileSets.Length > 0 || (fileType.HasFlag(FileTypes.Image) && fileContext.Configuration.ImageDirectoriesToHash.Any()))
            {
                var configFileContentItem = ContentItem.FromFile(configFileInfo.FullName);
                configFileSuccess = sessionContext
                                    .SectionedActionGroup(fileType.ToString(), SectionIdParts.WebGreaseBuildTask, SectionIdParts.ConfigurationFile)
                                    .MakeCachable(configFileContentItem, new { activity, fileContext.Configuration }, activity == ActivityName.Bundle) // Cached action can only be skipped when it is the bundle activity, otherwise don't.
                                    .Execute(configFileCacheSection =>
                {
                    fileContext.Configuration.AllLoadedConfigurationFiles.ForEach(configFileCacheSection.AddSourceDependency);

                    var success = true;
                    fileContext.Log.Information("Activity Start: [{0}] for [{1}] on configuration file \"{2}\"".InvariantFormat(activity, fileType, configFile), MessageImportance.High);
                    switch (activity)
                    {
                    case ActivityName.Bundle:
                        // execute the bundle pipeline
                        var bundleActivity = new BundleActivity(fileContext);
                        success           &= bundleActivity.Execute(fileSets);
                        break;

                    case ActivityName.Everything:
                        // execute the full pipeline
                        var everythingActivity = new EverythingActivity(fileContext);
                        success &= everythingActivity.Execute(fileSets, fileType);
                        break;
                    }

                    if (success && measure)
                    {
                        var configReportFile = Path.Combine(sessionContext.Configuration.ReportPath, (configFileInfo.Directory != null ? configFileInfo.Directory.Name + "." : string.Empty) + activity.ToString() + "." + fileType + "." + configFileInfo.Name);
                        fileContext.Measure.WriteResults(configReportFile, configFileInfo.FullName, configFileStart);
                    }

                    fileContext.Log.Information("Activity End: [{0}] for [{1}] on configuration file \"{2}\"".InvariantFormat(activity, fileType, configFile), MessageImportance.High);
                    return(success);
                });
            }

            return(Tuple.Create(configFileSuccess, fileSets.Length));
        }
Exemple #17
0
 /// <summary>Initializes a new instance of the <see cref="CssMinifier"/> class with default settings.</summary>
 /// <param name="context">The context.</param>
 public CssMinifier(IWebGreaseContext context)
 {
     this.CssActivity = new MinifyCssActivity(context)
     {
         ShouldMinify                   = true,
         ShouldOptimize                 = true,
         ShouldValidateForLowerCase     = false,
         ShouldExcludeProperties        = false,
         ShouldAssembleBackgroundImages = false
     };
     this.ShouldMinify = true;
     this.Errors       = new List <string>();
 }
        private ReadOnlyCacheSection(string jsonString, IWebGreaseContext context)
        {
            this.context = context;

            var json = JObject.Parse(jsonString);

            this.sourceDependencies = json["sourceDependencies"].ToString().FromJson <IEnumerable <CacheSourceDependency> >(true);
            this.cacheResults       = json["cacheResults"].ToString().FromJson <IEnumerable <CacheResult> >(true);

            this.childCacheSectionFiles = json["children"].AsEnumerable().Select(f => (string)f);

            this.absolutePath = (string)json["absolutePath"];
        }
        /// <summary>The create sprited images.</summary>
        /// <param name="mapXmlFile">The map xml file.</param>
        /// <param name="imageAssemblyAnalysisLog">The image assembly analysis log.</param>
        /// <param name="imageReferencesToAssemble">The image references to assemble.</param>
        /// <param name="cacheSection">The cache section.</param>
        /// <param name="results">The results.</param>
        /// <param name="threadContext">The thread Context.</param>
        /// <returns>The <see cref="bool"/>.</returns>
        private ImageLog CreateSpritedImages(
            string mapXmlFile,
            ImageAssemblyAnalysisLog imageAssemblyAnalysisLog,
            IEnumerable <InputImage> imageReferencesToAssemble,
            ICacheSection cacheSection,
            BlockingCollection <ContentItem> results,
            IWebGreaseContext threadContext)
        {
            if (!Directory.Exists(this.ImagesOutputDirectory))
            {
                Directory.CreateDirectory(this.ImagesOutputDirectory);
            }

            var imageMap = ImageAssembleGenerator.AssembleImages(
                imageReferencesToAssemble.ToSafeReadOnlyCollection(),
                SpritePackingType.Vertical,
                this.ImagesOutputDirectory,
                string.Empty,
                true,
                threadContext,
                this.ImageAssemblyPadding,
                imageAssemblyAnalysisLog,
                this.ForcedSpritingImageType);

            if (imageMap == null || imageMap.Document == null)
            {
                return(null);
            }

            var destinationDirectory = threadContext.Configuration.DestinationDirectory;

            if (!string.IsNullOrWhiteSpace(this.ImageAssembleScanDestinationFile))
            {
                var scanXml = imageMap.Document.ToString();
                FileHelper.WriteFile(mapXmlFile, scanXml);
                cacheSection.AddResult(ContentItem.FromFile(mapXmlFile), CacheFileCategories.SpriteLogFileXml);
            }

            var imageLog = new ImageLog(imageMap.Document);

            cacheSection.AddResult(ContentItem.FromContent(imageLog.ToJson(true)), CacheFileCategories.SpriteLogFile);

            foreach (var spritedFile in imageLog.InputImages.Select(il => il.OutputFilePath).Distinct())
            {
                var spritedImageContentItem = ContentItem.FromFile(spritedFile, spritedFile.MakeRelativeToDirectory(destinationDirectory));
                results.Add(spritedImageContentItem);
                cacheSection.AddResult(spritedImageContentItem, CacheFileCategories.HashedSpriteImage);
            }

            return(imageLog);
        }
        /// <summary>The dispose method, cleans up references and objects.</summary>
        private void Dispose()
        {
            if (this.cachedSection != null)
            {
                this.cachedSection.Dispose();
            }

            this.context = null;
            this.parent  = null;
            this.sourceDependencies.Clear();
            this.ChildCacheSections.Clear();
            this.childCacheSections = null;
            this.cacheResults.Clear();
        }
 /// <summary>Initializes a new instance of the <see cref="MinifyCssActivity"/> class.</summary>
 /// <param name="context">The context.</param>
 internal MinifyCssActivity(IWebGreaseContext context)
 {
     this.context                              = context;
     this.HackSelectors                        = new HashSet <string>();
     this.BannedSelectors                      = new HashSet <string>();
     this.ShouldExcludeProperties              = true;
     this.ShouldValidateForLowerCase           = false;
     this.ShouldOptimize                       = true;
     this.ShouldAssembleBackgroundImages       = true;
     this.ImageAssembleReferencesToIgnore      = new HashSet <string>();
     this.OutputUnitFactor                     = 1;
     this.ShouldPreventOrderBasedConflict      = false;
     this.ShouldMergeBasedOnCommonDeclarations = false;
 }
Exemple #22
0
        /// <summary>
        /// Executes the minification task
        /// </summary>
        /// <param name="context">context with settings to be used. Only used for the input/output settings.</param>
        private static void ExecuteMinification(IWebGreaseContext context)
        {
            var jsCruncher  = new MinifyJSActivity(context);
            var cssCruncher = new MinifyCssActivity(context);

            // only run the crunchers if the configuration has files for that particular file type
            foreach (var fileSet in context.Configuration.JSFileSets.Where(set => set.InputSpecs.Any()))
            {
                ProcessJsFileSet(jsCruncher, fileSet, context.Configuration.ConfigType, context.Configuration.DestinationDirectory);
            }

            // do the same thing for CSS files... nested loops are fun!
            foreach (var fileSet in context.Configuration.CssFileSets.Where(set => set.InputSpecs.Any()))
            {
                ProcessCssFileSet(cssCruncher, fileSet, context.Configuration.ConfigType, context.Configuration.DestinationDirectory);
            }
        }
Exemple #23
0
        /// <summary>Determines if the processor can parse the filetype, always true for this engine.</summary>
        /// <param name="context">The context.</param>
        /// <param name="contentItem">The full filename</param>
        /// <param name="preprocessConfig">The pre processing config</param>
        /// <returns>True if it can process it, otherwise false.</returns>
        public bool CanProcess(IWebGreaseContext context, ContentItem contentItem, PreprocessingConfig preprocessConfig = null)
        {
            if (preprocessConfig != null && preprocessConfig.Element != null)
            {
                var extensions = (string)preprocessConfig.Element.Attribute("wgincludeextensions")
                                 ?? (string)preprocessConfig.Element.Element("wgincludeextensions");

                if (!string.IsNullOrWhiteSpace(extensions))
                {
                    return(extensions
                           .Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)
                           .Any(wgIncludeExtension => contentItem.RelativeContentPath.EndsWith(wgIncludeExtension, StringComparison.OrdinalIgnoreCase)));
                }
            }

            return(true);
        }
        /// <summary>Applies the css optimization visitors.</summary>
        /// <param name="stylesheetNode">The stylesheet node.</param>
        /// <param name="threadContext">The thread Context.</param>
        /// <returns>The processed node.</returns>
        private AstNode ApplyOptimization(AstNode stylesheetNode, IWebGreaseContext threadContext)
        {
            // Step # 5 - Run the Css optimization visitors
            if (this.ShouldOptimize)
            {
                threadContext.SectionedAction(SectionIdParts.MinifyCssActivity, SectionIdParts.Optimize).Execute(
                    () =>
                {
                    stylesheetNode = stylesheetNode.Accept(new OptimizationVisitor {
                        ShouldMergeMediaQueries = this.ShouldMergeMediaQueries, ShouldPreventOrderBasedConflict = this.ShouldPreventOrderBasedConflict, ShouldMergeBasedOnCommonDeclarations = this.ShouldMergeBasedOnCommonDeclarations, NonMergeRuleSetSelectors = this.NonMergeSelectors
                    });
                    stylesheetNode = stylesheetNode.Accept(new ColorOptimizationVisitor());
                    stylesheetNode = stylesheetNode.Accept(new FloatOptimizationVisitor());
                });
            }

            return(stylesheetNode);
        }
        /// <summary>Parse the styleSheet.</summary>
        /// <param name="cssContent">The css content.</param>
        /// <param name="shouldLogDiagnostics">The should log diagnostics.</param>
        /// <returns>The styleSheet node.</returns>
        private static StyleSheetNode ParseStyleSheet(IWebGreaseContext context, string cssContent, bool shouldLogDiagnostics)
        {
            var lexer       = new CssLexer(new ANTLRStringStream(cssContent));
            var tokenStream = new CommonTokenStream(lexer);
            var parser      = new CssParser(tokenStream);

            var commonTree = context
                             .SectionedAction("CssParser", "Antlr")
                             .Execute(() =>
            {
                // Assign listener to parser.
                if (shouldLogDiagnostics)
                {
                    var listener = Trace.Listeners.OfType <TextWriterTraceListener>().FirstOrDefault();
                    if (listener != null)
                    {
                        parser.TraceDestination = listener.Writer;
                    }
                }

                var styleSheet = parser.main();
                return(styleSheet.Tree as CommonTree);
            });

            if (commonTree != null)
            {
                return(context.SectionedAction("CssParser", "CreateObjects").Execute(() =>
                {
                    if (shouldLogDiagnostics)
                    {
                        LogDiagnostics(cssContent, commonTree);
                    }

                    if (parser.NumberOfSyntaxErrors > 0)
                    {
                        throw new AggregateException("Syntax errors found.", parser._exceptions);
                    }

                    return CommonTreeTransformer.CreateStyleSheetNode(commonTree);
                }));
            }

            return(null);
        }
        /// <summary>The load.</summary>
        /// <param name="fullPath">The full path.</param>
        /// <param name="context">The context.</param>
        /// <returns>The <see cref="CacheSection"/>.</returns>
        internal static ReadOnlyCacheSection Load(string fullPath, IWebGreaseContext context)
        {
            if (!File.Exists(fullPath))
            {
                return(null);
            }

            return(Safe.Lock(LoadLock, () =>
            {
                ReadOnlyCacheSection cacheSection;
                if (!context.Cache.LoadedCacheSections.TryGetValue(fullPath, out cacheSection))
                {
                    cacheSection = new ReadOnlyCacheSection(File.ReadAllText(fullPath), context);
                    context.Cache.LoadedCacheSections.Add(fullPath, cacheSection);
                }

                cacheSection.referenceCount++;
                return cacheSection;
            }));
        }
        /// <summary>The unload.</summary>
        /// <param name="context">the context</param>
        /// <param name="fullPath">The full path.</param>
        /// <returns>The <see cref="bool"/>.</returns>
        private static bool Unload(IWebGreaseContext context, string fullPath)
        {
            return(Safe.Lock(LoadLock, () =>
            {
                ReadOnlyCacheSection cacheSection;
                if (context.Cache.LoadedCacheSections.TryGetValue(fullPath, out cacheSection))
                {
                    cacheSection.referenceCount--;
                    if (cacheSection.referenceCount == 0)
                    {
                        context.Cache.LoadedCacheSections.Remove(fullPath);
                    }
                    else
                    {
                        return false;
                    }
                }

                return true;
            }));
        }
        /// <summary>Registers available Image Assemblers.</summary>
        /// <param name="context">The global web grease context.</param>
        /// <returns>Dictionary of registered image assembler for file extension</returns>
        private static IEnumerable <ImageAssembleBase> RegisterAvailableAssemblers(IWebGreaseContext context)
        {
            var registeredAssemblers = new List <ImageAssembleBase>();

            var notSupportedAssemble = new NotSupportedAssemble(context);

            registeredAssemblers.Add(notSupportedAssemble);

            var photoAssemble = new PhotoAssemble(context);

            registeredAssemblers.Add(photoAssemble);

            var nonphotoNonindexedAssemble = new NonphotoNonindexedAssemble(context);

            registeredAssemblers.Add(nonphotoNonindexedAssemble);

            var nonphotoIndexedAssemble = new NonphotoIndexedAssemble(context);

            registeredAssemblers.Add(nonphotoIndexedAssemble);

            return(registeredAssemblers);
        }
        internal void Dispose()
        {
            if (this.disposed)
            {
                throw new BuildWorkflowException("Cannot dispose an object twice.");
            }

            if (Unload(this.context, this.absolutePath))
            {
                this.disposed = true;
                if (this.childCacheSections != null)
                {
                    this.childCacheSections.Where(ccs => ccs != null).ForEach(ccs => ccs.Dispose());
                }

                this.context                = null;
                this.cacheResults           = null;
                this.sourceDependencies     = null;
                this.childCacheSections     = null;
                this.childCacheSectionFiles = null;
            }
        }
Exemple #30
0
        /// <summary>Processed the contents of the file and returns the processed content.
        /// returns null if anything went wrong, and reports any errors through the lot delegates.</summary>
        /// <param name="context">The context.</param>
        /// <param name="contentItem">The content of the file.</param>
        /// <param name="preprocessingConfig">The pre processing configuration</param>
        /// <param name="minimalOutput">Is the goal to have the most minimal output (true skips lots of comments)</param>
        /// <returns>The processed contents or null of an error occurred.</returns>
        public ContentItem Process(IWebGreaseContext context, ContentItem contentItem, PreprocessingConfig preprocessingConfig, bool minimalOutput)
        {
            var settingsMinimalOutput = preprocessingConfig != null && preprocessingConfig.Element != null && (bool?)preprocessingConfig.Element.Attribute("minimalOutput") == true;

            context.SectionedAction(SectionIdParts.Preprocessing, SectionIdParts.Process, "WgInclude")
            .MakeCachable(contentItem, new { minimalOutput })
            .Execute(wgincludeCacheImportsSection =>
            {
                var workingFolder = context.GetWorkingSourceDirectory(contentItem.RelativeContentPath);
                var content       = contentItem.Content;
                if (string.IsNullOrWhiteSpace(content))
                {
                    return(true);
                }

                content     = IncludeRegex.Replace(content, match => ReplaceInputs(match, workingFolder, wgincludeCacheImportsSection, minimalOutput || settingsMinimalOutput));
                contentItem = ContentItem.FromContent(content, contentItem);
                return(true);
            });

            return(contentItem);
        }