-
Notifications
You must be signed in to change notification settings - Fork 360
/
Copy pathasync.dart
180 lines (169 loc) · 7.96 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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
// 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 'canonicalize_context.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;
/// The canonical URL of the stylesheet that caused the current [canonicalize]
/// invocation.
///
/// This is only set when the containing stylesheet has a canonical URL, and
/// when the URL being canonicalized is either relative or has a scheme for
/// which [isNonCanonicalScheme] returns `true`. This restriction ensures that
/// canonical URLs are always interpreted the same way regardless of their
/// context.
///
/// Subclasses should only access this from within calls to [canonicalize].
/// Outside of that context, its value is undefined and subject to change.
@protected
@nonVirtual
Uri? get containingUrl => utils.canonicalizeContext.containingUrl;
/// The canonicalize context of the stylesheet that caused the current
/// [canonicalize] invocation.
///
/// Subclasses should only access this from within calls to [canonicalize].
/// Outside of that context, its value is undefined and subject to change.
///
/// @nodoc
@internal
@protected
@nonVirtual
CanonicalizeContext get canonicalizeContext => utils.canonicalizeContext;
/// 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;
/// Returns whether the given URL scheme (without `:`) should be considered
/// "non-canonical" for this importer.
///
/// An importer may not return a URL with a non-canonical scheme from
/// [canonicalize]. In exchange, [containingUrl] is available within
/// [canonicalize] for absolute URLs with non-canonical schemes so that the
/// importer can resolve those URLs differently based on where they're loaded.
///
/// This must always return the same value for the same [scheme]. It is
/// expected to be very efficient.
FutureOr<bool> isNonCanonicalScheme(String scheme) => false;
}