.NET wrapper around the Dart Sass with the ability to support a virtual file system. Unlike other .NET wrappers around the Dart Sass (e.g. Citizen17.DartSass and AspNetCore.SassCompiler), this library is not based on the Dart runtime, but on the version for JavaScript.
This library can be installed through NuGet - https://nuget.org/packages/DartSassHost. Since the original library is written in JavaScript, you will need a JS engine to run it. As a JS engine is used the JavaScript Engine Switcher library. For correct working, you need to install one of the following NuGet packages:
- JavaScriptEngineSwitcher.ChakraCore
- JavaScriptEngineSwitcher.V8
- JavaScriptEngineSwitcher.Msie (only in the Chakra “Edge” JsRT mode)
After installing the packages, you will need to register the default JS engine.
In addition, if your project uses a relatively small amount of Sass or SCSS code, then you can use the JavaScriptEngineSwitcher.Jint package as a JS engine.
When we create an instance of the SassCompiler
class by using the constructor without parameters:
var sassCompiler = new SassCompiler();
Then we always use a JS engine registered by default. In fact, a constructor without parameters is equivalent to the following code:
var sassCompiler = new SassCompiler(JsEngineSwitcher.Current.CreateDefaultEngine);
This approach is great for web applications, but in some cases the usage of JS engine registration at global level will be redundant. It is for such cases that the possibility of passing of the JS engine factory to the constructor is provided:
var sassCompiler = new SassCompiler(new ChakraCoreJsEngineFactory());
You can also use a delegate that creates an instance of the JS engine:
var sassCompiler = new SassCompiler(() => new ChakraCoreJsEngine());
The main feature of this library is ability to support a virtual file system. You can pass an file manager through constructor of the SassCompiler
class:
var sassCompiler = new SassCompiler(CustomFileManager());
Any public class, that implements an IFileManager
interface, can be used as a file manager. A good example of implementing a custom file manager, which provides access to the virtual file system, is the VirtualFileManager
class from the BundleTransformer.SassAndScss package.
It should also be noted, that this library does not write the result of compilation to disk. Compile
and CompileFile
methods of the SassCompiler
class return the result of compilation in the form of an instance of the CompilationResult
class. Consider in detail properties of the CompilationResult
class:
Property name | Data type | Description |
---|---|---|
CompiledContent |
String |
CSS code. |
IncludedFilePaths |
IList<string> |
List of included files. |
SourceMap |
String |
Source map. |
Warnings |
IList<ProblemInfo> |
List of the warnings. |
Consider a simple example of usage of the Compile
method:
using System;
using DartSassHost;
using DartSassHost.Helpers;
using JavaScriptEngineSwitcher.ChakraCore;
namespace DartSassHost.Example.ConsoleApplication
{
class Program
{
static void Main(string[] args)
{
const string inputContent = @"$font-stack: Helvetica, sans-serif;
$primary-color: #333;
body {
font: 100% $font-stack;
color: $primary-color;
}";
var options = new CompilationOptions { SourceMap = true };
try
{
using (var sassCompiler = new SassCompiler(new ChakraCoreJsEngineFactory(), options))
{
CompilationResult result = sassCompiler.Compile(inputContent, "input.scss",
"output.css", "output.css.map", options);
Console.WriteLine("Compiled content:{1}{1}{0}{1}", result.CompiledContent,
Environment.NewLine);
Console.WriteLine("Source map:{1}{1}{0}{1}", result.SourceMap, Environment.NewLine);
Console.WriteLine("Included file paths: {0}",
string.Join(", ", result.IncludedFilePaths));
}
}
catch (SassCompilerLoadException e)
{
Console.WriteLine("During loading of Sass compiler an error occurred. See details:");
Console.WriteLine();
Console.WriteLine(SassErrorHelpers.GenerateErrorDetails(e));
}
catch (SassCompilationException e)
{
Console.WriteLine("During compilation of SCSS code an error occurred. See details:");
Console.WriteLine();
Console.WriteLine(SassErrorHelpers.GenerateErrorDetails(e));
}
catch (SassException e)
{
Console.WriteLine("During working of Sass compiler an unknown error occurred. See details:");
Console.WriteLine();
Console.WriteLine(SassErrorHelpers.GenerateErrorDetails(e));
}
}
}
}
First we create an instance of the SassCompiler
class, in the constructor of which we pass the JS engine factory and compilation options.
Let's consider in detail properties of the CompilationOptions
class:
Property name | Data type | Default value | Description |
---|---|---|---|
Charset |
Boolean |
true |
Flag for whether to emit a @charset or BOM for CSS with non-ASCII characters. |
IncludePaths |
IList<string> |
Empty list | List of paths that library can look in to attempt to resolve @import declarations. |
IndentType |
IndentType enumeration |
Space |
Indent type. Can take the following values:
|
IndentWidth |
Int32 |
2 |
Number of spaces or tabs to be used for indentation. |
InlineSourceMap |
Boolean |
false |
Flag for whether to embed sourceMappingUrl as data uri. |
LineFeedType |
LineFeedType enumeration |
Lf |
Line feed type. Can take the following values:
|
OmitSourceMapUrl |
Boolean |
false |
Flag for whether to disable sourceMappingUrl in css output. |
OutputStyle |
OutputStyle enumeration |
Expanded |
Output style for the generated css code. Can take the following values:
|
QuietDependencies |
Boolean |
false |
Flag for whether to silence compiler warnings from stylesheets loaded by using the IncludePaths property. |
SourceMap |
Boolean |
false |
Flag for whether to enable source map generation. |
SourceMapIncludeContents |
Boolean |
false |
Flag for whether to include contents in maps. |
SourceMapRootPath |
String |
Empty string | Value will be emitted as sourceRoot in the source map information. |
WarningLevel |
WarningLevel enumeration |
Default |
Warning level. Can take the following values:
|
Then we call the Compile
method with the following parameters:
content
- text content written on Sass/SCSS.inputPath
- path to input Sass/SCSS file. Needed for generation of source map.outputPath
(optional) - path to output CSS file. Needed for generation of source map. If path to output file is not specified, but specified a path to input file, then value of this parameter is obtained by replacing extension in the input file path by.css
extension.sourceMapPath
(optional) - path to source map file. If path to source map file is not specified, but specified a path to output file, then value of this parameter is obtained by replacing extension in the output file path by.css.map
extension.
Then output result of compilation to the console.
In addition, we provide handling of the following exception types: SassCompilerLoadException
, SassCompilationException
and SassException
.
In the Dart Sass Host, exceptions have the following hierarchy:
SassException
SassCompilerLoadException
SassCompilationException
Using of the CompileFile
method quite a bit different from using of the Compile
method:
using System;
using System.IO;
using DartSassHost;
using DartSassHost.Helpers;
using JavaScriptEngineSwitcher.ChakraCore;
namespace DartSassHost.Example.ConsoleApplication
{
class Program
{
static void Main(string[] args)
{
const string basePath = "/Projects/TestSass";
string inputFilePath = Path.Combine(basePath, "style.scss");
string outputFilePath = Path.Combine(basePath, "style.css");
string sourceMapFilePath = Path.Combine(basePath, "style.css.map");
var options = new CompilationOptions { SourceMap = true };
try
{
using (var sassCompiler = new SassCompiler(new ChakraCoreJsEngineFactory(), options))
{
CompilationResult result = sassCompiler.CompileFile(inputFilePath, outputFilePath,
sourceMapFilePath, options);
Console.WriteLine("Compiled content:{1}{1}{0}{1}", result.CompiledContent,
Environment.NewLine);
Console.WriteLine("Source map:{1}{1}{0}{1}", result.SourceMap, Environment.NewLine);
Console.WriteLine("Included file paths: {0}",
string.Join(", ", result.IncludedFilePaths));
}
}
catch (SassCompilerLoadException e)
{
Console.WriteLine("During loading of Sass compiler an error occurred. See details:");
Console.WriteLine();
Console.WriteLine(SassErrorHelpers.GenerateErrorDetails(e));
}
catch (SassCompilationException e)
{
Console.WriteLine("During compilation of SCSS code an error occurred. See details:");
Console.WriteLine();
Console.WriteLine(SassErrorHelpers.GenerateErrorDetails(e));
}
catch (SassException e)
{
Console.WriteLine("During working of Sass compiler an unknown error occurred. See details:");
Console.WriteLine();
Console.WriteLine(SassErrorHelpers.GenerateErrorDetails(e));
}
}
}
}
In this case, the inputPath
parameter is used instead of the content
parameter. Moreover, value of the inputPath
parameter now should contain the path to real file.
If you use the Dart Sass Host for .NET in some project, please send me a message so I can include it in this list:
- Bundle Transformer by Andrey Taritsyn
- DartSassBuilder by Dean Wiseman
- Excubo.WebCompiler by Stefan Lörwald
- LigerShark.WebOptimizer.Sass by Mads Kristensen
- WatchSass.Tool by Magnus Gideryd