/// <summary> /// Produces a code minifiction of CSS assets by using WebGrease Semantic CSS minifier /// </summary> /// <param name="assets">Set of CSS assets</param> /// <returns>Set of CSS assets with minified text content</returns> public IList <IAsset> Minify(IList <IAsset> assets) { if (assets == null) { throw new ArgumentNullException( nameof(assets), string.Format(CoreStrings.Common_ArgumentIsNull, nameof(assets)) ); } if (assets.Count == 0) { return(assets); } var assetsToProcessing = assets.Where(a => a.IsStylesheet && !a.Minified).ToList(); if (assetsToProcessing.Count == 0) { return(assets); } var wgCssMinifier = new CssMinifier(new WebGreaseContext(_wgConfiguration)) { ShouldMinify = ShouldMinify }; foreach (var asset in assetsToProcessing) { InnerMinify(asset, wgCssMinifier); } return(assets); }
/// <summary> /// Minifies the specified resource. /// </summary> /// <param name="resource">The resource.</param> /// <returns>The minified resource.</returns> public override string Minify(string resource) { CssMinifier minifier; if (this.Options.Minify) { minifier = new CssMinifier { RemoveWhiteSpace = true }; } else { minifier = new CssMinifier { RemoveWhiteSpace = false }; } string result = minifier.Minify(resource); if (this.Options.CacheFiles) { this.AddItemToCache(this.Options.MinifyCacheKey, result); } return(result); }
/// <summary> /// Runs the CSS minifier on the content. /// </summary> public static IAsset MinifyCss(this IAsset asset, CssSettings settings) { var minifier = new CssMinifier(settings); asset.Processors.Add(minifier); return(asset); }
public void MinifyComplexCaseTest() { var minifier = new CssMinifier(new WebGreaseContext(new WebGreaseConfiguration())); var filePath = Path.Combine(TestDeploymentPaths.TestDirectory, @"css.tests\css30\sites\vsteam\jquery-combined.css"); var css = File.ReadAllText(filePath); var actual = minifier.Minify(css); Assert.IsTrue(actual.Length < css.Length); }
public void MinifierErrorsTest() { var badCss = "p {color:red;}\r\np {margin: 10px}\r\np {width: }\r\nbody margin: 1em;}"; var minifier = new CssMinifier(new WebGreaseContext(new WebGreaseConfiguration())); var output = minifier.Minify(badCss); Assert.IsTrue(minifier.Errors.Count > 0); Assert.IsTrue(minifier.Errors[0].StartsWith("(3"), "first error should be on line 3"); }
/// <summary> /// Minifies CSS from a stream input /// </summary> /// <param name="stream"></param> /// <returns></returns> public static string MinifyCss(Stream stream) { var cssMinify = new CssMinifier(); if (!stream.CanRead) { throw new InvalidOperationException("Cannot read input stream"); } if (stream.CanSeek) { stream.Position = 0; } return(cssMinify.Minify(new StreamReader(stream))); }
public async Task MinifyCss_NullSettings_Success() { var minifier = new CssMinifier(null); var context = new Mock <IAssetContext>().SetupAllProperties(); context.Object.Content = new Dictionary <string, byte[]> { { "", "body { color: yellow; }".AsByteArray() } }; var options = new Mock <WebOptimizerOptions>(); await minifier.ExecuteAsync(context.Object); Assert.Equal("body{color:#ff0}", context.Object.Content.First().Value.AsString()); Assert.Equal("", minifier.CacheKey(new DefaultHttpContext())); }
public async Task MinifyCss_EmptyContent_Success(string input) { var minifier = new CssMinifier(new CssSettings()); var context = new Mock <IAssetContext>().SetupAllProperties(); context.Object.Content = new Dictionary <string, byte[]> { { "", input.AsByteArray() } }; var options = new Mock <WebOptimizerOptions>(); await minifier.ExecuteAsync(context.Object); Assert.Equal("", context.Object.Content.First().Value.AsString()); Assert.Equal("", minifier.CacheKey(new DefaultHttpContext())); }
private string minifyCss(string templateContent) { var outputPath = Path.Combine(_siteDirectory, @"_site\css\minified.css"); //todo extract all internal css/less links from template var cssFiles = new List <FileInfo>(); var cssMinifier = new CssMinifier(_fileSystem, cssFiles, outputPath); cssMinifier.Minify(); //todo replace extracted links with single link to minified css (possibly with a hash appended) throw new NotImplementedException(); }
public void MinifiesGoodCssTest() { var goodCssContent = "p {color:red;}\r\np {margin: 10px}\r\np {width: 10px}\r\nbody {margin: 1em;}"; var expected = "p{color:red;margin:10px;width:10px}body{margin:1em}"; var minifier = new CssMinifier(new WebGreaseContext(new WebGreaseConfiguration())); var actual = minifier.Minify(goodCssContent); Assert.AreEqual <string>(actual, expected); // pretty print is the only other option right now; should add indents, new lines etc. minifier.ShouldMinify = false; expected = "p\r\n{\r\n color:red;\r\n margin:10px;\r\n width:10px\r\n}\r\nbody\r\n{\r\n margin:1em\r\n}\r\n"; actual = minifier.Minify(goodCssContent); Assert.AreEqual <string>(actual, expected); }
private void InnerMinify(IAsset asset, CssMinifier wgCssMinifier) { string content = asset.Content; string topCharset = string.Empty; string preprocessedContent = content; if (EjectCharset) { preprocessedContent = EjectCssCharset(preprocessedContent, ref topCharset); } string newContent; string assetUrl = asset.Url; try { newContent = wgCssMinifier.Minify(preprocessedContent); if (EjectCharset && !string.IsNullOrWhiteSpace(topCharset)) { string separator = ShouldMinify ? string.Empty : Environment.NewLine; newContent = topCharset + separator + newContent; } IList <string> errors = wgCssMinifier.Errors; if (errors.Count > 0) { throw new WgMinificationException(FormatErrorDetails(errors[0], preprocessedContent, assetUrl)); } } catch (WgMinificationException e) { throw new AssetMinificationException( string.Format(CoreStrings.Minifiers_MinificationSyntaxError, CODE_TYPE, assetUrl, MINIFIER_NAME, e.Message)); } catch (Exception e) { throw new AssetMinificationException( string.Format(CoreStrings.Minifiers_MinificationFailed, CODE_TYPE, assetUrl, MINIFIER_NAME, e.Message), e); } asset.Content = newContent; asset.Minified = true; }
/// <summary> /// Produces a code minifiction of CSS asset by using WebGrease Semantic CSS minifier /// </summary> /// <param name="asset">CSS asset</param> /// <returns>CSS asset with minified text content</returns> public IAsset Minify(IAsset asset) { if (asset == null) { throw new ArgumentException(CoreStrings.Common_ValueIsEmpty, "asset"); } if (asset.Minified) { return(asset); } var wgCssMinifier = new CssMinifier(new WebGreaseContext(_wgConfiguration)) { ShouldMinify = ShouldMinify }; InnerMinify(asset, wgCssMinifier); return(asset); }
/// <summary> /// Minifies the specified resource. /// </summary> /// <param name="resource">The resource.</param> /// <returns>The minified resource.</returns> public override string Minify(string resource) { CssMinifier minifier; if (this.Options.Minify) { minifier = new CssMinifier { RemoveWhiteSpace = true }; } else { minifier = new CssMinifier { RemoveWhiteSpace = false }; } return(minifier.Minify(resource)); }
/// <summary> /// Produces a code minifiction of CSS asset by using WebGrease Semantic CSS minifier /// </summary> /// <param name="asset">CSS asset</param> /// <returns>CSS asset with minified text content</returns> public IAsset Minify(IAsset asset) { if (asset == null) { throw new ArgumentNullException( nameof(asset), string.Format(CoreStrings.Common_ArgumentIsNull, nameof(asset)) ); } if (asset.Minified) { return(asset); } var wgCssMinifier = new CssMinifier(new WebGreaseContext(_wgConfiguration)) { ShouldMinify = ShouldMinify }; InnerMinify(asset, wgCssMinifier); return(asset); }
private void InnerMinify(IAsset asset, CssMinifier wgCssMinifier) { string content = asset.Content; string topCharset = string.Empty; string preprocessedContent = content; if (EjectCharset) { preprocessedContent = EjectCssCharset(preprocessedContent, ref topCharset); } string newContent; string assetUrl = asset.Url; try { newContent = wgCssMinifier.Minify(preprocessedContent); if (EjectCharset && !string.IsNullOrWhiteSpace(topCharset)) { string separator = ShouldMinify ? string.Empty : Environment.NewLine; newContent = topCharset + separator + newContent; } IList<string> errors = wgCssMinifier.Errors; if (errors.Count > 0) { throw new WgMinificationException(FormatErrorDetails(errors[0], preprocessedContent, assetUrl)); } } catch (WgMinificationException e) { throw new AssetMinificationException( string.Format(CoreStrings.Minifiers_MinificationSyntaxError, CODE_TYPE, assetUrl, MINIFIER_NAME, e.Message)); } catch (Exception e) { throw new AssetMinificationException( string.Format(CoreStrings.Minifiers_MinificationFailed, CODE_TYPE, assetUrl, MINIFIER_NAME, e.Message), e); } asset.Content = newContent; asset.Minified = true; }
/// <summary> /// Produces a code minifiction of CSS-assets by using WebGrease Semantic CSS-minifier /// </summary> /// <param name="assets">Set of CSS-assets</param> /// <returns>Set of CSS-assets with minified text content</returns> public IList<IAsset> Minify(IList<IAsset> assets) { if (assets == null) { throw new ArgumentException(CoreStrings.Common_ValueIsEmpty, "assets"); } if (assets.Count == 0) { return assets; } var assetsToProcessing = assets.Where(a => a.IsStylesheet && !a.Minified).ToList(); if (assetsToProcessing.Count == 0) { return assets; } var wgCssMinifier = new CssMinifier(new WebGreaseContext(_wgConfiguration)) { ShouldMinify = ShouldMinify }; foreach (var asset in assetsToProcessing) { InnerMinify(asset, wgCssMinifier); } return assets; }
public void ProcessRequest(HttpContext context) { // set from an earlier in pipeline by CDNInterceptPipeline string minifyPath = StringUtil.GetString(context.Items["MinifyPath"]); if (string.IsNullOrEmpty(minifyPath)) { context.Response.StatusCode = 404; context.Response.End(); } UrlString url = new UrlString(minifyPath); string localPath = url.Path; string filePath = FileUtil.MapPath(localPath); // if the request is a .js file if (localPath.EndsWith(".js")) { HashEncryption hasher = new HashEncryption(HashEncryption.EncryptionProvider.MD5); if (!string.IsNullOrEmpty(localPath)) { // generate a unique filename for the cached .js version string cachedFilePath = FileUtil.MapPath(string.Format("/App_Data/MediaCache/{0}.js", hasher.Hash(url.ToString()))); // if it doesn't exist create it if (!FileUtil.FileExists(cachedFilePath)) { // if the original file exsits minify it if (FileUtil.FileExists(filePath)) { JsMinifier minifier = new JsMinifier(); string minified = minifier.Minify(filePath); FileUtil.WriteToFile(cachedFilePath, minified); } } if (FileUtil.FileExists(cachedFilePath)) { context.Response.ClearHeaders(); context.Response.Cache.SetExpires(DateTime.Now.AddDays(14)); context.Response.AddHeader("Content-Type", "application/x-javascript; charset=utf-8"); context.Response.WriteFile(cachedFilePath); context.Response.End(); _success = true; } } } // if the request is a .css file else if (localPath.EndsWith(".css")) { HashEncryption hasher = new HashEncryption(HashEncryption.EncryptionProvider.MD5); if (!string.IsNullOrEmpty(localPath)) { // generate a unique filename for the cached .css version string cachedFilePath = FileUtil.MapPath(string.Format("/App_Data/MediaCache/{0}.css", hasher.Hash(url.ToString()))); // if it doesn't exist create it if (!FileUtil.FileExists(cachedFilePath)) { // if the original file exsits minify it if (FileUtil.FileExists(filePath)) { CssMinifier minifier = new CssMinifier(); string minified = CssMinifier.Minify(FileUtil.ReadFromFile(filePath)); // if Css Processing is enabled, replace any urls inside the css file. if (CDNSettings.ProcessCss) { // find all css occurences of url([url]) Regex reReplaceUrl = new Regex("url\\(\\s*['\"]?([^\"')]+)['\"]?\\s*\\)"); try { // replacing url([url]) with url([cdnUrl]) in css minified = reReplaceUrl.Replace(minified, (m) => { string oldUrl = ""; if (m.Groups.Count > 1) { oldUrl = m.Groups[1].Value; } if (WebUtil.IsInternalUrl(oldUrl)) { if (oldUrl.StartsWith(".")) { oldUrl = VirtualPathUtility.Combine(url.Path, oldUrl); } string newUrl = CDNManager.ReplaceMediaUrl(oldUrl, string.Empty); if (!string.IsNullOrEmpty(newUrl)) { return(m.Value.Replace(m.Groups[1].Value, newUrl)); } } return(m.Value); }); } catch (Exception ex) { Log.Error("Minify error", ex, this); } } FileUtil.WriteToFile(cachedFilePath, minified); } } if (FileUtil.FileExists(cachedFilePath)) { context.Response.ClearHeaders(); context.Response.Cache.SetExpires(DateTime.Now.AddDays(14)); context.Response.AddHeader("Content-Type", "text/css; charset=utf-8"); context.Response.TransmitFile(cachedFilePath); context.Response.End(); _success = true; } } } }
/// <summary> /// Produces a code minifiction of CSS-asset by using WebGrease Semantic CSS-minifier /// </summary> /// <param name="asset">CSS-asset</param> /// <returns>CSS-asset with minified text content</returns> public IAsset Minify(IAsset asset) { if (asset == null) { throw new ArgumentException(CoreStrings.Common_ValueIsEmpty, "asset"); } if (asset.Minified) { return asset; } var wgCssMinifier = new CssMinifier(new WebGreaseContext(_wgConfiguration)) { ShouldMinify = ShouldMinify }; InnerMinify(asset, wgCssMinifier); return asset; }
public virtual async Task <ActionResult> Css(string name, string type) { var dynamicResourceResourceDefaultBasePath = WebConstants.CssDynamicResourceResourceDefaultBasePath; var dynamicResourceDefaultBasePath = WebConstants.CssDynamicResourceDefaultBasePath; if (string.IsNullOrEmpty(dynamicResourceResourceDefaultBasePath)) { dynamicResourceResourceDefaultBasePath = "/css"; } if (string.IsNullOrEmpty(dynamicResourceDefaultBasePath)) { dynamicResourceDefaultBasePath = "/css/app"; } return(await GetContentAsync(name : name, type : type, mime : "text/css", extension : ".css", dynamicResourceResourceBasePathKey : WebConstants.CSS_DYNAMIC_RESOURCE_RESOURCE_BASEPATH_KEY, dynamicResourceResourceDefaultBasePath : dynamicResourceResourceDefaultBasePath, dynamicResourcePathKey : WebConstants.CSS_DYNAMIC_RESOURCE_PATH_KEY, dynamicResourceDefaultBasePath : dynamicResourceDefaultBasePath, minify : (content) => ClientSideContentProvider.MinifyCss?CssMinifier.Minify(content) : content)); }