1
- use super :: { FsLoader , Loader , SourceFile , SourceKind } ;
1
+ use super :: {
2
+ CargoLoader , FsLoader , LoadError , Loader , SourceFile , SourceKind ,
3
+ } ;
2
4
use crate :: output:: { handle_parsed, CssBuf , CssHead , Format } ;
3
5
use crate :: { Error , ScopeRef } ;
4
6
use std:: { borrow:: Cow , collections:: BTreeMap , fmt, path:: Path } ;
5
7
use tracing:: instrument;
6
8
7
9
/// Utility keeping track of loading files.
8
10
///
11
+ /// The context is generic over the [`Loader`].
12
+ /// [`FsContext`] and [`CargoContext`] are type aliases for `Context`
13
+ /// where the loader is a [`FsLoader`] or [`CargoLoader`],
14
+ /// respectively.
15
+ ///
9
16
/// # Examples
10
17
///
11
18
/// The Context here is a [`FsContext`].
@@ -49,8 +56,8 @@ use tracing::instrument;
49
56
/// );
50
57
/// # Ok(()) }
51
58
/// ```
52
- pub struct Context < FileC > {
53
- file_context : FileC ,
59
+ pub struct Context < Loader > {
60
+ loader : Loader ,
54
61
scope : Option < ScopeRef > ,
55
62
loading : BTreeMap < String , SourceKind > ,
56
63
// TODO: Maybe have a map to loaded SourceFiles as well? Or even Parsed?
@@ -59,7 +66,7 @@ pub struct Context<FileC> {
59
66
/// A file-system based [`Context`].
60
67
pub type FsContext = Context < FsLoader > ;
61
68
62
- impl Context < FsLoader > {
69
+ impl FsContext {
63
70
/// Create a new `Context`, loading files based on the current
64
71
/// working directory.
65
72
pub fn for_cwd ( ) -> Self {
@@ -69,22 +76,62 @@ impl Context<FsLoader> {
69
76
/// Create a new `Context` and load a file.
70
77
///
71
78
/// The directory part of `path` is used as a base directory for the loader.
72
- pub fn for_path ( path : & Path ) -> Result < ( Self , SourceFile ) , Error > {
79
+ pub fn for_path ( path : & Path ) -> Result < ( Self , SourceFile ) , LoadError > {
73
80
let ( file_context, file) = FsLoader :: for_path ( path) ?;
74
81
Ok ( ( Context :: for_loader ( file_context) , file) )
75
82
}
76
83
77
84
/// Add a path to search for files.
78
85
pub fn push_path ( & mut self , path : & Path ) {
79
- self . file_context . push_path ( path) ;
86
+ self . loader . push_path ( path) ;
87
+ }
88
+ }
89
+
90
+ /// A file-system based [`Context`] for use in cargo build scripts.
91
+ ///
92
+ /// This is very similar to a [`FsContext`], but has a
93
+ /// `for_crate` constructor that uses the `CARGO_MANIFEST_DIR`
94
+ /// environment variable instead of the current working directory, and
95
+ /// it prints `cargo:rerun-if-changed` messages for each path that it
96
+ /// loads.
97
+ pub type CargoContext = Context < CargoLoader > ;
98
+
99
+ impl CargoContext {
100
+ /// Create a new `Context`, loading files based in the manifest
101
+ /// directory of the current crate.
102
+ ///
103
+ /// Relative paths will be resolved from the directory containing the
104
+ /// manifest of your package.
105
+ /// This assumes the program is called by `cargo` as a build script, so
106
+ /// the `CARGO_MANIFEST_DIR` environment variable is set.
107
+ pub fn for_crate ( ) -> Result < Self , LoadError > {
108
+ Ok ( Context :: for_loader ( CargoLoader :: for_crate ( ) ?) )
109
+ }
110
+
111
+ /// Create a new `Context` and load a file.
112
+ ///
113
+ /// The directory part of `path` is used as a base directory for the loader.
114
+ /// If `path` is relative, it will be resolved from the directory
115
+ /// containing the manifest of your package.
116
+ pub fn for_path ( path : & Path ) -> Result < ( Self , SourceFile ) , LoadError > {
117
+ let ( file_context, file) = CargoLoader :: for_path ( path) ?;
118
+ Ok ( ( Context :: for_loader ( file_context) , file) )
119
+ }
120
+
121
+ /// Add a path to search for files.
122
+ ///
123
+ /// If `path` is relative, it will be resolved from the directory
124
+ /// containing the manifest of your package.
125
+ pub fn push_path ( & mut self , path : & Path ) -> Result < ( ) , LoadError > {
126
+ self . loader . push_path ( path)
80
127
}
81
128
}
82
129
83
130
impl < AnyLoader : Loader > Context < AnyLoader > {
84
131
/// Create a new `Context` for a given file [`Loader`].
85
132
pub fn for_loader ( fc : AnyLoader ) -> Self {
86
133
Context {
87
- file_context : fc,
134
+ loader : fc,
88
135
scope : None ,
89
136
loading : Default :: default ( ) ,
90
137
}
@@ -211,12 +258,12 @@ impl<AnyLoader: Loader> Context<AnyLoader> {
211
258
& self ,
212
259
url : & str ,
213
260
names : & [ & dyn Fn ( & str , & str ) -> String ] ,
214
- ) -> Result < Option < ( String , AnyLoader :: File ) > , Error > {
261
+ ) -> Result < Option < ( String , AnyLoader :: File ) > , LoadError > {
215
262
if url. ends_with ( ".css" )
216
263
|| url. ends_with ( ".sass" )
217
264
|| url. ends_with ( ".scss" )
218
265
{
219
- self . file_context
266
+ self . loader
220
267
. find_file ( url)
221
268
. map ( |file| file. map ( |file| ( url. into ( ) , file) ) )
222
269
} else {
@@ -226,7 +273,7 @@ impl<AnyLoader: Loader> Context<AnyLoader> {
226
273
. unwrap_or ( ( "" , url) ) ;
227
274
228
275
for name in names. iter ( ) . map ( |f| f ( base, name) ) {
229
- if let Some ( result) = self . file_context . find_file ( & name) ? {
276
+ if let Some ( result) = self . loader . find_file ( & name) ? {
230
277
return Ok ( Some ( ( name, result) ) ) ;
231
278
}
232
279
}
@@ -277,7 +324,7 @@ fn relative<'a>(base: &SourceKind, url: &'a str) -> Cow<'a, str> {
277
324
impl < T : fmt:: Debug > fmt:: Debug for Context < T > {
278
325
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
279
326
f. debug_struct ( "Context" )
280
- . field ( "loader" , & self . file_context )
327
+ . field ( "loader" , & self . loader )
281
328
. field (
282
329
"scope" ,
283
330
& if self . scope . is_some ( ) { "loaded" } else { "no" } ,
0 commit comments