content: // Copyright 2019 Google LLC
  //
  // Use of this source code is governed by an MIT-style
  // license that can be found in the LICENSE file or at
  // https://opensource.org/licenses/MIT.
  
  import 'package:path/path.dart' as p;
  import 'package:sass_api/sass_api.dart';
  
  import '../io.dart';
  
  /// An importer that resolves URLs starting with `~` by searching in
  /// `node_modules` directories.
  ///
  /// This doesn't completely match Webpack's behavior (as it lacks the support
  /// for configuring its behavior), but it should be good enough to run the
  /// migrator with for most cases.
  class NodeModulesImporter extends Importer {
    /// Importers that load from various `node_modules` directories.
    final _fsImporters = <FilesystemImporter>[];
  
    /// Constructs a new [NodeModulesImporter] that searches for `node_modules` in
    /// [baseDirectory] and all of its ancestors.
    ///
    /// If not provided, [baseDirectory] defaults to the current directory.
    NodeModulesImporter([String? baseDirectory]) {
      var directory = baseDirectory ?? p.current;
      while (true) {
        var loadPath = p.join(directory, 'node_modules');
        if (Directory(loadPath).existsSync()) {
          _fsImporters.add(FilesystemImporter(loadPath));
        }
        var parent = p.dirname(directory);
        if (directory == parent) break;
        directory = parent;
      }
    }
  
    /// Canonicalizes [url] using this importer.
    ///
    /// If [url] starts with `~`, this searches all `node_modules` directories,
    /// using a [FilesystemImporter] to canonicalize to the real path on disk.
    ///
    /// If no matching stylesheet can be found, or if [url] does not start with
    /// `~`, this returns null.
    Uri? canonicalize(Uri url) {
      if (url.scheme == 'file') return _fsImporters.first.canonicalize(url);
  
      if (!url.path.startsWith('~')) return null;
      if (url.path.startsWith('~/')) return null;
      url = url.replace(path: url.path.substring(1));
      for (var importer in _fsImporters) {
        var result = importer.canonicalize(url);
        if (result != null) return result;
      }
      return null;
    }
  
    /// Loads [url] using a [FilesystemImporter].
    ///
    /// [url] must be the canonical URL returned by [canonicalize].
    ImporterResult? load(Uri url) => _fsImporters.first.load(url);
  }
  