public void DeserializeSettings(string serialization, CombinatorResource resource)
        {
            if (string.IsNullOrEmpty(serialization))
            {
                return;
            }

            var settings = _jsonConverter.Deserialize <SerializableSettings>(serialization);

            if (settings.Url != null)
            {
                resource.RequiredContext.Resource.SetUrlProtocolRelative(settings.Url);
                resource.IsOriginal = true;
            }

            resource.IsRemoteStorageResource = settings.IsRemoteStorageResource;

            if (resource.RequiredContext.Settings == null)
            {
                resource.RequiredContext.Settings = new RequireSettings();
            }
            var resourceSettings = resource.RequiredContext.Settings;

            resourceSettings.Culture    = settings.Culture;
            resourceSettings.Condition  = settings.Condition;
            resourceSettings.Attributes = settings.Attributes;

            resource.RequiredContext.Resource.TagBuilder.MergeAttributes(settings.TagAttributes, true);
        }
        private void EmbedImages(CombinatorResource resource, int maxSizeKB)
        {
            ProcessUrlSettings(resource,
                               (match) =>
            {
                var url       = match.Groups[1].Value;
                var extension = Path.GetExtension(url).ToLowerInvariant();

                // This is a dumb check but otherwise we'd have to inspect the file thoroughly
                if (!String.IsNullOrEmpty(extension) && ".jpg .jpeg .png .gif .tiff .bmp".Contains(extension))
                {
                    var imageData = _resourceFileService.GetImageBase64Data(MakeInlineUri(resource, url), maxSizeKB);

                    if (!String.IsNullOrEmpty(imageData))
                    {
                        var dataUrl =
                            "data:image/"
                            + Path.GetExtension(url).Replace(".", "")
                            + ";base64,"
                            + imageData;

                        return("url(\"" + dataUrl + "\")");
                    }
                }

                return(match.Groups[0].Value);
            });
        }
        private static void AdjustRelativePaths(CombinatorResource resource, Stylesheet stylesheet)
        {
            ProcessUrls(
                resource,
                stylesheet,
                (ruleSet, urlTerm) =>
            {
                var uri = InlineUriFactory(resource, urlTerm.Value);

                // Remote paths are preserved as full urls, local paths become uniformed relative ones.
                if (uri.Scheme != "data")
                {
                    string uriString = "";

                    if (resource.IsCdnResource || resource.AbsoluteUrl.Host != uri.Host)
                    {
                        uriString = uri.ToStringWithoutScheme();
                    }
                    else
                    {
                        uriString = uri.PathAndQuery;
                    }

                    urlTerm.Value = uriString;
                }
            });
        }
示例#4
0
        public void DeserializeSettings(string serialization, CombinatorResource resource)
        {
            if (String.IsNullOrEmpty(serialization))
            {
                return;
            }

            var settings = _serializer.XmlDeserialize <SerializableSettings>(serialization);

            if (settings.Url != null)
            {
                var resourceManifest = new ResourceManifest();
                resource.RequiredContext.Resource = resourceManifest.DefineResource(resource.Type.ToStringType(), settings.Url.ToString());
                resource.RequiredContext.Resource.SetUrlWithoutScheme(settings.Url);
                resource.IsOriginal = true;
            }

            if (resource.RequiredContext.Settings == null)
            {
                resource.RequiredContext.Settings = new RequireSettings();
            }
            var resourceSettings = resource.RequiredContext.Settings;

            resourceSettings.Culture    = settings.Culture;
            resourceSettings.Condition  = settings.Condition;
            resourceSettings.Attributes = settings.Attributes;
        }
示例#5
0
        public void Save(int hashCode, CombinatorResource resource)
        {
            var scliceCount = _fileRepository.Count(file => file.HashCode == hashCode);

            var fileRecord = new CombinedFileRecord()
            {
                HashCode       = hashCode,
                Slice          = ++scliceCount,
                Type           = resource.Type,
                LastUpdatedUtc = _clock.UtcNow,
                Settings       = _combinatorResourceManager.SerializeResourceSettings(resource)
            };

            if (!String.IsNullOrEmpty(resource.Content))
            {
                var path = MakePath(fileRecord);

                using (var stream = _storageProvider.CreateFile(path).OpenWrite())
                {
                    var bytes = Encoding.UTF8.GetBytes(resource.Content);
                    stream.Write(bytes, 0, bytes.Length);
                }
            }

            _fileRepository.Create(fileRecord);
        }
        private static void RegexAdjustRelativePaths(CombinatorResource resource)
        {
            RegexProcessUrls(resource,
                             (match) =>
            {
                var url = match.Groups[1].ToString();

                var uri = RegexMakeInlineUri(resource, url);

                // Remote paths are preserved as full urls, local paths become uniformed relative ones.
                string uriString = "";
                if (uri.Scheme != "data")
                {
                    if (resource.IsCdnResource || resource.AbsoluteUrl.Host != uri.Host)
                    {
                        uriString = uri.ToStringWithoutScheme();
                    }
                    else
                    {
                        uriString = uri.PathAndQuery;
                    }
                }
                else
                {
                    uriString = url;
                }

                return("url(\"" + uriString + "\")");
            });
        }
示例#7
0
 private string FetchRemoteResourceContent(CombinatorResource resource)
 {
     using (var wc = new WebClient())
     {
         // This strips the UTF8 BOM automatically, see: http://stackoverflow.com/a/1317795/220230
         return(Encoding.UTF8.GetString(wc.DownloadData(resource.AbsoluteUrl)));
     }
 }
示例#8
0
        public void OnContentLoaded(CombinatorResource resource)
        {
            if (Path.GetExtension(resource.AbsoluteUrl.ToString()).ToLowerInvariant() != ".less")
            {
                return;
            }

            resource.Content = Less.Parse(resource.Content);
        }
 private void MinifyResourceContent(CombinatorResource resource)
 {
     if (resource.Type == ResourceType.Style)
     {
         resource.Content = _minificationService.MinifyCss(resource.Content);
     }
     else if (resource.Type == ResourceType.JavaScript)
     {
         resource.Content = _minificationService.MinifyJavaScript(resource.Content);
     }
 }
            public void ProcessResource(CombinatorResource resource, StringBuilder combinedContent, ICombinatorSettings settings)
            {
                if (resource.IsCdnResource && !settings.CombineCdnResources)
                {
                    resource.IsOriginal = true;
                    return;
                }

                resource.Content = "processed: " + resource.Content;
                combinedContent.Append(resource.Content);
            }
示例#11
0
 public void LoadResourceContent(CombinatorResource resource)
 {
     if (resource.IsCdnResource || resource.IsRemoteStorageResource)
     {
         resource.Content = FetchRemoteResourceContent(resource);
     }
     else
     {
         resource.Content = FetchLocalResourceContent(resource);
     }
 }
        public void ProcessResource(CombinatorResource resource, StringBuilder combinedContent, ICombinatorSettings settings)
        {
            if (resource.IsCdnResource && !settings.CombineCdnResources)
            {
                resource.IsOriginal = true;
                return;
            }


            var absoluteUrlString = resource.AbsoluteUrl.ToString();

            _resourceFileService.LoadResourceContent(resource);

            _eventHandler.OnContentLoaded(resource);

            if (string.IsNullOrEmpty(resource.Content))
            {
                return;
            }

            if (resource.Type == ResourceType.Style)
            {
                //var stylesheet = new StylesheetParser().Parse(resource.Content);
                //AdjustRelativePaths(resource, stylesheet);

                //if (settings.EmbedCssImages && (settings.EmbedCssImagesStylesheetExcludeFilter == null || !settings.EmbedCssImagesStylesheetExcludeFilter.IsMatch(absoluteUrlString)))
                //{
                //    EmbedImages(resource, stylesheet, settings.EmbeddedImagesMaxSizeKB);
                //}

                //resource.Content = stylesheet.ToString();

                // Needed until ExCss becomes mature
                RegexAdjustRelativePaths(resource);

                if (settings.EmbedCssImages && (settings.EmbedCssImagesStylesheetExcludeFilter == null || !settings.EmbedCssImagesStylesheetExcludeFilter.IsMatch(absoluteUrlString)))
                {
                    RegexEmbedImages(resource, settings.EmbeddedImagesMaxSizeKB);
                }
            }

            if (settings.MinifyResources && (settings.MinificationExcludeFilter == null || !settings.MinificationExcludeFilter.IsMatch(absoluteUrlString)))
            {
                MinifyResourceContent(resource);
                if (string.IsNullOrEmpty(resource.Content))
                {
                    return;
                }
            }

            _eventHandler.OnContentProcessed(resource);

            combinedContent.Append(resource.Content);
        }
示例#13
0
        private static void ProcessUrlSettings(CombinatorResource resource, MatchEvaluator evaluator)
        {
            string content = resource.Content;

            content = Regex.Replace(
                content,
                "url\\(['|\"]?(.+?)['|\"]?\\)",
                evaluator,
                RegexOptions.IgnoreCase);

            resource.Content = content;
        }
示例#14
0
 public string GetRemoteResourceContent(CombinatorResource resource)
 {
     using (var wc = new WebClient())
     {
         var byteOrderMarkUtf8 = Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble());
         var content           = new UTF8Encoding(false).GetString(wc.DownloadData(resource.AbsoluteUrl));
         if (content.StartsWith(byteOrderMarkUtf8)) // Stripping "?"s from the beginning of css commments "/*"
         {
             content = content.Remove(0, byteOrderMarkUtf8.Length);
         }
         return(content);
     }
 }
示例#15
0
        private static void AddTimestampToUrlIfNecessary(CombinatorResource resource)
        {
            var uriBuilder = new UriBuilder(resource.AbsoluteUrl);

            if (uriBuilder.Query.Contains("timestamp="))
            {
                return;
            }

            uriBuilder.Query = "timestamp=" + resource.LastUpdatedUtc.ToFileTimeUtc(); // Using UriBuilder for this is maybe an overkill
            var urlString = resource.IsCdnResource || resource.IsRemoteStorageResource ? uriBuilder.Uri.ToStringWithoutScheme() : uriBuilder.Uri.PathAndQuery.ToString();

            resource.RequiredContext.Resource.SetUrl(urlString);
        }
示例#16
0
        public void OnContentLoaded(CombinatorResource resource)
        {
            var extension = Path.GetExtension(resource.AbsoluteUrl.ToString()).ToLowerInvariant();

            if (extension != ".sass" && extension != ".scss")
            {
                return;
            }

            using (var compiler = new SassCompiler())
            {
                resource.Content = compiler.Compile(_virtualPathProvider.MapPath(resource.RelativeVirtualPath).Replace("\\", @"\"), false, new List <string>());
            }
        }
示例#17
0
        public void ProcessResource(CombinatorResource resource, StringBuilder combinedContent, ICombinatorSettings settings)
        {
            if (!resource.IsCdnResource || settings.CombineCDNResources)
            {
                var absoluteUrlString = resource.AbsoluteUrl.ToString();

                if (!resource.IsCdnResource)
                {
                    resource.Content = _resourceFileService.GetLocalResourceContent(resource);
                }
                else if (settings.CombineCDNResources)
                {
                    resource.Content = _resourceFileService.GetRemoteResourceContent(resource);
                }

                if (String.IsNullOrEmpty(resource.Content))
                {
                    return;
                }

                if (settings.MinifyResources && (settings.MinificationExcludeFilter == null || !settings.MinificationExcludeFilter.IsMatch(absoluteUrlString)))
                {
                    MinifyResourceContent(resource);
                    if (String.IsNullOrEmpty(resource.Content))
                    {
                        return;
                    }
                }

                // Better to do after minification, as then urls commented out are removed
                if (resource.Type == ResourceType.Style)
                {
                    AdjustRelativePaths(resource);

                    if (settings.EmbedCssImages && (settings.EmbedCssImagesStylesheetExcludeFilter == null || !settings.EmbedCssImagesStylesheetExcludeFilter.IsMatch(absoluteUrlString)))
                    {
                        EmbedImages(resource, settings.EmbeddedImagesMaxSizeKB);
                    }
                }

                combinedContent.Append(resource.Content);
            }
            else
            {
                resource.IsOriginal = true;
            }
        }
        private static void ProcessImageUrls(CombinatorResource resource, Stylesheet stylesheet, Action <RuleSet, Term> processor)
        {
            ProcessUrls(
                resource,
                stylesheet,
                (ruleSet, urlTerm) =>
            {
                var url       = urlTerm.Value;
                var extension = Path.GetExtension(url).ToLowerInvariant();

                // This is a dumb check but otherwise we'd have to inspect the file thoroughly
                if (!string.IsNullOrEmpty(extension) && ".jpg .jpeg .png .gif .tiff .bmp".Contains(extension))
                {
                    processor(ruleSet, urlTerm);
                }
            });
        }
        private static void ProcessUrls(CombinatorResource resource, Stylesheet stylesheet, Action <RuleSet, Term> processor)
        {
            var items =
                stylesheet.RuleSets
                .SelectMany(ruleset => ruleset.Declarations
                            .SelectMany(declaration => declaration.Expression.Terms
                                        .Where(term => term.Type == TermType.Url)
                                        .Select(term => new { RuleSet = ruleset, Term = term })))
                .ToList();

            // Projected to a list so for can be used. This makes it possible to modify the collection from processors.
            for (int i = 0; i < items.Count; i++)
            {
                var item = items[i];
                processor(item.RuleSet, item.Term);
            }
        }
示例#20
0
        public string SerializeResourceSettings(CombinatorResource resource)
        {
            var settings = resource.RequiredContext.Settings;

            if (settings == null)
            {
                return("");
            }

            return(_serializer.XmlSerialize(
                       new SerializableSettings()
            {
                Url = resource.IsOriginal ? resource.IsCdnResource ? resource.AbsoluteUrl : resource.RelativeUrl : null,
                Culture = settings.Culture,
                Condition = settings.Condition,
                Attributes = settings.Attributes
            }));
        }
示例#21
0
        public string GetLocalResourceContent(CombinatorResource resource)
        {
            var relativeVirtualPath = resource.RelativeVirtualPath;

            // Maybe TryFileExists would be better?
            if (!_virtualPathProvider.FileExists(relativeVirtualPath))
            {
                throw new OrchardException(T("Local resource file not found under {0}", relativeVirtualPath));
            }

            string content;

            using (var stream = _virtualPathProvider.OpenFile(relativeVirtualPath))
            {
                content = new StreamReader(stream).ReadToEnd();
            }

            return(content);
        }
            public void Save(string fingerprint, CombinatorResource resource, ICombinatorSettings settings)
            {
                int count;

                sliceCounts.TryGetValue(fingerprint, out count);
                sliceCounts[fingerprint] = ++count;

                var sliceName = fingerprint + "-" + count;

                var savedResource = _resourceRepository.NewResource(resource.Type);

                var requiredContext = resource.RequiredContext;

                savedResource.IsOriginal     = resource.IsOriginal;
                savedResource.LastUpdatedUtc = DateTime.UtcNow;
                savedResource.FillRequiredContext(
                    requiredContext.Resource.Name,
                    requiredContext.Resource.Url,
                    requiredContext.Settings.Culture,
                    requiredContext.Settings.Condition,
                    requiredContext.Settings.Attributes);
                savedResource.Content = resource.Content;


                if (!resource.IsOriginal)
                {
                    var url = "/Media/Default/_PiedoneModules/Combinator/";
                    if (resource.Type == ResourceType.Style)
                    {
                        url += "Styles/" + sliceName + ".css";
                    }
                    else if (resource.Type == ResourceType.JavaScript)
                    {
                        url += "Scripts/" + sliceName + ".js";
                    }

                    savedResource.RequiredContext.Resource.SetUrl(url);
                }


                _resourceRepository.SaveResource(sliceName, savedResource);
            }
        public string SerializeResourceSettings(CombinatorResource resource)
        {
            var settings = resource.RequiredContext.Settings;

            if (settings == null)
            {
                return("");
            }

            return(_jsonConverter.Serialize(
                       new SerializableSettings()
            {
                Url = resource.IsOriginal ? !resource.IsCdnResource && !resource.IsRemoteStorageResource ? resource.RelativeUrl : resource.AbsoluteUrl : null,
                IsRemoteStorageResource = resource.IsRemoteStorageResource,
                Culture = settings.Culture,
                Condition = settings.Condition,
                Attributes = settings.Attributes,
                TagAttributes = resource.RequiredContext.Resource.TagBuilder.Attributes
            }));
        }
        // This will be needed until ExCSS becomes mature
        #region Legacy Regex-based CSS processing
        public static void RegexConvertRelativeUrlsToAbsolute(CombinatorResource resource, Uri baseUri)
        {
            if (string.IsNullOrEmpty(resource.Content) || resource.Type != ResourceType.Style)
            {
                return;
            }

            RegexProcessUrls(resource,
                             (match) =>
            {
                var url = match.Groups[1].ToString();

                if (!url.StartsWith("//") && !Uri.IsWellFormedUriString(url, UriKind.Absolute))
                {
                    url = UriHelper.Combine(baseUri.ToStringWithoutScheme(), url);
                }

                return("url(\"" + url + "\")");
            });
        }
        private void RegexProcessImageUrls(CombinatorResource resource, ImageMatchProcessor matchProcessor)
        {
            RegexProcessUrls(resource,
                             (match) =>
            {
                var url       = match.Groups[1].Value;
                var extension = Path.GetExtension(url).ToLowerInvariant();

                // This is a dumb check but otherwise we'd have to inspect the file thoroughly
                if (!string.IsNullOrEmpty(extension) && ".jpg .jpeg .png .gif .tiff .bmp".Contains(extension))
                {
                    var result = matchProcessor(url, extension, match);
                    if (result != null)
                    {
                        return(result);
                    }
                }

                return(match.Groups[0].Value);
            });
        }
        private void RegexEmbedImages(CombinatorResource resource, int maxSizeKB)
        {
            RegexProcessImageUrls(resource,
                                  (url, extenstion, match) =>
            {
                var imageContent = _resourceFileService.GetImageContent(RegexMakeInlineUri(resource, url));

                if (imageContent.Length / 1024 <= maxSizeKB)
                {
                    var dataUrl =
                        "data:image/"
                        + Path.GetExtension(url).Replace(".", "")
                        + ";base64,"
                        + Convert.ToBase64String(imageContent);

                    return("url(\"" + dataUrl + "\")");
                }

                return(null);
            });
        }
        private void EmbedImages(CombinatorResource resource, Stylesheet stylesheet, int maxSizeKB)
        {
            ProcessImageUrls(
                resource,
                stylesheet,
                (ruleSet, urlTerm) =>
            {
                var url          = urlTerm.Value;
                var imageContent = _resourceFileService.GetImageContent(InlineUriFactory(resource, url));

                if (imageContent.Length / 1024 <= maxSizeKB)
                {
                    var dataUrl =
                        "data:image/"
                        + Path.GetExtension(url).Replace(".", "")
                        + ";base64,"
                        + Convert.ToBase64String(imageContent);

                    urlTerm.Value = dataUrl;
                }
            });
        }
        public static void ConvertRelativeUrlsToAbsolute(CombinatorResource resource, Uri baseUri)
        {
            if (string.IsNullOrEmpty(resource.Content) || resource.Type != ResourceType.Style)
            {
                return;
            }

            var stylesheet = new StylesheetParser().Parse(resource.Content);

            // Modifying relative urls (because when saved, local urls were converted to unified relative ones) to point to the original domain
            ProcessUrls(
                resource,
                stylesheet,
                (ruleSet, urlTerm) =>
            {
                if (urlTerm.Value.StartsWith("//") || Uri.IsWellFormedUriString(urlTerm.Value, UriKind.Absolute))
                {
                    return;
                }

                urlTerm.Value = UriHelper.Combine(baseUri.ToStringWithoutScheme(), urlTerm.Value);
            });
        }
示例#29
0
 private static bool IsOwnedResource(CombinatorResource resource)
 {
     return((!resource.IsCdnResource && !resource.IsOriginal) || resource.IsRemoteStorageResource);
 }
 public void LoadResourceContent(CombinatorResource resource)
 {
 }