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; } }); }
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; }
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 + "\")"); }); }
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))); } }
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); }
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); }
private static void ProcessUrlSettings(CombinatorResource resource, MatchEvaluator evaluator) { string content = resource.Content; content = Regex.Replace( content, "url\\(['|\"]?(.+?)['|\"]?\\)", evaluator, RegexOptions.IgnoreCase); resource.Content = content; }
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); } }
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); }
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>()); } }
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); } }
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 })); }
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); }); }
private static bool IsOwnedResource(CombinatorResource resource) { return((!resource.IsCdnResource && !resource.IsOriginal) || resource.IsRemoteStorageResource); }
public void LoadResourceContent(CombinatorResource resource) { }