/// <summary> /// Executes the processor on the specified configuration. /// </summary> public Task ExecuteAsync(IAssetContext context) { var content = new Dictionary <string, byte[]>(); var env = (IWebHostEnvironment)context.HttpContext.RequestServices.GetService(typeof(IWebHostEnvironment)); IFileProvider fileProvider = context.Asset.GetFileProvider(env); foreach (string route in context.Content.Keys) { IFileInfo file = fileProvider.GetFileInfo(route); var settings = new ScssOptions { InputFile = file.PhysicalPath }; if (options != null) { settings.IncludePaths.AddRange(options.IncludePaths); settings.GenerateSourceMap = options.GenerateSourceMap; settings.Indent = options.Indent; settings.IsIndentedSyntaxSource = options.IsIndentedSyntaxSource; settings.Linefeed = options.Linefeed; settings.OmitSourceMapUrl = options.OmitSourceMapUrl; settings.SourceComments = options.SourceComments; settings.SourceMapContents = options.SourceMapContents; settings.SourceMapEmbed = options.SourceMapEmbed; settings.SourceMapRoot = options.SourceMapRoot; } ScssResult result = Scss.ConvertToCss(context.Content[route].AsString(), settings); content[route] = result.Css.AsByteArray(); } context.Content = content; return(Task.CompletedTask); }
/// <summary> /// Executes the processor on the specified configuration. /// </summary> public Task ExecuteAsync(IAssetContext context) { var content = new Dictionary <string, byte[]>(); var env = (IWebHostEnvironment)context.HttpContext.RequestServices.GetService(typeof(IWebHostEnvironment)); IFileProvider fileProvider = context.Asset.GetFileProvider(env); foreach (string route in context.Content.Keys) { IFileInfo file = fileProvider.GetFileInfo(route); var settings = new ScssOptions { InputFile = file.PhysicalPath }; settings.TryImport = (string file, string parentPath, out string scss, out string map) => { // System.Console.WriteLine("File to import is " + file); // System.Console.WriteLine("Parent Path is " + parentPath); var basePath = "/styles/"; var path = GetFilePath(file, parentPath); var f = fileProvider.GetFileInfo(basePath + path + ".scss"); using (var reader = new System.IO.StreamReader(f.CreateReadStream(), System.Text.Encoding.UTF8)) { string value = reader.ReadToEnd(); // System.Console.WriteLine("SCSS is " + value); scss = value; map = null; } return(true); }; System.Console.WriteLine("FP " + fileProvider.GetType().Name); System.Console.WriteLine("Route is " + route); System.Console.WriteLine("File is " + file.PhysicalPath); System.Console.WriteLine("Settings: " + settings.IncludePaths); ScssResult result = Scss.ConvertToCss(context.Content[route].AsString(), settings); content[route] = result.Css.AsByteArray(); } context.Content = content; foreach (string key in context.Content.Keys) { IFileInfo input = fileProvider.GetFileInfo(key); IFileInfo output = fileProvider.GetFileInfo(context.Asset.Route); System.Console.WriteLine("Input is " + input.Name + " + " + input.PhysicalPath); System.Console.WriteLine("Output is " + output.Name + " + " + output.PhysicalPath); string absoluteOutputPath = new System.IO.FileInfo(output.PhysicalPath).FullName; System.Console.WriteLine("Output actual path is " + absoluteOutputPath); } return(Task.CompletedTask); }
protected override byte[] GenerateCode(string inputFileName, string inputFileContent) { var options = new ScssOptions(); ScssResult result = Scss.ConvertFileToCss(inputFileName, options); UglifyResult minified = Uglify.Css(result.Css); return(Encoding.UTF8.GetBytes(minified.Code)); }
protected override async Task <IEnumerable <IDocument> > ExecuteAsync(IDocument input, IExecutionContext context) { context.LogDebug($"Processing Sass for {input.ToSafeDisplayString()}"); FilePath inputPath = await _inputPath.GetValueAsync(input, context); if (inputPath?.IsAbsolute != true) { inputPath = context.FileSystem.GetInputFile(new FilePath(Path.GetRandomFileName())).Path; context.LogWarning($"No input path found for document {input.ToSafeDisplayString()}, using {inputPath.FileName.FullPath}"); } string content = await input.GetStringAsync(); // Sass conversion FileImporter importer = new FileImporter(context.FileSystem, _importPathFunc); ScssOptions options = new ScssOptions { OutputStyle = _outputStyle, GenerateSourceMap = _generateSourceMap, SourceComments = _includeSourceComments, InputFile = inputPath.FullPath, TryImport = importer.TryImport }; IEnumerable <string> includePaths = _includePaths .Where(x => x != null) .Select(x => x.IsAbsolute ? x.FullPath : context.FileSystem.GetContainingInputPath(x)?.Combine(x)?.FullPath) .Where(x => x != null); options.IncludePaths.AddRange(includePaths); ScssResult result = Scss.ConvertToCss(content, options); // Process the result DirectoryPath relativeDirectory = context.FileSystem.GetContainingInputPath(inputPath); FilePath relativePath = relativeDirectory?.GetRelativePath(inputPath) ?? inputPath.FileName; FilePath cssPath = relativePath.ChangeExtension("css"); IDocument cssDocument = input.Clone( cssPath, await context.GetContentProviderAsync(result.Css ?? string.Empty)); // Generate a source map if requested if (_generateSourceMap && result.SourceMap != null) { FilePath sourceMapPath = relativePath.ChangeExtension("map"); IDocument sourceMapDocument = input.Clone( sourceMapPath, await context.GetContentProviderAsync(result.SourceMap)); return(new[] { cssDocument, sourceMapDocument }); } return(cssDocument.Yield()); }
public override ContentResult TryProcess(ContentObject file) { var contentType = file.ContentType; // This plugin is only working on scss files if (contentType != ScssType) { return(ContentResult.None); } if (file.Content == null) { file.Content = file.SourceFile.ReadAllText(); } var content = file.Content; var scss = (ScssObject)Site["scss"]; var options = new ScssOptions(); foreach (var pathObj in scss.Includes) { var path = pathObj as string; if (path != null) { // TODO: rewrite for zio //options.IncludePaths.Add((UPath)path); } } var result = SharpScss.Scss.ConvertToCss(content, options); file.Content = result.Css; file.ChangeContentType(ContentType.Css); if (result.IncludedFiles != null) { foreach (var includeFile in result.IncludedFiles) { // TODO: rewrite for zio //file.Dependencies.Add(new FileContentDependency(new FileEntry(Site.FileSystem, (UPath)includeFile))); } } return(ContentResult.Continue); }
private static void AddFileToProject(FileInfo source, FileInfo target, ScssOptions options) { try { if (options.IsDebugLoggingEnabled) { Logger.Log(string.Format("Nesting {0} under {1}", target.Name, source.Name)); } var buildAction = options.IncludeCssInProjectOutput ? InteropHelper.BuildActionType.Content : InteropHelper.BuildActionType.None; InteropHelper.AddNestedFile(SassyStudioPackage.Instance.DTE, source.FullName, target.FullName, buildAction); } catch (Exception ex) { Logger.Log(ex, string.Format("Failed to include {0} in project under {1}", target.Name, source.Name)); } }
/// <summary> /// Executes the processor on the specified configuration. /// </summary> public Task ExecuteAsync(IAssetContext context) { var content = new Dictionary<string, byte[]>(); var env = (IWebHostEnvironment)context.HttpContext.RequestServices.GetService(typeof(IWebHostEnvironment)); IFileProvider fileProvider = context.Asset.GetFileProvider(env); foreach (string route in context.Content.Keys) { IFileInfo file = fileProvider.GetFileInfo(route); var settings = new ScssOptions { InputFile = file.PhysicalPath }; ScssResult result = Scss.ConvertToCss(context.Content[route].AsString(), settings); content[route] = result.Css.AsByteArray(); } context.Content = content; return Task.CompletedTask; }
public void Process() { Console.WriteLine("Sass"); Colorizer.WriteLine($" Output Style: [DarkCyan!{appSettings.ScssOutput}]"); // get files var inFiles = util.GetFiles("scss", "sass"); Colorizer.WriteLine($" Processing [White!{inFiles.Count}] files..."); foreach (var inFile in inFiles) { if (appSettings.Verbose) { Colorizer.WriteLine($" [DarkGray!{inFile.FullName.Replace(appSettings.Input, ".")}]"); } try { var outFile = new FileInfo(inFile.FullName .Replace(appSettings.Input, appSettings.Output) .Replace(".scss", ".css")); // preprocess var options = new ScssOptions { InputFile = inFile.FullName, OutputFile = outFile.FullName, OutputStyle = appSettings.ScssOutput, }; var result = Scss.ConvertFileToCss(inFile.FullName, options); // save result outFile.Directory?.Create(); File.WriteAllText(outFile.FullName, result.Css); } catch (Exception ex) { throw util.ProcessingException(inFile, ex); } } }
private async System.Threading.Tasks.Task TranspileAsync(string filePath) { await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); DTE2 dte = await AsyncServiceProvider.GlobalProvider.GetServiceAsync <DTE, DTE2>(); var options = new ScssOptions(); options.IncludePaths.Add(Path.GetDirectoryName(filePath)); ScssResult result = Scss.ConvertToCss(_doc.TextBuffer.CurrentSnapshot.GetText(), options); var cssPath = Path.ChangeExtension(filePath, ".css"); dte.SourceControl.CheckOutItemSafely(cssPath); using (var writer = new StreamWriter(cssPath)) { await writer.WriteAsync(result.Css); } ProjectItem scssItem = dte.Solution.FindProjectItem(filePath); ProjectItem cssItem = dte.Solution.FindProjectItem(cssPath); if (cssItem != null || scssItem.TryAddNestedFile(cssPath, out cssItem)) { UglifyResult minified = Uglify.Css(result.Css); var minPath = Path.ChangeExtension(cssPath, ".min.css"); dte.SourceControl.CheckOutItemSafely(minPath); using (var writer = new StreamWriter(minPath)) { await writer.WriteAsync(minified.Code); } cssItem.TryAddNestedFile(minPath, out _); } }
public override ContentResult TryProcessContent(ContentObject file, ContentProcessingStage stage) { var contentType = file.ContentType; // This plugin is only working on scss files if (contentType != ScssType) { return(ContentResult.None); } if (file.Content == null) { file.Content = file.SourceFile.ReadAllText(); } var content = file.Content; var options = new ScssOptions(); options.InputFile = (string)file.Path; var includePaths = new List <DirectoryEntry>(); foreach (var pathObj in Plugin.Includes) { var path = pathObj as string; if (path != null && UPath.TryParse(path, out var validPath) && Site.MetaFileSystem.DirectoryExists(validPath)) { includePaths.Add(new DirectoryEntry(Site.MetaFileSystem, validPath)); } else { Site.Error($"Invalid folder path `{pathObj}` found in site.scss.includes."); } } var tempIncludePaths = new List <DirectoryEntry>(); var extensions = new string[] { ".scss", ".sass", ".css" }; var includedFiles = new List <FileEntry>(); options.TryImport = (ref string file, string parentpath, out string scss, out string map) => { scss = null; map = null; // From: https://sass-lang.com/documentation/at-rules/import#load-paths // Imports will always be resolved relative to the current file first, though. // Load paths will only be used if no relative file exists that matches the import. // This ensures that you can’t accidentally mess up your relative imports when you add a new library. tempIncludePaths.Clear(); UPath filePath = (UPath)file; var directoryName = ((UPath)parentpath).GetDirectory(); if (!directoryName.IsNull && directoryName.IsAbsolute) { DirectoryEntry localDirEntry = null; if (Site.FileSystem.DirectoryExists(directoryName)) { localDirEntry = new DirectoryEntry(Site.FileSystem, directoryName); if (!tempIncludePaths.Contains(localDirEntry)) { tempIncludePaths.Add(localDirEntry); } } if (Site.MetaFileSystem.DirectoryExists(directoryName)) { localDirEntry = new DirectoryEntry(Site.MetaFileSystem, directoryName); if (!tempIncludePaths.Contains(localDirEntry)) { tempIncludePaths.Add(localDirEntry); } } } tempIncludePaths.AddRange(includePaths); // From libsass, order for ambiguous import: // (1) filename as given // (2) underscore + given // (3) underscore + given + extension // (4) given + extension // (5) given + _index.scss // (6) given + _index.sass var ufile = (UPath)file; var relativeFolder = ufile.GetDirectory(); var filename = ufile.GetName(); bool Resolve(FileEntry entry, out string scss, out string file) { scss = null; file = null; if (entry.Exists) { scss = entry.ReadAllText(); file = (string)entry.Path; includedFiles.Add(entry); return(true); } return(false); } foreach (var dirEntry in tempIncludePaths) { var rootFolder = dirEntry.Path / relativeFolder; // (1) filename as given if (Resolve(new FileEntry(dirEntry.FileSystem, rootFolder / filename), out scss, out file)) { return(true); } // (2) underscore + given if (Resolve(new FileEntry(dirEntry.FileSystem, rootFolder / $"_{filename}"), out scss, out file)) { return(true); } // (3) underscore + given + extension foreach (var extension in extensions) { if (Resolve(new FileEntry(dirEntry.FileSystem, rootFolder / $"_{filename}{extension}"), out scss, out file)) { return(true); } } // (4) given + extension foreach (var extension in extensions) { if (Resolve(new FileEntry(dirEntry.FileSystem, rootFolder / $"{filename}{extension}"), out scss, out file)) { return(true); } } // (5) given + _index.scss if (Resolve(new FileEntry(dirEntry.FileSystem, rootFolder / $"{filename}" / "_index.scss"), out scss, out file)) { return(true); } // (6) given + _index.sass if (Resolve(new FileEntry(dirEntry.FileSystem, rootFolder / $"{filename}" / "_index.sass"), out scss, out file)) { return(true); } } return(false); }; var result = SharpScss.Scss.ConvertToCss(content, options); file.Content = result.Css; file.ChangeContentType(ContentType.Css); foreach (var includeFile in includedFiles) { file.Dependencies.Add(new FileContentDependency(includeFile)); } return(ContentResult.Continue); }
public SassDocumentCompiler(ScssOptions options) { Options = options; }
private static void AddFileToProject(FileInfo source, FileInfo target, ScssOptions options) { try { if (options.IsDebugLoggingEnabled) Logger.Log(string.Format("Nesting {0} under {1}", target.Name, source.Name)); var buildAction = options.IncludeCssInProjectOutput ? InteropHelper.BuildActionType.Content : InteropHelper.BuildActionType.None; InteropHelper.AddNestedFile(SassyStudioPackage.Instance.DTE, source.FullName, target.FullName, buildAction); } catch (Exception ex) { Logger.Log(ex, string.Format("Failed to include {0} in project under {1}", target.Name, source.Name)); } }
/// <summary> /// Compile a SCSS file or files into CSS. /// </summary> /// <param name="scssInputPath">Web path to the scss input file (e.g. "/scss/application.scss").</param> /// <param name="outputPath">Web path to the CSS output file (e.g. "/stylesheets/application.css").</param> /// <param name="debugMode">Set to true for expanded output with source maps, false for compressed production CSS only</param> /// <param name="force">Force a rebuild</param> /// <returns>True if successful, false if an error occurred</returns> public static void BuildScss(this string scssInputPath, string outputPath, bool debugMode = false, bool force = false) { var process = force; Debug.WriteLine(""); Debug.WriteLine("LibSass result (" + (debugMode ? "debug" : "release") + " mode):"); Debug.WriteLine("------------------------------"); #region Determine if at least one file has been modified if (force) { Debug.WriteLine("FORCED REBUILD MODE"); } else { if (!FileExists(outputPath)) { Debug.WriteLine("CSS file is missing, will recompile..."); process = true; } else { if (debugMode && !FileExists(outputPath + ".map")) { Debug.WriteLine("Debug mode and CSS Map file is missing, will recompile..."); process = true; } else { if (HttpContext.Current.Application.KeyExists(ConvertFilePathToKey(scssInputPath))) { var files = (ArrayList)HttpContext.Current.Application[ConvertFilePathToKey(scssInputPath)]; if (files.Count > 0) { foreach (string file in files) { var segments = file.Split('|'); Debug.Write(GetFilename(segments[0]) + "... "); if (segments.Length == 2) { FileInfo fileInfo = new FileInfo(MapPath(segments[0])); DateTime lastModified = fileInfo.LastWriteTime; if (segments[1] != lastModified.DateFormat(DateFormats.Rss)) { process = true; Debug.WriteLine(" modified, will recompile..."); break; } else { Debug.WriteLine(" unchanged"); } } else { process = true; Debug.WriteLine(" has no previous timestamp, will recompile..."); break; } } } else { process = true; Debug.WriteLine("No files list is present, will recompile..."); } } else { process = true; Debug.WriteLine("Cannot determine prior build timestamps, will recompile..."); } } } } #endregion #region No state or file(s) modified, process... if (process == true) { var debugOptions = new ScssOptions { OutputStyle = ScssOutputStyle.Expanded, SourceComments = true, GenerateSourceMap = true, OutputFile = MapPath(outputPath) }; var releaseOptions = new ScssOptions { OutputStyle = ScssOutputStyle.Compressed, SourceComments = false, GenerateSourceMap = false, OutputFile = MapPath(outputPath) }; try { ScssResult css; var options = debugOptions; if (debugMode == false) { options = releaseOptions; } css = Scss.ConvertFileToCss(MapPath(scssInputPath), options); if (outputPath.FileExists()) { DeleteFiles(outputPath); Debug.WriteLine("Deleted " + outputPath); } if ((outputPath + ".map").FileExists()) { DeleteFiles(outputPath + ".map"); Debug.WriteLine("Deleted " + outputPath + ".map"); } WriteFile(outputPath, css.Css); Debug.WriteLine("Generated " + outputPath); if (options.GenerateSourceMap == true) { WriteFile(outputPath + ".map", css.SourceMap); Debug.WriteLine("Generated " + outputPath + ".map"); } if (css.IncludedFiles.Count > 0) { ArrayList fileList = new ArrayList(); foreach (var file in css.IncludedFiles) { FileInfo fileInfo = new FileInfo(MapPath(file)); DateTime lastModified = fileInfo.LastWriteTime; var item = file + "|" + lastModified.DateFormat(DateFormats.Rss); fileList.Add(item); Debug.WriteLine(item); } HttpContext.Current.Application[ConvertFilePathToKey(scssInputPath)] = fileList; Debug.WriteLine("Saved state for " + fileList.Count + " files"); Debug.WriteLine(""); } else { Debug.WriteLine("No files to process, aborting"); Debug.WriteLine(""); } } catch (ScssException e) { Debug.WriteLine("LibSass error: " + e.Message); Debug.WriteLine(""); } } else { Debug.WriteLine("File(s) not modified, aborting"); Debug.WriteLine(""); } #endregion }
public LibSassNetDocumentCompiler(ScssOptions options) { Options = options; }
/// <inheritdoc /> public IEnumerable <IDocument> Execute(IReadOnlyList <IDocument> inputs, IExecutionContext context) { return(inputs .AsParallel() .SelectMany(context, input => { Trace.Verbose($"Processing Sass for {input.SourceString()}"); FilePath inputPath = _inputPath.Invoke <FilePath>(input, context); if (inputPath?.IsAbsolute != true) { inputPath = context.FileSystem.GetInputFile(new FilePath(Path.GetRandomFileName())).Path; Trace.Warning($"No input path found for document {input.SourceString()}, using {inputPath.FileName.FullPath}"); } string content = input.Content; // Sass conversion FileImporter importer = new FileImporter(context.FileSystem, _importPathFunc); ScssOptions options = new ScssOptions { OutputStyle = _outputStyle, GenerateSourceMap = _generateSourceMap, SourceComments = _includeSourceComments, InputFile = inputPath.FullPath, TryImport = importer.TryImport }; options.IncludePaths.AddRange( _includePaths .Where(x => x != null) .Select(x => x.IsAbsolute ? x.FullPath : context.FileSystem.GetContainingInputPath(x)?.Combine(x)?.FullPath) .Where(x => x != null)); ScssResult result = Scss.ConvertToCss(content, options); // Process the result DirectoryPath relativeDirectory = context.FileSystem.GetContainingInputPath(inputPath); FilePath relativePath = relativeDirectory?.GetRelativePath(inputPath) ?? inputPath.FileName; FilePath cssPath = relativePath.ChangeExtension("css"); IDocument cssDocument = context.GetDocument( input, context.GetContentStream(result.Css ?? string.Empty), new MetadataItems { { Keys.RelativeFilePath, cssPath }, { Keys.WritePath, cssPath } }); IDocument sourceMapDocument = null; if (_generateSourceMap && result.SourceMap != null) { FilePath sourceMapPath = relativePath.ChangeExtension("map"); sourceMapDocument = context.GetDocument( input, context.GetContentStream(result.SourceMap), new MetadataItems { { Keys.RelativeFilePath, sourceMapPath }, { Keys.WritePath, sourceMapPath } }); } return new[] { cssDocument, sourceMapDocument }; }) .Where(x => x != null)); }
private static void AddFileToProject(FileInfo source, FileInfo target, ScssOptions options) { var buildAction = options.IncludeCssInProjectOutput ? InteropHelper.BuildActionType.Content : InteropHelper.BuildActionType.None; InteropHelper.AddNestedFile(SassyStudioPackage.Instance.DTE, source.FullName, target.FullName, buildAction); }