Dart Sass Documentation

repository·main·Indexed 26 days ago

https://github.com/sass/dart-sass

A Dart implementation of the Sass CSS preprocessor providing a high-performance compiler via CLI, npm, Pub, and libraries for JavaScript and Dart. This documentation covers the compilation lifecycle (parsing, evaluation, and serialization), the structure of Sass, CSS, and Selector Abstract Syntax Trees (AST), the Embedded Sass Compiler, and the JavaScript API. It also details how to extend Sass using custom importers, functions, and loggers.

Tokens
9.2K
Snippets
19
Records
69
Agent score
88%

What's inside Dart Sass

  1. Use @sass/types for Sass JS API type definitions

    main

    The @sass/types package provides the type definitions for the Sass JS API. It is a dual-publish of the official Sass JS API types.

    Use this package if you only require the Sass JS types without the full compiler implementation (for example, when providing types for tools like @types/gulp-sass).

    Note: The sass and sass-embedded packages also contain these types. To ensure compatibility, always use the same version of @sass/types that matches your version of sass or sass-embedded.

  2. Understand SassScript value types

    main

    SassScript values are represented by specific value types that are used both internally and in the public Dart API. These values are typically produced by the evaluator during the evaluation of the Sass AST (Abstract Syntax Tree).

    Important: Immutability All Sass values are immutable. You cannot modify an existing value instance. To change a value, you must create a new value instance. A common pattern for complex updates is to create a mutable copy, perform the necessary edits, and then instantiate a new immutable value from that result.

  3. Compare performance of Dart Sass implementations

    main

    Dart Sass can be run in several ways, each with different performance characteristics. Based on informal benchmarks, the Dart Sass native executable generally provides the best performance, often outperforming or matching sassc (libsass) and significantly outperforming Dart Sass on Node.js.

    Key performance takeaways:

    • Native Executable: Best for most use cases, especially large files and frameworks like Bootstrap or a11ycolor. It is often faster than libsass in real-world scenarios.
    • Node.js: Substantially slower than the native executable or the Dart VM. For high-performance requirements, consider using the embedded protocol or waiting for WebAssembly support.
    • Complexity Impact: Performance varies depending on whether your SCSS uses heavy @extend patterns (dense or sparse) or intensive computations (like color processing).
  4. Understand Built-In Sass Functions

    main

    Sass provides standard functions that are either available globally or through specific built-in modules. Each module is exported as a BuiltInModule.

    Note that some functions are not defined within the standard function files:

    • The if() function is defined in functions.dart but is primarily handled by the evaluator as a LegacyIfExpression to manage special argument evaluation behavior. It is available for edge cases like if(...$args) or meta.get-function("if").
    • Certain functions in the sass:meta module are defined directly within the evaluator because they require runtime information only accessible to the evaluator's private variables.
  5. Understand the Selector Abstract Syntax Tree (AST)

    main

    The Selector AST represents a parsed CSS selector. It is constructed recursively by the selector parser and is fully immutable.

    Key characteristics:

    • Parsing Timing: Unlike the main Sass AST (which is parsed from raw source strings), the Selector AST is parsed during evaluation. This allows the system to resolve interpolation before the selectors are fully parsed.
    • Sass-specific Constructs: While it does not contain SassScript, it includes specific constructs:
      • Parent selector (&): These are resolved by the evaluator before being passed to the serializer.
      • Placeholder selectors: These are omitted during the serialization process.
  6. Understand the Sass Abstract Syntax Tree (AST) structure

    main

    The Sass AST represents a Sass source file (SCSS, indented syntax, or plain CSS) as a recursive, immutable tree structure. The AST is categorized into three main types of nodes:

    1. Statement AST: Represents statement-level constructs such as variable assignments, style rules, and at-rules.
    2. Expression AST: Represents SassScript expressions, including function calls, operations, and value literals.
    3. Miscellaneous AST nodes: Nodes used by both statements and expressions, or those that do not fit into the first two categories, located in the root AST directory.

    The AST is typically processed starting from the root Stylesheet node by the evaluator to produce a CSS AST.

  7. Understand the Sass compilation lifecycle

    main

    Sass compilation follows a three-pass process implemented as an AST-walking interpreter:

    1. Parsing: The source file (SCSS, indented syntax, or CSS) is parsed into an Abstract Syntax Tree (AST) located in ast/sass.
    2. Evaluation: The evaluator (via visitor/async_evaluate.dart) resolves variables, mixins, and control flow. It builds a new CSS AST (ast/css). This phase handles module resolution and @extend across modules.
    3. Serialization: The CSS AST is converted into a CSS text buffer via visitor/serialize.dart. This step also generates source maps.

    Note on Late Parsing & Early Serialization:

    • Late Parsing: Certain elements like Selectors, @keyframes frames, and Media queries are parsed during the evaluation phase (e.g., when using #{} interpolation).
    • Early Serialization: The evaluator may invoke the serializer during evaluation to convert interpolated values into strings for parsing (e.g., when injecting a variable into a selector).
  8. Use Visitors to traverse Sass ASTs

    main

    The visitor package provides implementations of the visitor pattern for various Sass Abstract Syntax Trees (ASTs). These visitors can be used to implement custom logic that runs over an AST to extract information or perform transformations.

    Key implementations include:

    • Evaluator (async_evaluate.dart): Implements critical business logic for evaluating Sass expressions.
    • Serializer (serialize.dart): Implements logic for converting ASTs into other formats.
    • Utility Visitors: Small utilities or base classes used to determine specific properties of an AST.

    Many of these visitors are provided specifically to support users of the sass_api package.

  9. Use the sass_api package for AST and load resolution access

    main

    The sass_api package provides advanced APIs for working with Dart Sass that are not available in the standard sass package. Specifically, it allows access to the Sass Abstract Syntax Tree (AST) and the Sass load resolution logic.

    Note that sass_api is versioned separately from the main sass package and is expected to evolve more quickly, meaning it may contain breaking changes as the compiler internals change.

  10. Use the Embedded Sass Compiler

    main

    The Embedded Sass Compiler is a special mode of the Dart Sass command-line executable that allows it to communicate with an "embedded host" via stdin and stdout. This mode uses a protocol buffer-based protocol and is only supported on the Dart VM.

    This mode is designed for scenarios where an external process (the host) needs to orchestrate Sass compilations by sending commands through standard input and receiving results through standard output.

  11. Understand the CSS Abstract Syntax Tree (AST)

    main

    The CSS Abstract Syntax Tree (AST) represents the plain CSS output generated by the Sass compiler. It is distinct from the Sass AST in two ways:

    1. Generation: It is created by the evaluator during its traversal of the Sass AST, rather than by a parser.
    2. Mutability: Unlike other Sass ASTs which are immutable, the CSS AST is mutable to support features like @extend and at-rule hoisting.

    Important Note on Values: The CSS AST does not have its own representation of declaration values; instead, it uses Value objects. Because of this, a CSS AST may contain values that cannot be represented in plain CSS (such as Sass maps). If the serializer encounters such a value, it will emit an error.

  12. Understand the Sass Parser architecture

    main

    Sass parsing is implemented using a handwritten recursive descent parser powered by the string_scanner package. This approach allows for arbitrary backtracking required by Sass's grammar and enables precise source span tracking for error reporting and source map generation.

    Key components include:

    • Parser: The base class providing infrastructure, utilities, and methods for parsing common CSS constructs.
    • StylesheetParser: The base class for initial stylesheet parsing. It contains the core logic for statement- and expression-level parsing, leaving only syntax-specific differences to be implemented by subclasses.