Skip to content

Latest commit

 

History

History
161 lines (126 loc) · 6.4 KB

import.md

File metadata and controls

161 lines (126 loc) · 6.4 KB

Import

The @import rule is the legacy way of splitting styles across multiple files in Sass. The @use rule should generally be used instead, but @import is still supported for backwards-compatibility.

Table of Contents

Syntax

ImportRule            ::= '@import' (ImportArgumentNoMedia ',')* ImportArgument
ImportArgumentNoMedia ::= ImportUrl ImportModifierNoMedia*
ImportArgument        ::= ImportUrl ImportModifier
ImportModifierNoMedia ::= InterpolatedIdentifier* (ImportFunction | ImportSupports)
ImportModifier        ::= ImportModifierNoMedia* InterpolatedIdentifier* ImportMedia?
ImportMedia           ::= MediaFeatureInParens (',' MediaQueryList)*
                        | InterpolatedIdentifier (',' MediaQueryList)*
ImportSupports        ::= 'supports(' SupportsDeclaration ')'
ImportFunction        ::= InterpolatedIdentifier¹ '(' InterpolatedDeclarationValue? ')'
ImportUrl             ::= QuotedString | InterpolatedUrl

1: This identifier may not be "supports" or "and". No whitespace is allowed between it and the following (.

This somewhat involved grammar was chosen over the simpler

ImportRule     ::= '@import" (ImportArgument ',')* ImportArgument
ImportArgument ::= ImportUrl ImportModifier*
ImportArgument ::= ImportUrl ImportModifier*
ImportModifier ::= ImportFunction | ImportSupports | MediaQueryList

because this simpler version produces a number of problematic ambiguities. For example:

  • @import "..." a b(c) could be parsed as either:
    • MediaQuery "a", ImportFunction "b(c)"
    • MediaQuery "a b", MediaQuery "(c)"
  • @import "..." a and(b) could be parsed as either:
    • MediaQuery "a", ImportFunction "and(b)"
    • MediaQuery "a and(b)"

To resolve these, this grammar explicitly indicates that a MediaQueryList and its associated commas may only appear at the end of an ImportRule, and delineates the exact circumstances in which an InterpolatedIdentifier is or is not part of a MediaQueryList.

Note that this parses @import "..." layer (max-width: 600px) differently than the CSS standard: in CSS, layer is a CSS layering keyword but Sass parses it as part of a media query in this instance. This doesn't pose a problem in practice because Sass's semantics never depend on how import modifiers are parsed.

Semantics

To execute an @import rule rule:

  • For each of rule's ImportArgumentNoMedias and ImportArguments argument:

    • If any of the following are true, argument is considered "plain CSS":

      • argument's URL string begins with http:// or https://.
      • argument's URL string ends with .css.
      • argument's URL is an InterpolatedUrl.
      • argument has at least one ImportModifierNoMedia.
      • argument has a non-empty ImportModifier.

      Note that this means that imports that explicitly end with .css are treated as plain CSS @import rules, rather than importing stylesheets as CSS.

    • If argument is "plain CSS":

      • Evaluate each of the following within argument's ImportModifierNoMedias or ImportModifiers, and concatenate the results into a single string with " " between each one:

        • For an InterpolatedIdentifier outside an ImportMedia, concatenate the result of evaluating it.

        • For an ImportFunction, concatenate:

          • The result of evaluating its InterpolatedIdentifier
          • "("
          • The result of evaluating its InterpolatedDeclarationValue (or "" if it doesn't have one)
          • ")"
        • For an ImportSupports, concatenate:

          • "supports("
          • The result of evaluating its SupportsDeclaration as a CSS string
          • `")"
        • For an ImportMedia, concatenate the result of evaluating it as a MediaQueryList as a CSS string.

          ImportMedia is a subset of the valid syntax of MediaQueryList, so this will always work.

      • Add an @import with the evaluated modifiers to the current module's CSS AST.

    • Otherwise, let file be the result of loading the file with argument's URL string. If this returns null, throw an error.

    • If file's canonical URL is the same as that of any other current source file, throw an error.

    • Let imported be the result of executing file with the empty configuration and the current import context, except that if rule is nested within at-rules and/or style rules, that context is preserved when executing file.

      Note that this execution can mutate import.

    • Let css be the result of resolving imported's extensions, except that if rule is nested within at-rules and/or style rules, that context is added to CSS that comes from modules loaded by imported.

      This creates an entirely separate CSS tree with an entirely separate @extend context than normal @uses of these modules. This means their CSS may be duplicated, and they may be extended differently.

    • Add css to the current module's CSS.

    • Add imported's extensions to the current module.

    • If the @import rule is nested within at-rules and/or style rules, add each member in imported to the local scope.

    • Otherwise, add each member in imported to the current import context and the current module.

      Members defined directly in imported will have already been added to import in the course of its execution. This only adds members that imported forwards.

      Members from imported override members of the same name and type that have already been added to import and module.