mirror of
https://github.com/danog/dart-sass.git
synced 2024-11-26 20:24:42 +01:00
Add AsyncImporter.fromImport
for Dart importers
This commit is contained in:
parent
8a344e343f
commit
136bd285b3
@ -9,6 +9,13 @@
|
||||
|
||||
[import-only files]: https://sass-lang.com/documentation/at-rules/import#import-only-files
|
||||
|
||||
### Dart API
|
||||
|
||||
* Add an `Importer.fromImport` getter, which is `true` if the current
|
||||
`Importer.canonicalize()` call comes from an `@import` rule and `false`
|
||||
otherwise. Importers should only use this to determine whether to load
|
||||
[import-only files].
|
||||
|
||||
## 1.32.13
|
||||
|
||||
* **Potentially breaking bug fix:** Null values in `@use` and `@forward`
|
||||
|
@ -4,7 +4,10 @@
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
import 'result.dart';
|
||||
import 'utils.dart' as utils;
|
||||
|
||||
/// An interface for importers that resolves URLs in `@import`s to the contents
|
||||
/// of Sass files.
|
||||
@ -20,6 +23,22 @@ import 'result.dart';
|
||||
///
|
||||
/// Subclasses should extend [AsyncImporter], not implement it.
|
||||
abstract class AsyncImporter {
|
||||
/// Whether the current [canonicalize] invocation comes from an `@import`
|
||||
/// rule.
|
||||
///
|
||||
/// When evaluating `@import` rules, URLs should canonicalize to an
|
||||
/// [import-only file] if one exists for the URL being canonicalized.
|
||||
/// Otherwise, canonicalization should be identical for `@import` and `@use`
|
||||
/// rules.
|
||||
///
|
||||
/// [import-only file]: https://sass-lang.com/documentation/at-rules/import#import-only-files
|
||||
///
|
||||
/// Subclasses should only access this from within calls to [canonicalize].
|
||||
/// Outside of that context, its value is undefined and subject to change.
|
||||
@protected
|
||||
@nonVirtual
|
||||
bool get fromImport => utils.fromImport;
|
||||
|
||||
/// If [url] is recognized by this importer, returns its canonical format.
|
||||
///
|
||||
/// Note that canonical URLs *must* be absolute, including a scheme. Returning
|
||||
|
@ -2,6 +2,8 @@
|
||||
// MIT-style license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:path/path.dart' as p;
|
||||
|
||||
import '../io.dart';
|
||||
@ -13,30 +15,12 @@ import '../io.dart';
|
||||
/// canonicalization should be identical for `@import` and `@use` rules. It's
|
||||
/// admittedly hacky to set this globally, but `@import` will eventually be
|
||||
/// removed, at which point we can delete this and have one consistent behavior.
|
||||
bool _inImportRule = false;
|
||||
bool get fromImport => Zone.current[#_inImportRule] as bool? ?? false;
|
||||
|
||||
/// Runs [callback] in a context where [resolveImportPath] uses `@import`
|
||||
/// semantics rather than `@use` semantics.
|
||||
T inImportRule<T>(T callback()) {
|
||||
var wasInImportRule = _inImportRule;
|
||||
_inImportRule = true;
|
||||
try {
|
||||
return callback();
|
||||
} finally {
|
||||
_inImportRule = wasInImportRule;
|
||||
}
|
||||
}
|
||||
|
||||
/// Like [inImportRule], but asynchronous.
|
||||
Future<T> inImportRuleAsync<T>(Future<T> callback()) async {
|
||||
var wasInImportRule = _inImportRule;
|
||||
_inImportRule = true;
|
||||
try {
|
||||
return await callback();
|
||||
} finally {
|
||||
_inImportRule = wasInImportRule;
|
||||
}
|
||||
}
|
||||
/// Runs [callback] in a context where [inImportRule] returns `true` and
|
||||
/// [resolveImportPath] uses `@import` semantics rather than `@use` semantics.
|
||||
T inImportRule<T>(T callback()) =>
|
||||
runZoned(callback, zoneValues: {#_inImportRule: true});
|
||||
|
||||
/// Resolves an imported path using the same logic as the filesystem importer.
|
||||
///
|
||||
@ -95,7 +79,7 @@ String? _exactlyOne(List<String> paths) {
|
||||
paths.map((path) => " " + p.prettyUri(p.toUri(path))).join("\n");
|
||||
}
|
||||
|
||||
/// If [_inImportRule] is `true`, invokes callback and returns the result.
|
||||
/// If [fromImport] is `true`, invokes callback and returns the result.
|
||||
///
|
||||
/// Otherwise, returns `null`.
|
||||
T? _ifInImport<T>(T callback()) => _inImportRule ? callback() : null;
|
||||
T? _ifInImport<T>(T callback()) => fromImport ? callback() : null;
|
||||
|
28
test/dart_api/from_import_importer.dart
Normal file
28
test/dart_api/from_import_importer.dart
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright 2017 Google Inc. 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:sass/sass.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
/// An [Importer] whose [canonicalize] method asserts the value of
|
||||
/// [Importer.fromImport].
|
||||
class FromImportImporter extends Importer {
|
||||
/// The expected value of [Importer.fromImport] in the call to [canonicalize].
|
||||
final bool _expected;
|
||||
|
||||
/// The callback to call once [canonicalize] is called.
|
||||
///
|
||||
/// This ensures that the test doesn't exit until [canonicalize] is called.
|
||||
final void Function() _done;
|
||||
|
||||
FromImportImporter(this._expected) : _done = expectAsync0(() {});
|
||||
|
||||
Uri? canonicalize(Uri url) {
|
||||
expect(fromImport, equals(_expected));
|
||||
_done();
|
||||
return Uri.parse('u:');
|
||||
}
|
||||
|
||||
ImporterResult? load(Uri url) => ImporterResult("", syntax: Syntax.scss);
|
||||
}
|
@ -12,6 +12,7 @@ import 'package:test/test.dart';
|
||||
import 'package:sass/sass.dart';
|
||||
import 'package:sass/src/exception.dart';
|
||||
|
||||
import 'from_import_importer.dart';
|
||||
import 'test_importer.dart';
|
||||
import '../utils.dart';
|
||||
|
||||
@ -182,4 +183,23 @@ void main() {
|
||||
return true;
|
||||
})));
|
||||
});
|
||||
|
||||
group("currentLoadFromImport is", () {
|
||||
test("true from an @import", () {
|
||||
compileString('@import "foo"', importers: [FromImportImporter(true)]);
|
||||
});
|
||||
|
||||
test("false from a @use", () {
|
||||
compileString('@use "foo"', importers: [FromImportImporter(false)]);
|
||||
});
|
||||
|
||||
test("false from a @forward", () {
|
||||
compileString('@forward "foo"', importers: [FromImportImporter(false)]);
|
||||
});
|
||||
|
||||
test("false from meta.load-css", () {
|
||||
compileString('@use "sass:meta"; @include meta.load-css("")',
|
||||
importers: [FromImportImporter(false)]);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user