/// <summary> /// Produces a code minifiction of JS-assets by using C# port of /// Douglas Crockford's JSMin /// </summary> /// <param name="assets">Set of JS-assets</param> /// <returns>Set of JS-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.IsScript && !a.Minified).ToList(); if (assetsToProcessing.Count == 0) { return assets; } var jsMin = new JsMinifier(); foreach (var asset in assetsToProcessing) { InnerMinify(asset, jsMin); } return assets; }
public void JsMinificationIsCorrect() { // Arrange var minifier = new JsMinifier(); const string input = "// is.js\r\n" + "\r\n" + "// (c) 2001 Douglas Crockford\r\n" + "// 2001 June 3\r\n" + "\r\n\r\n" + "// is\r\n" + "\r\n" + "// The -is- object is used to identify the browser. Every browser edition\r\n" + "// identifies itself, but there is no standard way of doing it, and some of\r\n" + "// the identification is deceptive. This is because the authors of web\r\n" + "// browsers are liars. For example, Microsoft's IE browsers claim to be\r\n" + "// Mozilla 4. Netscape 6 claims to be version 5.\r\n" + "\r\n" + "// Warning: Do not use this awful, awful code or any other thing like it.\r\n" + "// Seriously.\r\n" + "\r\n" + "var is = {\r\n" + "\tie: navigator.appName == 'Microsoft Internet Explorer',\r\n" + "\tjava: navigator.javaEnabled(),\r\n" + "\tns: navigator.appName == 'Netscape',\r\n" + "\tua: navigator.userAgent.toLowerCase(),\r\n" + "\tversion: parseFloat(navigator.appVersion.substr(21)) ||\r\n" + " parseFloat(navigator.appVersion),\r\n" + "\twin: navigator.platform == 'Win32'\r\n" + "}\r\n" + "is.mac = is.ua.indexOf('mac') >= 0;\r\n" + "\r\n" + "if (is.ua.indexOf('opera') >= 0) {\r\n" + "\tis.ie = is.ns = false;\r\n" + "\tis.opera = true;\r\n" + "}\r\n" + "\r\n" + "if (is.ua.indexOf('gecko') >= 0) {\r\n" + "\tis.ie = is.ns = false;\r\n" + "\tis.gecko = true;\r\n" + "}" ; const string targetOutput = "var is={ie:navigator.appName=='Microsoft Internet Explorer',java:navigator.javaEnabled(),ns:navigator.appName=='Netscape',ua:navigator.userAgent.toLowerCase(),version:parseFloat(navigator.appVersion.substr(21))||parseFloat(navigator.appVersion),win:navigator.platform=='Win32'}\n" + "is.mac=is.ua.indexOf('mac')>=0;if(is.ua.indexOf('opera')>=0){is.ie=is.ns=false;is.opera=true;}\n" + "if(is.ua.indexOf('gecko')>=0){is.ie=is.ns=false;is.gecko=true;}" ; // Act string output = minifier.Minify(input); // Assert Assert.AreEqual(targetOutput, output); }
/// <summary> /// Produces a code minifiction of JS-asset by using C# port of /// Douglas Crockford's JSMin /// </summary> /// <param name="asset">JS-asset</param> /// <returns>JS-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 jsMin = new JsMinifier(); InnerMinify(asset, jsMin); return asset; }
public void Setup() { var websiteInfo = new Mock <IWebsiteInfo>(); websiteInfo.Setup(x => x.GetBasePath()).Returns("/"); websiteInfo.Setup(x => x.GetBaseUrl()).Returns(new Uri("http://test.com")); _jsMin = new JsMinifier(); _nuglify = new NuglifyJs( new NuglifySettings(new NuglifyCodeSettings(null), new CssSettings()), Mock.Of <ISourceMapDeclaration>()); var nodeServices = new SmidgeJavaScriptServices(NodeServicesFactory.CreateNodeServices( new NodeServicesOptions(new NullServiceProvider()) { ProjectPath = AssemblyPath, WatchFileExtensions = new string[] {} })); _jsUglify = new UglifyNodeMinifier(nodeServices); }
/// <summary> /// Produces a code minifiction of JS asset by using C# port of /// Douglas Crockford's JSMin /// </summary> /// <param name="asset">JS asset</param> /// <returns>JS 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 jsMin = new JsMinifier(); InnerMinify(asset, jsMin); return(asset); }
public void Should_Minify_Single_File() { var filepath = @"c:\css\script.js"; var script = "function test() { alert(\"hello\"); }"; var fileSystem = new MockFileSystem(new Dictionary <string, MockFileData> { { filepath, new MockFileData(script) } }); var files = new List <FileInfo> { new FileInfo(filepath) }; var minifier = new JsMinifier(fileSystem, files, _outputPath); minifier.Minify(); var minifiedFile = fileSystem.File.ReadAllText(_outputPath, Encoding.UTF8); Assert.Equal("function test(){alert(\"hello\")}", minifiedFile); }
public static TargetConfig LoadFromFile(string path) { JavaScriptSerializer ser = new JavaScriptSerializer(new TargetConfigTypeResolver()); ser.RegisterConverters(new JavaScriptConverter[] { new ModelConverter() }); using (StreamReader r = new StreamReader(path)) { string json = r.ReadToEnd(); // replace Global Variables in the json file foreach (string key in GlobalVariables.Keys) { json = json.Replace($"${key}", HttpUtility.JavaScriptStringEncode(GlobalVariables[key].ToString())); } var minifier = new JsMinifier(); // minify JSON to strip away comments // Comments in config files are very useful but JSON parsers // do not allow comments. Minification solves the issue. string jsonMin = minifier.Minify(json); return(ser.Deserialize <TargetConfig>(jsonMin)); } }
/// <summary> /// Produces code minifiction of JS content by using C# port of /// Douglas Crockford's JSMin (version of May 22 2007) /// </summary> /// <param name="content">JS content</param> /// <param name="isInlineCode">Flag whether the content is inline code</param> /// <param name="encoding">Text encoding</param> /// <returns>Minification result</returns> public CodeMinificationResult Minify(string content, bool isInlineCode, Encoding encoding) { if (string.IsNullOrWhiteSpace(content)) { return(new CodeMinificationResult(string.Empty)); } string newContent = string.Empty; var errors = new List <MinificationErrorInfo>(); try { var jsMin = new JsMinifier(); newContent = jsMin.Minify(content); } catch (JsMinificationException e) { errors.Add(new MinificationErrorInfo(e.Message)); } var minificationResult = new CodeMinificationResult(newContent, errors); return(minificationResult); }
private void InnerMinify(IAsset asset, JsMinifier jsMin) { string newContent; string assetUrl = asset.Url; try { newContent = jsMin.Minify(asset.Content); } catch (JsMinificationException 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)); } asset.Content = newContent; asset.Minified = true; }
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; } } } }