private void DetectAdditionalSourceFilesJavaScript(string fileName, bool clear = true) { if (clear) { AdditionalSourceFiles.Clear(); } if (!File.Exists(fileName)) { return; } string filePath = Path.GetDirectoryName(fileName); using (var reader = new StreamReader(fileName)) { while (!reader.EndOfStream) { string line = reader.ReadLine(); var match = Regex.Match(line, @"^\s*import\s+.*?([""'])(.+?)\1"); if (match.Success) { string file = match.Groups[2].Value.Trim(); if (Path.GetExtension(file) != ".js") { file += ".js"; } file = file.Replace("/", "\\"); file = Path.Combine(filePath, file); if (AdditionalSourceFiles.Add(file)) { DetectAdditionalSourceFilesJavaScript(file, clear: false); } } } } }
private void DetectAdditionalSourceFilesCss(string fileName, bool clear = true) { if (clear) { AdditionalSourceFiles.Clear(); } if (!File.Exists(fileName)) { return; } string filePath = Path.GetDirectoryName(fileName); using (var reader = new StreamReader(fileName)) { while (!reader.EndOfStream) { string line = reader.ReadLine(); var match = Regex.Match(line, @"^\s*@import\s+url\(\s*([""']?)(.+?)\1\s*\)"); if (!match.Success) { match = Regex.Match(line, @"^\s*@import\s+(""|')(.+?)\1"); } if (match.Success) { string file = match.Groups[2].Value.Trim(); if (!file.StartsWith("http://") && !file.StartsWith("https://")) { file = file.Replace("/", "\\"); file = Path.Combine(filePath, file); if (AdditionalSourceFiles.Add(file)) { DetectAdditionalSourceFilesCss(file, clear: false); } } } } } }
private async Task CompileJavaScript(bool force) { string srcFileName = Path.GetFileName(fullFileName); string bundleFileName = Path.GetFileNameWithoutExtension(fullFileName) + ".bundle.js"; string minFileName = Path.GetFileNameWithoutExtension(fullFileName) + ".min.js"; string onlyMinFileName = minFileName; string banner = ""; string iifeParams = ""; string iifeArgs = ""; bool noIife = false; bool mangle = true; bool keepFargs = false; bool keepFnames = false; string buildDir = ""; using (var reader = new StreamReader(fullFileName)) { int lineNumber = 0; while (!reader.EndOfStream && lineNumber < 20) { string line = reader.ReadLine(); lineNumber++; var match = Regex.Match(line, @"^\s*(/\*!.*\*/)"); if (lineNumber == 1 && match.Success) { string comment = match.Groups[1].Value; banner = " --banner \"" + comment + "\""; } match = Regex.Match(line, @"^\s*/\*\s*iife-params\((.*)\)\s*\*/", RegexOptions.IgnoreCase); if (match.Success) { iifeParams = match.Groups[1].Value; } match = Regex.Match(line, @"^\s*/\*\s*iife-args\((.*)\)\s*\*/", RegexOptions.IgnoreCase); if (match.Success) { iifeArgs = match.Groups[1].Value; } match = Regex.Match(line, @"^\s*/\*\s*no-iife\s*\*/", RegexOptions.IgnoreCase); if (match.Success) { noIife = true; } match = Regex.Match(line, @"^\s*/\*\s*no-mangle\s*\*/", RegexOptions.IgnoreCase); if (match.Success) { mangle = false; } match = Regex.Match(line, @"^\s*/\*\s*keep-fargs\s*\*/", RegexOptions.IgnoreCase); if (match.Success) { keepFargs = true; } match = Regex.Match(line, @"^\s*/\*\s*keep-fnames\s*\*/", RegexOptions.IgnoreCase); if (match.Success) { keepFnames = true; } match = Regex.Match(line, @"^\s*/\*\s*build-dir\((.*)\)\s*\*/", RegexOptions.IgnoreCase); if (match.Success && buildDir == "") { buildDir = match.Groups[1].Value.Trim().Replace('/', '\\'); buildDir = Regex.Replace(buildDir, "\\+", "\\"); if (buildDir != "" && !buildDir.EndsWith("\\")) { buildDir += "\\"; } if (buildDir != "") { bundleFileName = Path.Combine(buildDir, bundleFileName); minFileName = Path.Combine(buildDir, minFileName); // onlyMinFileName is not changed Directory.CreateDirectory(Path.Combine(fileDir, buildDir)); } } } } fullOutputFileName = minFileName; if (!force && AreFilesUpToDate(minFileName, minFileName + ".map")) { SetCompressedResultSize(Path.Combine(fileDir, minFileName)); return; } if (!force) { Status = null; } ClearFileTimes(); SaveResultFileTime(minFileName); SaveResultFileTime(minFileName + ".map"); LastLog = ""; if (AdditionalSourceFiles.Any()) { Environment.SetEnvironmentVariable("NO_COLOR", "1", EnvironmentVariableTarget.Process); string formatArg = ""; if (!noIife) { formatArg = " -f iife"; } await ExecAsync( "rollup \"" + srcFileName + "\" -o \"" + bundleFileName + "\"" + formatArg + " -m -p rollup-plugin-sourcemaps" + banner, fileDir, utf8 : true); if ((iifeParams != "" || iifeArgs != "") && File.Exists(Path.Combine(fileDir, bundleFileName))) { string[] lines = File.ReadAllLines(Path.Combine(fileDir, bundleFileName)); for (int i = 0; i < 3; i++) { if (Regex.IsMatch(lines[i], @"^\(function \(\) \{\s*$")) { lines[i] = lines[i].Replace("()", "(" + iifeParams + ")"); break; } } for (int i = lines.Length - 1; i > lines.Length - 4; i--) { if (Regex.IsMatch(lines[i], @"^\}\(\)\);\s*$") || Regex.IsMatch(lines[i], @"^\}\)\(\);\s*$")) { lines[i] = lines[i].Replace("()", "(" + iifeArgs + ")"); break; } } File.WriteAllLines(Path.Combine(fileDir, bundleFileName), lines); } } else { bundleFileName = srcFileName; } if (needsRecompile) { return; // Abort this run and restart } if (Status != false) { string mangleParam = mangle ? " --mangle" : ""; string mapParam = " --source-map \"url='" + onlyMinFileName.Replace('\\', '/') + ".map'\""; if (File.Exists(Path.Combine(fileDir, bundleFileName) + ".map")) { // The url part must refer to the file without the build directory because // both files (min.js and map) will be in the same directory. mapParam = " --source-map \"content='" + bundleFileName.Replace('\\', '/') + ".map',url='" + onlyMinFileName.Replace('\\', '/') + ".map'\""; } string addParams = ""; if (keepFargs) { addParams += " --keep-fargs"; } if (keepFnames) { addParams += " --keep-fnames"; } await ExecAsync( "uglifyjs " + bundleFileName + " --compress" + mangleParam + " --output \"" + minFileName + "\" --comments \"/^!/\"" + mapParam + addParams, fileDir, utf8 : true); PostprocessMapFile(minFileName + ".map"); } if (needsRecompile) { return; // Abort this run and restart } if (Status != false) { RestoreResultFileTime(minFileName); RestoreResultFileTime(minFileName + ".map"); if (!Project.KeepIntermediaryFiles && !Project.KeepUnminifiedFiles) { if (bundleFileName != srcFileName) { File.Delete(Path.Combine(fileDir, bundleFileName)); File.Delete(Path.Combine(fileDir, bundleFileName + ".map")); bundleFileName = ""; } } LastLog += Environment.NewLine + "Compiled files:" + Environment.NewLine; if (!string.IsNullOrEmpty(bundleFileName)) { LastLog += "- " + bundleFileName + Environment.NewLine; } LastLog += "- " + minFileName + Environment.NewLine; if (isAnyFileModified) { LastCompileTime = DateTime.UtcNow; } else { LastLog += "Note: File content has not changed to previous build." + Environment.NewLine; } SetCompressedResultSize(Path.Combine(fileDir, minFileName)); } }
private void DetectAdditionalSourceFilesScss(string fileName, bool clear = true) { if (clear) { AdditionalSourceFiles.Clear(); } if (!File.Exists(fileName)) { return; } string filePath = Path.GetDirectoryName(fileName); using (var reader = new StreamReader(fileName)) { while (!reader.EndOfStream) { string line = reader.ReadLine(); var match = Regex.Match(line, @"^\s*@(?:forward|import|use)\s+(?:(""|')(.+?)\1\s*,?\s*)+"); if (match.Success) { foreach (Capture capture in match.Groups[2].Captures) { string file = capture.Value.Trim(); file = file.Replace("/", "\\"); file = Path.Combine(filePath, file); switch (Path.GetExtension(file)) { case ".css": case ".scss": case ".sass": if (AdditionalSourceFiles.Add(file)) { DetectAdditionalSourceFilesScss(file, clear: false); } break; default: // Add all possible variants as they may exist or change later if (AdditionalSourceFiles.Add(file + ".css")) { DetectAdditionalSourceFilesScss(file + ".css", clear: false); } if (AdditionalSourceFiles.Add(file + ".scss")) { DetectAdditionalSourceFilesScss(file + ".scss", clear: false); } if (AdditionalSourceFiles.Add(file + ".sass")) { DetectAdditionalSourceFilesScss(file + ".sass", clear: false); } string partialFile = Path.Combine(Path.GetDirectoryName(file), "_" + Path.GetFileName(file)); if (AdditionalSourceFiles.Add(partialFile + ".css")) { DetectAdditionalSourceFilesScss(partialFile + ".css", clear: false); } if (AdditionalSourceFiles.Add(partialFile + ".scss")) { DetectAdditionalSourceFilesScss(partialFile + ".scss", clear: false); } if (AdditionalSourceFiles.Add(partialFile + ".sass")) { DetectAdditionalSourceFilesScss(partialFile + ".sass", clear: false); } break; } } } } } }