Skip to content

Commit

Permalink
Add quietDeps and verbose to the JS API (#1353)
Browse files Browse the repository at this point in the history
To support this, we now run Node-Sass-style relative loads outside of
the Node importer. This allows the evaluator to check whether a
relative load succeeded and use that to determine whether the
stylesheet counts as a dependency.

See sass/sass#3065
  • Loading branch information
nex3 committed Jun 15, 2021
1 parent a077094 commit 7e37166
Show file tree
Hide file tree
Showing 11 changed files with 351 additions and 103 deletions.
10 changes: 9 additions & 1 deletion CHANGELOG.md
@@ -1,11 +1,19 @@
## 1.34.2
## 1.35.0

* Fix a couple bugs that could prevent some members from being found in certain
files that use a mix of imports and the module system.

* Fix incorrect recommendation for migrating division expressions that reference
namespaced variables.

### JS API

* Add a `quietDeps` option which silences compiler warnings from stylesheets
loaded through importers and load paths.

* Add a `verbose` option which causes the compiler to emit all deprecation
warnings, not just 5 per feature.

## 1.34.1

* Fix a bug where `--update` would always compile any file that depends on a
Expand Down
4 changes: 2 additions & 2 deletions lib/src/async_import_cache.dart
Expand Up @@ -102,8 +102,8 @@ class AsyncImportCache {
/// canonicalize [url] (resolved relative to [baseUrl] if it's passed).
///
/// If any importers understand [url], returns that importer as well as the
/// canonicalized URL and the original URL resolved relative to [baseUrl] if
/// applicable. Otherwise, returns `null`.
/// canonicalized URL and the original URL (resolved relative to [baseUrl] if
/// applicable). Otherwise, returns `null`.
Future<Tuple3<AsyncImporter, Uri, Uri>?> canonicalize(Uri url,
{AsyncImporter? baseImporter,
Uri? baseUrl,
Expand Down
6 changes: 3 additions & 3 deletions lib/src/import_cache.dart
Expand Up @@ -5,7 +5,7 @@
// DO NOT EDIT. This file was generated from async_import_cache.dart.
// See tool/grind/synchronize.dart for details.
//
// Checksum: 6821c9a63333c3c99b0c9515aa04e73a14e0f141
// Checksum: 27d8582c2ab318a52d433390ec256497b6af5dec
//
// ignore_for_file: unused_import

Expand Down Expand Up @@ -108,8 +108,8 @@ class ImportCache {
/// canonicalize [url] (resolved relative to [baseUrl] if it's passed).
///
/// If any importers understand [url], returns that importer as well as the
/// canonicalized URL and the original URL resolved relative to [baseUrl] if
/// applicable. Otherwise, returns `null`.
/// canonicalized URL and the original URL (resolved relative to [baseUrl] if
/// applicable). Otherwise, returns `null`.
Tuple3<Importer, Uri, Uri>? canonicalize(Uri url,
{Importer? baseImporter, Uri? baseUrl, bool forImport = false}) {
if (baseImporter != null) {
Expand Down
60 changes: 29 additions & 31 deletions lib/src/importer/node/implementation.dart
Expand Up @@ -68,18 +68,33 @@ class NodeImporter {
yield* sassPath.split(isWindows ? ';' : ':');
}

/// Loads the stylesheet at [url].
/// Loads the stylesheet at [url] relative to [previous] if possible.
///
/// This can also load [url] directly if it's an absolute `file:` URL, even if
/// `previous` isn't defined or isn't a `file:` URL.
///
/// Returns the stylesheet at that path and the URL used to load it, or `null`
/// if loading failed.
Tuple2<String, String>? loadRelative(
String url, Uri? previous, bool forImport) {
if (p.url.isAbsolute(url)) {
if (!url.startsWith('/') && !url.startsWith('file:')) return null;
return _tryPath(p.fromUri(url), forImport);
}

if (previous?.scheme != 'file') return null;

// 1: Filesystem imports relative to the base file.
return _tryPath(
p.join(p.dirname(p.fromUri(previous)), p.fromUri(url)), forImport);
}

/// Loads the stylesheet at [url] from an importer or load path.
///
/// The [previous] URL is the URL of the stylesheet in which the import
/// appeared. Returns the contents of the stylesheet and the URL to use as
/// [previous] for imports within the loaded stylesheet.
Tuple2<String, String>? load(String url, Uri? previous, bool forImport) {
var parsed = Uri.parse(url);
if (parsed.scheme == '' || parsed.scheme == 'file') {
var result = _resolveRelativePath(p.fromUri(parsed), previous, forImport);
if (result != null) return result;
}

// The previous URL is always an absolute file path for filesystem imports.
var previousString = _previousToString(previous);
for (var importer in _importers) {
Expand All @@ -90,22 +105,17 @@ class NodeImporter {
}
}

return _resolveLoadPathFromUrl(parsed, forImport);
return _resolveLoadPathFromUrl(Uri.parse(url), forImport);
}

/// Asynchronously loads the stylesheet at [url].
/// Asynchronously loads the stylesheet at [url] from an importer or load
/// path.
///
/// The [previous] URL is the URL of the stylesheet in which the import
/// appeared. Returns the contents of the stylesheet and the URL to use as
/// [previous] for imports within the loaded stylesheet.
Future<Tuple2<String, String>?> loadAsync(
String url, Uri? previous, bool forImport) async {
var parsed = Uri.parse(url);
if (parsed.scheme == '' || parsed.scheme == 'file') {
var result = _resolveRelativePath(p.fromUri(parsed), previous, forImport);
if (result != null) return result;
}

// The previous URL is always an absolute file path for filesystem imports.
var previousString = _previousToString(previous);
for (var importer in _importers) {
Expand All @@ -116,20 +126,7 @@ class NodeImporter {
}
}

return _resolveLoadPathFromUrl(parsed, forImport);
}

/// Tries to load a stylesheet at the given [path] relative to [previous].
///
/// Returns the stylesheet at that path and the URL used to load it, or `null`
/// if loading failed.
Tuple2<String, String>? _resolveRelativePath(
String path, Uri? previous, bool forImport) {
if (p.isAbsolute(path)) return _tryPath(path, forImport);
if (previous?.scheme != 'file') return null;

// 1: Filesystem imports relative to the base file.
return _tryPath(p.join(p.dirname(p.fromUri(previous)), path), forImport);
return _resolveLoadPathFromUrl(Uri.parse(url), forImport);
}

/// Converts [previous] to a string to pass to the importer function.
Expand Down Expand Up @@ -192,8 +189,9 @@ class NodeImporter {
} else if (contents != null) {
return Tuple2(contents, file);
} else {
var resolved = _resolveRelativePath(file, previous, forImport) ??
_resolveLoadPath(file, forImport);
var resolved =
loadRelative(p.toUri(file).toString(), previous, forImport) ??
_resolveLoadPath(file, forImport);
if (resolved != null) return resolved;
throw "Can't find stylesheet to import.";
}
Expand Down
4 changes: 4 additions & 0 deletions lib/src/importer/node/interface.dart
Expand Up @@ -8,6 +8,10 @@ class NodeImporter {
NodeImporter(Object options, Iterable<String> includePaths,
Iterable<Object> importers);

Tuple2<String, String>? loadRelative(
String url, Uri? previous, bool forImport) =>
throw '';

Tuple2<String, String>? load(String url, Uri? previous, bool forImport) =>
throw '';

Expand Down
8 changes: 8 additions & 0 deletions lib/src/node.dart
Expand Up @@ -106,6 +106,8 @@ Future<RenderResult> _renderAsync(RenderOptions options) async {
indentWidth: _parseIndentWidth(options.indentWidth),
lineFeed: _parseLineFeed(options.linefeed),
url: file == null ? 'stdin' : p.toUri(file).toString(),
quietDeps: options.quietDeps ?? false,
verbose: options.verbose ?? false,
sourceMap: _enableSourceMaps(options));
} else if (file != null) {
result = await compileAsync(file,
Expand All @@ -116,6 +118,8 @@ Future<RenderResult> _renderAsync(RenderOptions options) async {
useSpaces: options.indentType != 'tab',
indentWidth: _parseIndentWidth(options.indentWidth),
lineFeed: _parseLineFeed(options.linefeed),
quietDeps: options.quietDeps ?? false,
verbose: options.verbose ?? false,
sourceMap: _enableSourceMaps(options));
} else {
throw ArgumentError("Either options.data or options.file must be set.");
Expand Down Expand Up @@ -147,6 +151,8 @@ RenderResult _renderSync(RenderOptions options) {
indentWidth: _parseIndentWidth(options.indentWidth),
lineFeed: _parseLineFeed(options.linefeed),
url: file == null ? 'stdin' : p.toUri(file).toString(),
quietDeps: options.quietDeps ?? false,
verbose: options.verbose ?? false,
sourceMap: _enableSourceMaps(options));
} else if (file != null) {
result = compile(file,
Expand All @@ -157,6 +163,8 @@ RenderResult _renderSync(RenderOptions options) {
useSpaces: options.indentType != 'tab',
indentWidth: _parseIndentWidth(options.indentWidth),
lineFeed: _parseLineFeed(options.linefeed),
quietDeps: options.quietDeps ?? false,
verbose: options.verbose ?? false,
sourceMap: _enableSourceMaps(options));
} else {
throw ArgumentError("Either options.data or options.file must be set.");
Expand Down
6 changes: 5 additions & 1 deletion lib/src/node/render_options.dart
Expand Up @@ -26,6 +26,8 @@ class RenderOptions {
external bool? get sourceMapContents;
external bool? get sourceMapEmbed;
external String? get sourceMapRoot;
external bool? get quietDeps;
external bool? get verbose;

external factory RenderOptions(
{String? file,
Expand All @@ -44,5 +46,7 @@ class RenderOptions {
Object? sourceMap,
bool? sourceMapContents,
bool? sourceMapEmbed,
String? sourceMapRoot});
String? sourceMapRoot,
bool? quietDeps,
bool? verbose});
}

0 comments on commit 7e37166

Please sign in to comment.