public static async Tasks.Task CompileAsync(CompilerOptions options, Project project) { var tf = new JoinableTaskFactory(Microsoft.VisualStudio.Shell.ThreadHelper.JoinableTaskContext); await tf.SwitchToMainThreadAsync(); if (options == null || project == null || !LessCatalog.Catalog.TryGetValue(project.UniqueName, out ProjectMap map)) { return; } IEnumerable <CompilerOptions> parents = map.LessFiles .Where(l => l.Value.Exists(c => c == options)) .Select(l => l.Key) .Union(new[] { options }) .Distinct(); var sw = new Stopwatch(); sw.Start(); var compilerTaks = new List <Tasks.Task>(); foreach (CompilerOptions parentOptions in parents.Where(p => p.Compile)) { compilerTaks.Add(CompileSingleFileAsync(parentOptions)); } await Tasks.Task.WhenAll(compilerTaks); sw.Stop(); VsHelpers.WriteStatus($"LESS file compiled in {Math.Round(sw.Elapsed.TotalSeconds, 2)} seconds"); }
private static async Tasks.Task <bool> CompileSingleFileAsync(CompilerOptions options) { try { VsHelpers.CheckFileOutOfSourceControl(options.OutputFilePath); if (options.SourceMap) { VsHelpers.CheckFileOutOfSourceControl(options.OutputFilePath + ".map"); } CompilerResult result = await NodeProcess.ExecuteProcess(options); Logger.Log($"{result.Arguments}"); if (result.HasError) { Logger.Log(result.Error); VsHelpers.WriteStatus($"Error compiling LESS file. See Output Window for details"); } else { AddFilesToProject(options); Minify(options); } return(true); } catch (Exception ex) { Logger.Log(ex); VsHelpers.WriteStatus($"Error compiling LESS file. See Output Window for details"); return(false); } }
public static void Minify(CompilerOptions options) { if (!options.Minify || !File.Exists(options.OutputFilePath)) { return; } string cssContent = File.ReadAllText(options.OutputFilePath); var settings = new CssSettings { ColorNames = CssColor.Strict, CommentMode = CssComment.Important }; NUglify.UglifyResult result = Uglify.Css(cssContent, settings); if (result.HasErrors) { return; } string minFilePath = Path.ChangeExtension(options.OutputFilePath, ".min.css"); VsHelpers.CheckFileOutOfSourceControl(minFilePath); File.WriteAllText(minFilePath, result.Code, new UTF8Encoding(true)); VsHelpers.AddNestedFile(options.OutputFilePath, minFilePath); }
private static void AddFilesToProject(CompilerOptions options) { Microsoft.VisualStudio.Shell.ThreadHelper.ThrowIfNotOnUIThread(); ProjectItem item = VsHelpers.DTE.Solution.FindProjectItem(options.InputFilePath); if (item?.ContainingProject != null) { if (options.OutputFilePath == Path.ChangeExtension(options.InputFilePath, ".css")) { VsHelpers.AddNestedFile(options.InputFilePath, options.OutputFilePath); } else { VsHelpers.AddFileToProject(item.ContainingProject, options.OutputFilePath); } string mapFilePath = Path.ChangeExtension(options.OutputFilePath, ".css.map"); if (File.Exists(mapFilePath)) { VsHelpers.AddNestedFile(options.OutputFilePath, mapFilePath); } } }
private async void DocumentSaved(object sender, TextDocumentFileActionEventArgs e) { if (e.FileActionType != FileActionTypes.ContentSavedToDisk || !_project.IsLessCompilationEnabled()) { return; } if (NodeProcess.IsInstalling) { VsHelpers.WriteStatus("The LESS compiler is being installed. Please try again in a few seconds..."); } else if (NodeProcess.IsReadyToExecute()) { CompilerOptions options = await CompilerOptions.Parse(e.FilePath, _view.TextBuffer.CurrentSnapshot.GetText()); if (_view.Properties.TryGetProperty(typeof(LessAdornment), out LessAdornment adornment)) { await adornment.Update(options); } if (options == null || !_project.SupportsCompilation() || !_project.IsLessCompilationEnabled()) { return; } await LessCatalog.UpdateFile(_project, options); if (await LessCatalog.EnsureCatalog(_project)) { await CompilerService.CompileAsync(options, _project); } } }
public static async Task <CompilerOptions> Parse(string lessFilePath, string lessContent = null) { if (!File.Exists(lessFilePath) || ProjectMap.ShouldIgnore(lessFilePath)) { return(null); } lessContent = lessContent ?? await VsHelpers.ReadFileAsync(lessFilePath); var options = new CompilerOptions(lessFilePath); // Compile if (Path.GetFileName(lessFilePath).StartsWith("_", StringComparison.Ordinal) || lessContent.IndexOf("no-compile", StringComparison.OrdinalIgnoreCase) > -1) { options.Compile = false; } // Minify if (lessContent.IndexOf("no-minify", StringComparison.OrdinalIgnoreCase) > -1) { options.Minify = false; } // Arguments Match argsMatch = _regex.Match(lessContent, 0, Math.Min(500, lessContent.Length)); if (argsMatch.Success) { string inFile = Path.GetFileName(options.InputFilePath); options.Arguments = $"\"{inFile}\" {argsMatch.Groups["args"].Value.TrimEnd('*', '/').Trim()}"; } // Source map options.SourceMap = options.Arguments.IndexOf("--source-map", StringComparison.OrdinalIgnoreCase) > -1; // OutputFileName Match outMatch = _outFile.Match(options.Arguments); if (argsMatch.Success && outMatch.Success) { string relative = outMatch.Groups["out"].Value.Replace("/", "\\"); options.OutputFilePath = Path.Combine(Path.GetDirectoryName(lessFilePath), relative); } else { options.OutputFilePath = Path.ChangeExtension(lessFilePath, ".css"); if (argsMatch.Success) { options.Arguments += $" \"{Path.GetFileName(options.OutputFilePath)}\""; } } // Trim the argument list options.Arguments = options.Arguments.Trim(); return(options); }
private async Task AddFile(string lessFilePath) { if (LessFiles.Keys.Any(c => c.InputFilePath == lessFilePath)) { return; } string lessContent = await VsHelpers.ReadFileAsync(lessFilePath); CompilerOptions options = await CompilerOptions.Parse(lessFilePath, lessContent); LessFiles.Add(options, new List <CompilerOptions>()); await AddOption(options, lessContent); }
public static async Tasks.Task CompileProjectAsync(Project project) { if (project == null || !LessCatalog.Catalog.TryGetValue(project.UniqueName, out ProjectMap map)) { return; } var compileTasks = new List <Tasks.Task>(); foreach (CompilerOptions option in map.LessFiles.Keys) { if (option.Compile) { compileTasks.Add(CompileSingleFile(option)); } } await Tasks.Task.WhenAll(compileTasks); VsHelpers.WriteStatus($"LESS files in solution compiled"); }
private static void AddFilesToProject(CompilerOptions options) { ProjectItem item = VsHelpers.DTE.Solution.FindProjectItem(options.InputFilePath); if (item?.ContainingProject != null) { if (options.OutputFilePath == Path.ChangeExtension(options.InputFilePath, ".css")) { VsHelpers.AddNestedFile(options.InputFilePath, options.OutputFilePath); } else { VsHelpers.AddFileToProject(item.ContainingProject, options.OutputFilePath); } string mapFilePath = Path.ChangeExtension(options.OutputFilePath, ".css.map"); if (File.Exists(mapFilePath)) { VsHelpers.AddNestedFile(options.OutputFilePath, mapFilePath); } } }
public static async Tasks.Task CompileProjectAsync(Project project) { var tf = new JoinableTaskFactory(Microsoft.VisualStudio.Shell.ThreadHelper.JoinableTaskContext); await tf.SwitchToMainThreadAsync(); if (project == null || !LessCatalog.Catalog.TryGetValue(project.UniqueName, out ProjectMap map)) { return; } var compileTasks = new List <Tasks.Task>(); foreach (CompilerOptions option in map.LessFiles.Keys) { if (option.Compile) { compileTasks.Add(CompileSingleFileAsync(option)); } } await Tasks.Task.WhenAll(compileTasks); VsHelpers.WriteStatus($"LESS files in solution compiled"); }