DartSassHost

.NET wrapper around the Dart Sass with the ability to support a virtual file system.


Keywords
CSS, DartSass, SCSS, Sass, csharp, dart-sass, dotnet
License
MIT
Install
Install-Package DartSassHost -Version 1.0.12

Documentation

Dart Sass Host for .NET NuGet version Download count

Dart Sass Host logo

.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.

Installation

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:

After installing the packages, you will need to register the default JS engine.

Usage

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:
  • Space - space character
  • Tab - tab character
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:
  • Cr - Macintosh (CR)
  • CrLf - Windows (CR LF)
  • Lf - Unix (LF)
  • LfCr
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:
  • Expanded
  • Compressed
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:
  • Quiet - warnings are not displayed
  • Default - displayed only 5 instances of the same deprecation warning per compilation
  • Verbose - displayed all deprecation warnings

Then we call the Compile method with the following parameters:

  1. content - text content written on Sass/SCSS.
  2. inputPath - path to input Sass/SCSS file. Needed for generation of source map.
  3. 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.
  4. 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.

Who's Using Dart Sass Host for .NET

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: