private void Minify(string jsPath) { string minifiedPath = null; if (jsPath.EndsWith(".js", StringComparison.OrdinalIgnoreCase) == false) { minifiedPath = jsPath + ".min"; } else { minifiedPath = jsPath.Substring(0, jsPath.Length - 3) + ".min.js"; } var mapPath = jsPath.Replace(".js", ".min.js") + ".map"; StreamWriter mapWriter = null; V3SourceMap sourceMap = null; try { var settings = new CodeSettings(); //try //{ //Be aware that the text encoding should be UTF-8 with no Byte-Order Mark (BOM) written at the beginning. //V3 source map files that include a BOM will not be read by Chrome mapWriter = new StreamWriter(mapPath, false, new System.Text.UTF8Encoding(false)); sourceMap = new V3SourceMap(mapWriter); sourceMap.StartPackage(minifiedPath, mapPath); // the first argument specifies "file" field in map file. // the second arugment specifies "//# sourceMappingURL=" in the output (minified js) settings.SymbolsMap = sourceMap; //} //catch (Exception ex) //{ //} settings.TermSemicolons = true; Minifier minifier = new Minifier(); minifier.FileName = jsPath; var content = minifier.MinifyJavaScript(File.ReadAllText(jsPath), settings); using (StreamWriter sw = new StreamWriter(minifiedPath)) { sw.Write(content); } } finally { if (sourceMap != null) { sourceMap.EndPackage(); sourceMap.Dispose(); } mapWriter?.Dispose(); } }
/// <summary> /// Override to end the output of all files processed, this is required if not appending source maps to each file /// </summary> public void EndPackage() { _wrapped.EndPackage(); //need to dispose the wrapped source map which is what is used to generate the whole thing _wrapped.Dispose(); //get the created map and base64 it SourceMapOutput = _mapBuilder.ToString(); }
public void SourceMapForMultipleFiles() { var assetBuilder = new StringBuilder(); var assets = new[] { "SourceMapForMultipleFiles1.js", "SourceMapForMultipleFiles2.js", "SourceMapForMultipleFiles3.js" }; var currentPath = AppDomain.CurrentDomain.BaseDirectory; foreach (var asset in assets) { assetBuilder.AppendLine("///#source 1 1 " + asset); var path = Path.Combine(currentPath, "TestData\\JS\\Input\\SourceMap\\" + asset); assetBuilder.AppendLine(File.ReadAllText(path)); } var stringBuilder = new StringBuilder(); using (var textWriter = new StringWriter(stringBuilder)) { var sourceMap = new V3SourceMap(textWriter); sourceMap.StartPackage("infile.js", "SourceMapForMultipleFiles.js.map"); var uglifyResult = Uglify.Js(assetBuilder.ToString(), "SourceMapForMultipleFiles.js", new CodeSettings { SymbolsMap = sourceMap, SourceMode = JavaScriptSourceMode.Program, MinifyCode = true, OutputMode = OutputMode.SingleLine, StripDebugStatements = false, LineTerminator = "\r\n" }); sourceMap.EndPackage(); sourceMap.Dispose(); var code = uglifyResult.Code; Assert.AreEqual(File.ReadAllText(Path.Combine(currentPath, "TestData\\JS\\Expected\\SourceMap\\SourceMapForMultipleFiles.js")), code); var builder = stringBuilder.ToString(); Assert.AreEqual(File.ReadAllText(Path.Combine(currentPath, "TestData\\JS\\Expected\\SourceMap\\SourceMapForMultipleFiles.js.map")), builder); } }
private static void MinifyFileWithSourceMap(string file, string minFile, CodeSettings settings, bool isBundle) { string mapPath = minFile + ".map"; ProjectHelpers.CheckOutFileFromSourceControl(mapPath); using (TextWriter writer = new StreamWriter(mapPath, false, new UTF8Encoding(false))) using (V3SourceMap sourceMap = new V3SourceMap(writer)) { settings.SymbolsMap = sourceMap; sourceMap.StartPackage(Path.GetFileName(minFile), Path.GetFileName(mapPath)); // This fails when debugger is attached. Bug raised with Ron Logan MinifyFile(file, minFile, settings, isBundle); sourceMap.EndPackage(); if (!isBundle) { MarginBase.AddFileToProject(file, mapPath); } } }
public string BuildBundleContent(Bundle bundle, BundleContext context, IEnumerable <BundleFile> files) { if (files == null) { return(string.Empty); } if (context == null) { throw new ArgumentNullException("context"); } if (bundle == null) { throw new ArgumentNullException("bundle"); } // Generates source map using an approach documented here: http://ajaxmin.codeplex.com/discussions/446616 // Get paths and create any directories required var mapVirtualPath = bundle.Path + ".map"; var sourcePath = HostingEnvironment.MapPath(bundle.Path); var mapPath = HostingEnvironment.MapPath(mapVirtualPath); var directoryPath = Path.GetDirectoryName(mapPath); if (directoryPath == null) { throw new InvalidOperationException("directoryPath was invalid."); } if (!Directory.Exists(directoryPath)) { Directory.CreateDirectory(directoryPath); } // Concatenate file contents to be minified, including the sourcemap hints var contentConcated = new StringBuilder(); foreach (var file in files) { var filePath = HostingEnvironment.MapPath(file.VirtualFile.VirtualPath); if (bundleFileType == BundleFileTypes.JavaScript) { contentConcated.AppendLine(";///#SOURCE 1 1 " + filePath); } contentConcated.AppendLine(file.ApplyTransforms()); } var contentConcatedString = contentConcated.ToString(); // Try minify (+ source map) using AjaxMin dll try { var contentBuilder = new StringBuilder(); using (var contentWriter = new StringWriter(contentBuilder)) using (var mapWriter = new StreamWriter(mapPath, false, new UTF8Encoding(false))) using (var sourceMap = new V3SourceMap(mapWriter)) { sourceMap.StartPackage(sourcePath, mapPath); var settings = new CodeSettings() { EvalTreatment = EvalTreatment.MakeImmediateSafe, PreserveImportantComments = false, SymbolsMap = sourceMap, TermSemicolons = true }; var minifier = new Minifier(); string contentMinified; switch (bundleFileType) { case BundleFileTypes.JavaScript: contentMinified = minifier.MinifyJavaScript(contentConcatedString, settings); break; case BundleFileTypes.StyleSheet: var cssSettings = new CssSettings { TermSemicolons = true }; contentMinified = minifier.MinifyStyleSheet(contentConcatedString, cssSettings, settings); break; default: throw new ArgumentOutOfRangeException("Unrecognised BundleFileTypes enum value. Could not find minifier method to handle."); } if (minifier.ErrorList.Count > 0) { return(GenerateMinifierErrorsContent(contentConcatedString, minifier)); } contentWriter.Write(contentMinified); sourceMap.EndPackage(); sourceMap.EndFile(contentWriter, "\r\n"); } return(contentBuilder.ToString()); } catch (Exception ex) { Trace.TraceWarning("An exception occurred trying to build bundle contents for bundle with virtual path: " + bundle.Path + ". See Exception details.", ex, typeof(AjaxMinBundleBuilder)); return(GenerateGenericErrorsContent(contentConcatedString)); } }
public override IEnumerable<PvcCore.PvcStream> Execute(IEnumerable<PvcCore.PvcStream> inputStreams) { var resultStreams = new List<PvcStream>(); SwitchParser switchParser = null; if (!String.IsNullOrEmpty(this.commandLineSwitches)) { switchParser = new SwitchParser(); switchParser.Parse(this.commandLineSwitches); } foreach (var inputStream in inputStreams) { var dirName = Path.GetDirectoryName(inputStream.StreamName); var fileName = Path.GetFileNameWithoutExtension(inputStream.StreamName) + ".min" + Path.GetExtension(inputStream.StreamName); var resultName = Path.Combine(dirName, fileName); var fileContent = new StreamReader(inputStream).ReadToEnd(); var minifier = new Minifier(); var sourceStream = new MemoryStream(); var outputWriter = new StreamWriter(sourceStream); if (inputStream.StreamName.EndsWith(".js")) { // Currently AjaxMin only supports JS source maps if (this.generateSourceMaps) { var resultMapName = resultName + ".map"; var utf8 = new UTF8Encoding(false); var mapStream = new MemoryStream(); var mapWriter = new SourcemapStreamWriter(mapStream, utf8); var sourceMap = new V3SourceMap(mapWriter); if (sourceMap != null) { if (switchParser == null) { switchParser = new SwitchParser(); } switchParser.JSSettings.SymbolsMap = sourceMap; switchParser.JSSettings.TermSemicolons = true; sourceMap.StartPackage(resultName, resultMapName); outputWriter.Write(minifier.MinifyJavaScript(fileContent, switchParser.JSSettings)); sourceMap.EndPackage(); sourceMap.EndFile(outputWriter, "\r\n"); sourceMap.Dispose(); mapWriter.Flush(); resultStreams.Add(new PvcStream(() => mapStream).As(resultMapName)); } } else { CodeSettings settings = new CodeSettings(); if (switchParser != null) settings = switchParser.JSSettings; outputWriter.Write(minifier.MinifyJavaScript(fileContent, settings)); } } else { CssSettings settings = new CssSettings(); if (switchParser != null) settings = switchParser.CssSettings; outputWriter.Write(minifier.MinifyStyleSheet(fileContent, settings)); } foreach (var error in minifier.ErrorList) { Console.Error.WriteLine(error.ToString()); } outputWriter.Flush(); resultStreams.Add(new PvcStream(() => sourceStream).As(resultName)); } return resultStreams; }
/// <summary> /// Generate source map then minify file /// </summary> /// <param name="file"></param> /// <param name="minFile"></param> /// <param name="settings"></param> /// <param name="isBundle"></param> private static void MinifyFileWithSourceMap(string file, string minFile, CodeSettings settings, bool isBundle) { var fileName = minFile + ".map"; using (var writer = new StreamWriter(fileName, false, new UTF8Encoding(false))) { using (var map = new V3SourceMap(writer)) { settings.SymbolsMap = map; map.StartPackage(Path.GetFileName(minFile), Path.GetFileName(fileName)); MinifyFile(file, minFile, settings, true, isBundle); map.EndPackage(); } } Console.WriteLine("Source map generated: " + Path.GetFileName(fileName)); }
public override IEnumerable <PvcCore.PvcStream> Execute(IEnumerable <PvcCore.PvcStream> inputStreams) { var resultStreams = new List <PvcStream>(); SwitchParser switchParser = null; if (!String.IsNullOrEmpty(this.commandLineSwitches)) { switchParser = new SwitchParser(); switchParser.Parse(this.commandLineSwitches); } foreach (var inputStream in inputStreams) { var dirName = Path.GetDirectoryName(inputStream.StreamName); var fileName = Path.GetFileNameWithoutExtension(inputStream.StreamName) + ".min" + Path.GetExtension(inputStream.StreamName); var resultName = Path.Combine(dirName, fileName); var fileContent = new StreamReader(inputStream).ReadToEnd(); var minifier = new Minifier(); var sourceStream = new MemoryStream(); var outputWriter = new StreamWriter(sourceStream); if (inputStream.StreamName.EndsWith(".js")) { // Currently AjaxMin only supports JS source maps if (this.generateSourceMaps) { var resultMapName = resultName + ".map"; var utf8 = new UTF8Encoding(false); var mapStream = new MemoryStream(); var mapWriter = new SourcemapStreamWriter(mapStream, utf8); var sourceMap = new V3SourceMap(mapWriter); if (sourceMap != null) { if (switchParser == null) { switchParser = new SwitchParser(); } switchParser.JSSettings.SymbolsMap = sourceMap; switchParser.JSSettings.TermSemicolons = true; sourceMap.StartPackage(resultName, resultMapName); outputWriter.Write(minifier.MinifyJavaScript(fileContent, switchParser.JSSettings)); sourceMap.EndPackage(); sourceMap.EndFile(outputWriter, "\r\n"); sourceMap.Dispose(); mapWriter.Flush(); resultStreams.Add(new PvcStream(() => mapStream).As(resultMapName)); } } else { CodeSettings settings = new CodeSettings(); if (switchParser != null) { settings = switchParser.JSSettings; } outputWriter.Write(minifier.MinifyJavaScript(fileContent, settings)); } } else { CssSettings settings = new CssSettings(); if (switchParser != null) { settings = switchParser.CssSettings; } outputWriter.Write(minifier.MinifyStyleSheet(fileContent, settings)); } foreach (var error in minifier.ErrorList) { Console.Error.WriteLine(error.ToString()); } outputWriter.Flush(); resultStreams.Add(new PvcStream(() => sourceStream).As(resultName)); } return(resultStreams); }