/
async.dart
140 lines (132 loc) · 6.26 KB
/
async.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// 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 '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.
///
/// Importers should override [toString] to provide a human-readable description
/// of the importer. For example, the default filesystem importer returns its
/// load path.
///
/// This class should only be extended by importers that *need* to do
/// asynchronous work. It's only compatible with the asynchronous `compile()`
/// methods. If an importer can work synchronously, it should extend [Importer]
/// instead.
///
/// Subclasses should extend [AsyncImporter], not implement it.
///
/// {@category Importer}
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
/// `file:` URLs is encouraged if the imported stylesheet comes from a file on
/// disk.
///
/// If Sass has already loaded a stylesheet with the returned canonical URL,
/// it re-uses the existing parse tree. This means that importers **must
/// ensure** that the same canonical URL always refers to the same stylesheet,
/// *even across different importers*.
///
/// This may return `null` if [url] isn't recognized by this importer.
///
/// If this importer's URL format supports file extensions, it should
/// canonicalize them the same way as the default filesystem importer:
///
/// * The importer should look for stylesheets by adding the prefix `_` to the
/// URL's basename, and by adding the extensions `.sass` and `.scss` if the
/// URL doesn't already have one of those extensions. For example, if the
/// URL was `foo/bar/baz`, the importer would look for:
/// * `foo/bar/baz.sass`
/// * `foo/bar/baz.scss`
/// * `foo/bar/_baz.sass`
/// * `foo/bar/_baz.scss`
///
/// If the URL was `foo/bar/baz.scss`, the importer would just look for:
/// * `foo/bar/baz.scss`
/// * `foo/bar/_baz.scss`
///
/// If the importer finds a stylesheet at more than one of these URLs, it
/// should throw an exception indicating that the import is ambiguous. Note
/// that if the extension is explicitly specified, a stylesheet with the
/// opposite extension may exist.
///
/// * If none of the possible paths is valid, the importer should perform the
/// same resolution on the URL followed by `/index`. In the example above,
/// it would look for:
/// * `foo/bar/baz/_index.sass`
/// * `foo/bar/baz/index.sass`
/// * `foo/bar/baz/_index.scss`
/// * `foo/bar/baz/index.scss`
///
/// As above, if the importer finds a stylesheet at more than one of these
/// URLs, it should throw an exception indicating that the import is
/// ambiguous.
///
/// If no stylesheets are found, the importer should return `null`.
///
/// Calling [canonicalize] multiple times with the same URL must return the
/// same result. Calling [canonicalize] with a URL returned by [canonicalize]
/// must return that URL. Calling [canonicalize] with a URL relative to one
/// returned by [canonicalize] must return a meaningful result.
FutureOr<Uri?> canonicalize(Uri url);
/// Loads the Sass text for the given [url], or returns `null` if
/// this importer can't find the stylesheet it refers to.
///
/// The [url] comes from a call to [canonicalize] for this importer.
///
/// When Sass encounters an `@import` rule in a stylesheet, it first calls
/// [canonicalize] and [load] on the importer that first loaded that
/// stylesheet with the imported URL resolved relative to the stylesheet's
/// original URL. If either of those returns `null`, it then calls
/// [canonicalize] and [load] on each importer in order with the URL as it
/// appears in the `@import` rule.
///
/// If the importer finds a stylesheet at [url] but it fails to load for some
/// reason, or if [url] is uniquely associated with this importer but doesn't
/// refer to a real stylesheet, the importer may throw an exception that will
/// be wrapped by Sass. If the exception object has a `message` property, it
/// will be used as the wrapped exception's message; otherwise, the exception
/// object's `toString()` will be used. This means it's safe for importers to
/// throw plain strings.
FutureOr<ImporterResult?> load(Uri url);
/// Returns the time that the Sass file at [url] was last modified.
///
/// The [url] comes from a call to [canonicalize] for this importer.
///
/// By default, this returns the current time, indicating that [url] should be
/// reloaded on every compilation. If implementations override this to provide
/// a more accurate time, Sass will be better able to avoid recompiling it
/// unnecessarily.
///
/// If this throws an exception, the exception is ignored and the current time
/// is used as the modification time.
FutureOr<DateTime> modificationTime(Uri url) => DateTime.now();
/// Without accessing the filesystem, returns whether or not passing [url] to
/// [canonicalize] could possibly return [canonicalUrl].
///
/// This is expected to be very efficient, and subclasses are allowed to
/// return false positives if it would be inefficient to determine whether
/// [url] would actually resolve to [canonicalUrl]. Subclasses are not allowed
/// to return false negatives.
FutureOr<bool> couldCanonicalize(Uri url, Uri canonicalUrl) => true;
}