hyper_static_server/
builder.rs

1
2
3
4
5#[ allow (unused_imports) ]
6use ::std::{
7		
8		cell,
9		env,
10		ffi,
11		fmt,
12		fs,
13		io,
14		iter,
15		mem,
16		path,
17		rc,
18		
19		collections::BTreeSet,
20		iter::Iterator,
21		path::{Path, PathBuf},
22		
23		str::FromStr as _,
24		fmt::{Write as _},
25		io::{Write as _},
26		
27	};
28
29
30use ::globset;
31use ::walkdir;
32use ::blake2;
33use ::proc_macro2;
34
35
36use crate::builder_errors::*;
37
38
39
40
41#[ derive (Clone, Debug) ]
42pub struct BuilderConfiguration {
43	
44	pub sources : Option<PathBuf>,
45	#[ cfg (feature = "builder-assets") ]
46	pub assets_sources : Option<PathBuf>,
47	#[ cfg (feature = "builder-askama") ]
48	pub templates_sources : Option<PathBuf>,
49	#[ cfg (feature = "builder-markdown") ]
50	pub markdowns_sources : Option<PathBuf>,
51	
52	#[ cfg (feature = "builder-assets") ]
53	pub assets_route_base : Option<PathBuf>,
54	
55	#[ cfg (feature = "builder-assets") ]
56	pub css_route_base : Option<PathBuf>,
57	#[ cfg (feature = "builder-assets") ]
58	pub js_route_base : Option<PathBuf>,
59	
60	#[ cfg (feature = "builder-assets") ]
61	pub images_route_base : Option<PathBuf>,
62	#[ cfg (feature = "builder-assets") ]
63	pub icons_route_base : Option<PathBuf>,
64	#[ cfg (feature = "builder-assets") ]
65	pub favicons_route_base : Option<PathBuf>,
66	#[ cfg (feature = "builder-assets") ]
67	pub fonts_route_base : Option<PathBuf>,
68	
69	pub outputs : PathBuf,
70	pub generated : PathBuf,
71}
72
73
74impl Default for BuilderConfiguration {
75	
76	fn default () -> Self {
77		
78		let _sources = Self::resolve_sources () .or_panic (0xc6e7914d);
79		let _outputs = Self::resolve_outputs () .or_panic (0x344e2c9e);
80		
81		#[ cfg (feature = "builder-assets") ]
82		let _assets_sources = _sources.join ("./assets");
83		#[ cfg (feature = "builder-assets") ]
84		let _assets_sources = if _assets_sources.exists () { Some (_assets_sources) } else { None };
85		
86		#[ cfg (feature = "builder-askama") ]
87		let _templates_sources = _sources.join ("./templates");
88		#[ cfg (feature = "builder-askama") ]
89		let _templates_sources = if _templates_sources.exists () { Some (_templates_sources) } else { None };
90		
91		#[ cfg (feature = "builder-markdown") ]
92		let _markdowns_sources = _sources.join ("./markdown");
93		#[ cfg (feature = "builder-markdown") ]
94		let _markdowns_sources = if _markdowns_sources.exists () { Some (_markdowns_sources) } else { None };
95		
96		let _generated = _outputs.join ("./hss-builder-generated-default.in");
97		
98		#[ cfg (feature = "builder-assets") ]
99		let _assets_route_base = Some (PathBuf::from ("/assets"));
100		
101		#[ cfg (feature = "builder-assets") ]
102		let _css_route_base = Some (PathBuf::from ("/assets/css"));
103		#[ cfg (feature = "builder-assets") ]
104		let _js_route_base = Some (PathBuf::from ("/assets/js"));
105		
106		#[ cfg (feature = "builder-assets") ]
107		let _images_route_base = Some (PathBuf::from ("/assets/images"));
108		#[ cfg (feature = "builder-assets") ]
109		let _icons_route_base = Some (PathBuf::from ("/assets/icons"));
110		#[ cfg (feature = "builder-assets") ]
111		let _favicons_route_base = Some (PathBuf::from ("/assets/favicons"));
112		#[ cfg (feature = "builder-assets") ]
113		let _fonts_route_base = Some (PathBuf::from ("/assets/fonts"));
114		
115		Self {
116				
117				sources : Some (_sources),
118				#[ cfg (feature = "builder-assets") ]
119				assets_sources : _assets_sources,
120				#[ cfg (feature = "builder-askama") ]
121				templates_sources : _templates_sources,
122				#[ cfg (feature = "builder-markdown") ]
123				markdowns_sources : _markdowns_sources,
124				
125				#[ cfg (feature = "builder-assets") ]
126				assets_route_base : _assets_route_base,
127				
128				#[ cfg (feature = "builder-assets") ]
129				css_route_base : _css_route_base,
130				#[ cfg (feature = "builder-assets") ]
131				js_route_base : _js_route_base,
132				
133				#[ cfg (feature = "builder-assets") ]
134				images_route_base : _images_route_base,
135				#[ cfg (feature = "builder-assets") ]
136				icons_route_base : _icons_route_base,
137				#[ cfg (feature = "builder-assets") ]
138				favicons_route_base : _favicons_route_base,
139				#[ cfg (feature = "builder-assets") ]
140				fonts_route_base : _fonts_route_base,
141				
142				outputs : _outputs,
143				generated : _generated,
144			}
145	}
146}
147
148
149impl BuilderConfiguration {
150	
151	pub fn minimal () -> BuilderResult<Self> {
152		
153		let _sources = Self::resolve_sources () ?;
154		let _outputs = Self::resolve_outputs () ?;
155		let _generated = _outputs.join ("./hss-builder-generated-default.in");
156		
157		let _builder = Self {
158				
159				sources : Some (_sources),
160				
161				#[ cfg (feature = "builder-assets") ]
162				assets_sources : None,
163				#[ cfg (feature = "builder-askama") ]
164				templates_sources : None,
165				#[ cfg (feature = "builder-markdown") ]
166				markdowns_sources : None,
167				
168				#[ cfg (feature = "builder-assets") ]
169				assets_route_base : None,
170				
171				#[ cfg (feature = "builder-assets") ]
172				css_route_base : None,
173				#[ cfg (feature = "builder-assets") ]
174				js_route_base : None,
175				
176				#[ cfg (feature = "builder-assets") ]
177				images_route_base : None,
178				#[ cfg (feature = "builder-assets") ]
179				icons_route_base : None,
180				#[ cfg (feature = "builder-assets") ]
181				favicons_route_base : None,
182				#[ cfg (feature = "builder-assets") ]
183				fonts_route_base : None,
184				
185				outputs : _outputs,
186				generated : _generated,
187			};
188		
189		Ok (_builder)
190	}
191	
192	pub fn resolve_sources () -> BuilderResult<PathBuf> {
193		let _sources = PathBuf::from (env::var ("CARGO_MANIFEST_DIR") .or_wrap (0x4c6c04d8) ?);
194		if ! _sources.is_dir () {
195			return Err (error_with_code (0x148bc689));
196		}
197		normalize_path (&_sources)
198	}
199	
200	pub fn resolve_outputs () -> BuilderResult<PathBuf> {
201		let _outputs = PathBuf::from (env::var ("OUT_DIR") .or_wrap (0xf039039f) ?);
202		if ! _outputs.is_dir () {
203			return Err (error_with_code (0xfcee6b4d));
204		}
205		normalize_path (&_outputs)
206	}
207}
208
209
210
211
212pub struct Builder {
213	configuration : BuilderConfiguration,
214	generated : String,
215	counter : u32,
216	route_names : Vec<String>,
217	dependencies : BTreeSet<PathBuf>,
218}
219
220
221impl Builder {
222	
223	pub fn new (_configuration : BuilderConfiguration) -> Self {
224		Self {
225				configuration : _configuration,
226				generated : String::with_capacity (1024 * 1024),
227				counter : 1,
228				route_names : Vec::new (),
229				dependencies : BTreeSet::new (),
230			}
231	}
232	
233	pub fn new_with_defaults () -> Self {
234		Self::new (BuilderConfiguration::default ())
235	}
236}
237
238
239
240
241impl Builder {
242	
243	
244	
245	
246	fn route_asset_raw (&mut self, _relative : &Path, _source : &Path, _content_type : &str, _route_base : Option<&Path>, _route_builder : &(impl RoutePathBuilder + ?Sized), _extensions_builder : &(impl RouteExtensionsBuilder + ?Sized), _macro : &str, _source_0 : &str, _source_relative : Option<&Path>) -> BuilderResult {
247		
248		let _route = _route_builder.build (_relative, &_source, _route_base, None) ?;
249		let _extensions = _extensions_builder.build () ?;
250		
251		let _id = self.generate_id ();
252		
253		let _description = if let Some (_relative) = _source_relative {
254			format! ("{} ({}, from = `{}`, file = `...{}`)", _macro, _content_type, _source_0, _relative.display ())
255		} else {
256			format! ("{} ({}, file = `{}`)", _macro, _content_type, _source_0)
257		};
258		
259		self.route_names.push (format! ("Route_{}", _id));
260		
261		#[ cfg (any (not (feature = "builder-relaxed-dependencies"), feature = "production")) ]
262		self.dependencies_include (&_source) ?;
263		
264		let _mode = "auto";
265		
266		writeln! (self.generated, "::hyper_static_server::resource! (Resource_{}, {}, {}, (relative_to_cwd, {:?}), {:?});", _id, _content_type, _mode, _source, _description) .infallible (0x5fa962ac);
267		writeln! (self.generated, "::hyper_static_server::route! (Route_{}, Resource_{}, {:?}, {});", _id, _id, _route, _extensions) .infallible (0x46de4cc9);
268		
269		Ok (())
270	}
271	
272	
273	
274	
275	#[ cfg (feature = "builder-askama") ]
276	pub fn route_askama (&mut self, _source_0 : &str, _context : Option<(&str, Option<&str>)>, _route_builder : &(impl RoutePathBuilder + ?Sized), _extensions_builder : &(impl RouteExtensionsBuilder + ?Sized)) -> BuilderResult {
277		
278		let _templates_sources = self.configuration.templates_sources.as_ref () .map (PathBuf::as_path);
279		let (_relative, _source) = self.resolve_file (_templates_sources, _source_0) ?;
280		
281		let _route_base = Some (Path::new ("/"));
282		
283		self.route_askama_0 (&_relative, &_source, _context, _route_base, _route_builder, _extensions_builder, _source_0, None)
284	}
285	
286	#[ cfg (feature = "builder-askama") ]
287	pub fn route_askamas (&mut self, _sources_0 : &str, _glob : Option<&str>, _context : Option<(&str, Option<&str>)>, _route_builder : &(impl RoutePathBuilder + ?Sized), _extensions_builder : &(impl RouteExtensionsBuilder + ?Sized)) -> BuilderResult {
288		
289		let _templates_sources = self.configuration.templates_sources.as_ref () .map (PathBuf::as_path);
290		let (_files, _folders) = self.resolve_files (_templates_sources, _sources_0, _glob) ?;
291		
292		#[ cfg (any (not (feature = "builder-relaxed-dependencies"), feature = "production")) ]
293		self.dependencies_include_all (_folders.iter () .map (PathBuf::as_path)) ?;
294		
295		let _route_base = Some (Path::new ("/"));
296		
297		for (_relative, _source) in _files.into_iter () {
298			
299			self.route_askama_0 (&_relative, &_source, _context, _route_base, _route_builder, _extensions_builder, _sources_0, Some (_relative.as_path ())) ?;
300		}
301		
302		Ok (())
303	}
304	
305	
306	#[ cfg (feature = "builder-askama") ]
307	fn route_askama_0 (&mut self, _relative : &Path, _source : &Path, _context : Option<(&str, Option<&str>)>, _route_base : Option<&Path>, _route_builder : &(impl RoutePathBuilder + ?Sized), _extensions_builder : &(impl RouteExtensionsBuilder + ?Sized), _source_0 : &str, _source_relative : Option<&Path>) -> BuilderResult {
308		
309		let _relative_1 = _relative.with_extension ("");
310		
311		let _template = _relative.strip_prefix ("/") .infallible (0x7285dc26);
312		
313		let _route = _route_builder.build (&_relative_1, &_source, _route_base, None) ?;
314		let _extensions = _extensions_builder.build () ?;
315		
316		let _id = self.generate_id ();
317		
318		let _content_type = "html";
319		let _description = if let Some (_relative) = _source_relative {
320			format! ("askama ({}, from = `{}`, file = `...{}`)", _content_type, _source_0, _relative.display ())
321		} else {
322			format! ("askama ({}, file = `{}`)", _content_type, _source_0)
323		};
324		
325		self.route_names.push (format! ("Route_{}", _id));
326		
327		#[ cfg (any (not (feature = "builder-relaxed-dependencies"), feature = "production")) ]
328		self.dependencies_include (&_source) ?;
329		
330		let (_context_type, _context_path) = _context.unwrap_or (("()", None));
331		if let Some (_context_path) = _context_path {
332			
333			let _sources = self.configuration.sources.as_ref () .map (PathBuf::as_path);
334			let (_, _context_path) = self.resolve_file (None, _context_path) ?;
335			let _context_encoding = match _context_path.extension () .or_wrap (0x70d90b37) ? .to_str () .or_wrap (0xa22f0541) ? {
336				"toml" => "toml",
337				"yaml" => "yaml",
338				"json" => "json",
339				_ =>
340					return Err (error_with_format (0xcbc42494, format_args! ("{}", _context_path.display ()))),
341			};
342			#[ cfg (any (not (feature = "builder-relaxed-dependencies"), feature = "production")) ]
343			self.dependencies_include (&_context_path) ?;
344			
345			writeln! (self.generated, "::hyper_static_server::askama! (Resource_{}, Template_{}, {{ type : {}, deserialize : ({:?}, {:?}) }}, {}, {:?}, {:?});", _id, _id, _context_type, _context_encoding, _context_path, _content_type, _template, _description) .infallible (0x35966385);
346		} else {
347			writeln! (self.generated, "::hyper_static_server::askama! (Resource_{}, Template_{}, {{ type : {} }}, {}, {:?}, {:?});", _id, _id, _context_type, _content_type, _template, _description) .infallible (0x35966385);
348		}
349		writeln! (self.generated, "::hyper_static_server::route! (Route_{}, Resource_{}, {:?}, {});", _id, _id, _route, _extensions) .infallible (0x41a5ee4c);
350		
351		Ok (())
352	}
353	
354	
355	#[ cfg (feature = "builder-askama") ]
356	pub fn watch_askama (&mut self, _source : &str) -> BuilderResult {
357		
358		let _templates_sources = self.configuration.templates_sources.as_ref () .map (PathBuf::as_path);
359		let (_relative, _source) = self.resolve_file (_templates_sources, _source) ?;
360		
361		#[ cfg (any (not (feature = "builder-relaxed-dependencies"), feature = "production")) ]
362		self.dependencies_include (&_source) ?;
363		
364		Ok (())
365	}
366	
367	#[ cfg (feature = "builder-askama") ]
368	pub fn watch_askamas (&mut self, _sources : &str, _glob : Option<&str>) -> BuilderResult {
369		
370		let _templates_sources = self.configuration.templates_sources.as_ref () .map (PathBuf::as_path);
371		let (_files, _folders) = self.resolve_files (_templates_sources, _sources, _glob) ?;
372		
373		#[ cfg (any (not (feature = "builder-relaxed-dependencies"), feature = "production")) ]
374		self.dependencies_include_all (_folders.iter () .map (PathBuf::as_path)) ?;
375		
376		#[ cfg (any (not (feature = "builder-relaxed-dependencies"), feature = "production")) ]
377		self.dependencies_include_all (_files.iter () .map (|_pair| _pair.1.as_path ())) ?;
378		
379		Ok (())
380	}
381	
382	
383	
384	
385	#[ cfg (feature = "builder-askama") ]
386	#[ cfg (feature = "builder-markdown") ]
387	pub fn route_markdown_askama (&mut self, _source_markdown_0 : &str, _source_template_0 : &str, _context : Option<&str>, _route_builder : &(impl RoutePathBuilder + ?Sized), _extensions_builder : &(impl RouteExtensionsBuilder + ?Sized)) -> BuilderResult {
388		
389		let _templates_sources = self.configuration.templates_sources.as_ref () .map (PathBuf::as_path);
390		let (_relative_template, _source_template) = self.resolve_file (_templates_sources, _source_template_0) ?;
391		
392		let _template = _relative_template.strip_prefix ("/") .infallible (0xda5e5ad4);
393		
394		#[ cfg (any (not (feature = "builder-relaxed-dependencies"), feature = "production")) ]
395		self.dependencies_include (&_source_template) ?;
396		
397		let _markdowns_sources = self.configuration.markdowns_sources.as_ref () .map (PathBuf::as_path);
398		let (_relative_markdown, _source_markdown) = self.resolve_file (_markdowns_sources, _source_markdown_0) ?;
399		
400		let _route_base = Some (Path::new ("/"));
401		
402		self.route_markdown_askama_0 (&_relative_markdown, &_source_markdown, &_template, _context, _route_base, _route_builder, _extensions_builder, _source_markdown_0, None)
403	}
404	
405	#[ cfg (feature = "builder-askama") ]
406	#[ cfg (feature = "builder-markdown") ]
407	pub fn route_markdowns_askama (&mut self, _sources_markdown_0 : &str, _glob : Option<&str>, _source_template_0 : &str, _context : Option<&str>, _route_builder : &(impl RoutePathBuilder + ?Sized), _extensions_builder : &(impl RouteExtensionsBuilder + ?Sized)) -> BuilderResult {
408		
409		let _templates_sources = self.configuration.templates_sources.as_ref () .map (PathBuf::as_path);
410		let (_relative_template, _source_template) = self.resolve_file (_templates_sources, _source_template_0) ?;
411		
412		let _template = _relative_template.strip_prefix ("/") .infallible (0xe0168bd3);
413		
414		#[ cfg (any (not (feature = "builder-relaxed-dependencies"), feature = "production")) ]
415		self.dependencies_include (&_source_template) ?;
416		
417		let _markdowns_sources = self.configuration.markdowns_sources.as_ref () .map (PathBuf::as_path);
418		let (_files_markdown, _folders_markdown) = self.resolve_files (_markdowns_sources, _sources_markdown_0, _glob) ?;
419		
420		#[ cfg (any (not (feature = "builder-relaxed-dependencies"), feature = "production")) ]
421		self.dependencies_include_all (_folders_markdown.iter () .map (PathBuf::as_path)) ?;
422		
423		let _route_base = Some (Path::new ("/"));
424		
425		for (_relative_markdown, _source_markdown) in _files_markdown.into_iter () {
426			
427			self.route_markdown_askama_0 (&_relative_markdown, &_source_markdown, &_template, _context, _route_base, _route_builder, _extensions_builder, _sources_markdown_0, Some (_relative_markdown.as_path ())) ?;
428		}
429		
430		Ok (())
431	}
432	
433	
434	#[ cfg (feature = "builder-askama") ]
435	#[ cfg (feature = "builder-markdown") ]
436	fn route_markdown_askama_0 (&mut self, _relative_markdown : &Path, _source_markdown : &Path, _template : &Path, _context : Option<&str>, _route_base : Option<&Path>, _route_builder : &(impl RoutePathBuilder + ?Sized), _extensions_builder : &(impl RouteExtensionsBuilder + ?Sized), _source_0 : &str, _source_relative : Option<&Path>) -> BuilderResult {
437		
438		let _relative_markdown_1 = _relative_markdown.with_extension ("");
439		
440		let (_output_body, _output_title, _output_metadata, _output_frontmatter, _refresher) = if cfg! (any (not (feature = "builder-relaxed-dependencies"), not (feature = "builder-markdown-dynamic"), not (feature = "builder-askama-dynamic"), feature = "production")) {
441			
442			self.dependencies_include (_source_markdown) ?;
443			
444			let _markdown = self.compile_markdown_body (_source_markdown, true) ?;
445			let _markdown_body = _markdown.body;
446			let _markdown_metadata = _markdown.metadata;
447			let _markdown_frontmatter = _markdown.frontmatter;
448			
449			let _markdown_title = _markdown_metadata.title.as_ref () .map (String::as_str) .unwrap_or ("");
450			
451			let _output_title = self.configuration.outputs.join (fingerprint_data (&_markdown_title)) .with_extension ("txt");
452			create_file_from_str (&_output_title, _markdown_title, true, true) ?;
453			
454			let _output_body = self.configuration.outputs.join (fingerprint_data (&_markdown_body)) .with_extension ("html");
455			create_file_from_str (&_output_body, &_markdown_body, true, true) ?;
456			
457			let _output_metadata = self.configuration.outputs.join (fingerprint_data (&_markdown_body)) .with_extension ("meta");
458			let _markdown_metadata = ::serde_json::to_string_pretty (&_markdown_metadata) .or_wrap (0x94fe158d) ?;
459			create_file_from_str (&_output_metadata, &_markdown_metadata, true, true) ?;
460			
461			let _output_frontmatter = if let Some (_frontmatter) = _markdown_frontmatter {
462				let _encoding = _frontmatter.encoding.as_ref ();
463				let _data = _frontmatter.data.as_ref ();
464				let _extension = match _encoding {
465					"toml" => "toml",
466					"yaml" => "yaml",
467					"json" => "json",
468					_ =>
469						return Err (error_with_format (0x75f4427f, format_args! ("{}", _encoding))),
470				};
471				let _path = self.configuration.outputs.join (fingerprint_data (&_data)) .with_extension (_extension);
472				create_file_from_str (&_path, &_data, true, true) ?;
473				Some ((_extension, _path))
474			} else {
475				None
476			};
477			
478			(_output_body, _output_title, _output_metadata, _output_frontmatter, false)
479			
480		} else {
481			
482			let _token = fingerprint_data (_source_markdown.to_string_lossy () .as_bytes ());
483			
484			let _output_body = self.configuration.outputs.join (&_token) .with_extension ("html");
485			
486			let _output_title = self.configuration.outputs.join (&_token) .with_extension ("txt");
487			
488			let _output_metadata = self.configuration.outputs.join (&_token) .with_extension ("meta");
489			
490			let _output_frontmatter = self.configuration.outputs.join (&_token) .with_extension ("data");
491			
492			(_output_body, _output_title, _output_metadata, Some (("auto", _output_frontmatter)), true)
493		};
494		
495		let _route = _route_builder.build (&_relative_markdown_1, _source_markdown, _route_base, None) ?;
496		let _extensions = _extensions_builder.build () ?;
497		
498		let _id = self.generate_id ();
499		
500		let _content_type = "html";
501		let _description = if let Some (_relative) = _source_relative {
502			format! ("markdown_askama ({}, from = `{}`, file = `...{}`)", _content_type, _source_0, _relative.display ())
503		} else {
504			format! ("markdown_askama ({}, file = `{}`)", _content_type, _source_0)
505		};
506		
507		self.route_names.push (format! ("Route_{}", _id));
508		
509		let _refresher_code = if _refresher {
510			let (_context_encoding, _context_path) = _output_frontmatter.as_ref () .or_panic (0xc27ad812);
511			writeln! (self.generated, "::hyper_static_server::resource_markdown_refresher! (Refresher_{}, (relative_to_cwd, {:?}), (relative_to_cwd, {:?}), (relative_to_cwd, {:?}), (relative_to_cwd, {:?}), (relative_to_cwd, {:?}));", _id, _source_markdown, _output_body, _output_title, _output_metadata, _context_path) .infallible (0x2b54879e);
512			format! ("Refresher_{},", _id)
513		} else {
514			String::new ()
515		};
516		
517		if let Some ((_context_encoding, _context_path)) = _output_frontmatter {
518			if let Some (_context_type) = _context {
519				writeln! (self.generated, "::hyper_static_server::askama_document! (Resource_{}, Template_{}, {{ type : {}, deserialize : ({:?}, {:?}) }}, {}, {:?}, {:?}, {:?}, {:?}, {} {:?});", _id, _id, _context_type, _context_encoding, _context_path, _content_type, _template, _output_body, _output_title, _output_metadata, _refresher_code, _description) .infallible (0xd64341cb);
520			} else {
521				let _context_type = _context.unwrap_or ("()");
522				writeln! (self.generated, "::hyper_static_server::askama_document! (Resource_{}, Template_{}, {{ type : {} }}, {}, {:?}, {:?}, {:?}, {:?}, {} {:?});", _id, _id, _context_type, _content_type, _template, _output_body, _output_title, _output_metadata, _refresher_code, _description) .infallible (0xd64341cb);
523			}
524		} else {
525			let _context_type = _context.unwrap_or ("()");
526			writeln! (self.generated, "::hyper_static_server::askama_document! (Resource_{}, Template_{}, {{ type : {} }}, {}, {:?}, {:?}, {:?}, {:?}, {} {:?});", _id, _id, _context_type, _content_type, _template, _output_body, _output_title, _output_metadata, _refresher_code, _description) .infallible (0xd64341cb);
527		}
528		
529		writeln! (self.generated, "::hyper_static_server::route! (Route_{}, Resource_{}, {:?}, {});", _id, _id, _route, _extensions) .infallible (0xafb30ea0);
530		
531		Ok (())
532	}
533	
534	
535	
536	
537	#[ cfg (feature = "builder-markdown") ]
538	pub fn route_markdown (&mut self, _source_0 : &str, _header_source : Option<&str>, _footer_source : Option<&str>, _route_builder : &(impl RoutePathBuilder + ?Sized), _extensions_builder : &(impl RouteExtensionsBuilder + ?Sized)) -> BuilderResult {
539		
540		let _markdowns_sources = self.configuration.markdowns_sources.as_ref () .map (PathBuf::as_path);
541		let (_relative, _source) = self.resolve_file (_markdowns_sources, _source_0) ?;
542		
543		let _route_base = Some (Path::new ("/"));
544		
545		self.route_markdown_0 (&_relative, &_source, _header_source, _footer_source, _route_base, _route_builder, _extensions_builder, _source_0, None)
546	}
547	
548	#[ cfg (feature = "builder-markdown") ]
549	pub fn route_markdowns (&mut self, _sources_0 : &str, _glob : Option<&str>, _header_source : Option<&str>, _footer_source : Option<&str>, _route_builder : &(impl RoutePathBuilder + ?Sized), _extensions_builder : &(impl RouteExtensionsBuilder + ?Sized)) -> BuilderResult {
550		
551		let _markdowns_sources = self.configuration.markdowns_sources.as_ref () .map (PathBuf::as_path);
552		let (_files, _folders) = self.resolve_files (_markdowns_sources, _sources_0, _glob) ?;
553		
554		#[ cfg (any (not (feature = "builder-relaxed-dependencies"), feature = "production")) ]
555		self.dependencies_include_all (_folders.iter () .map (PathBuf::as_path)) ?;
556		
557		let _route_base = Some (Path::new ("/"));
558		
559		for (_relative, _source) in _files.into_iter () {
560			
561			if _source.extension () .or_wrap (0xc1ecda55) ? != "md" {
562				return Err (error_with_format (0x393ea45d, format_args! ("{}", _source.display ())));
563			}
564			
565			self.route_markdown_0 (&_relative, &_source, _header_source, _footer_source, _route_base, _route_builder, _extensions_builder, _sources_0, Some (_relative.as_path ())) ?;
566		}
567		
568		Ok (())
569	}
570	
571	
572	#[ cfg (feature = "builder-markdown") ]
573	fn route_markdown_0 (&mut self, _relative : &Path, _source : &Path, _header_source : Option<&str>, _footer_source : Option<&str>, _route_base : Option<&Path>, _route_builder : &(impl RoutePathBuilder + ?Sized), _extensions_builder : &(impl RouteExtensionsBuilder + ?Sized), _source_0 : &str, _source_relative : Option<&Path>) -> BuilderResult {
574		
575		let _markdowns_sources = self.configuration.markdowns_sources.as_ref () .map (PathBuf::as_path);
576		let _header_source = _header_source.map (|_source| BuilderResult::Ok (self.resolve_file (_markdowns_sources, _source) ? .1)) .transpose () ?;
577		let _footer_source = _footer_source.map (|_source| BuilderResult::Ok (self.resolve_file (_markdowns_sources, _source) ? .1)) .transpose () ?;
578		
579		let _relative_1 = _relative.with_extension ("");
580		
581		if cfg! (any (not (feature = "builder-relaxed-dependencies"), not (feature = "builder-markdown-dynamic"), feature = "production")) {
582			
583			#[ cfg (any (not (feature = "builder-relaxed-dependencies"), not (feature = "builder-markdown-dynamic"), feature = "production")) ]
584			{
585				self.dependencies_include (&_source) ?;
586				if let Some (_header_source) = &_header_source {
587					self.dependencies_include (_header_source) ?;
588				}
589				if let Some (_footer_source) = &_footer_source {
590					self.dependencies_include (_footer_source) ?;
591				}
592			}
593			
594			let _header_source = _header_source.as_ref () .map (PathBuf::as_path);
595			let _footer_source = _footer_source.as_ref () .map (PathBuf::as_path);
596			
597			let _html_data = self.compile_markdown_html (_source, _header_source, _footer_source) ?;
598			
599			let _output = self.configuration.outputs.join (fingerprint_data (&_html_data)) .with_extension ("html");
600			create_file_from_str (&_output, &_html_data, true, true) ?;
601			
602			// FIXME:  Here the second argument should be `_source`.
603			self.route_asset_raw (&_relative_1, &_output, "html", _route_base, _route_builder, _extensions_builder, "markdown", _source_0, _source_relative) ?;
604			
605			self.dependencies_exclude (&_output) ?;
606			
607		} else {
608			
609			let _route = _route_builder.build (&_relative_1, &_source, _route_base, None) ?;
610			let _extensions = _extensions_builder.build () ?;
611			
612			let _id = self.generate_id ();
613			
614			let _description = format! ("{} (file = `{}`)", "resource_markdown", _source_0);
615			
616			self.route_names.push (format! ("Route_{}", _id));
617			
618			writeln! (self.generated, "::hyper_static_server::resource_markdown_dynamic! (Resource_{}, {}, (relative_to_cwd, {:?}), (relative_to_cwd, {:?}), (relative_to_cwd, {:?}), {:?});", _id, "html", _source, _header_source, _footer_source, _description) .infallible (0x15f089dc);
619			writeln! (self.generated, "::hyper_static_server::route! (Route_{}, Resource_{}, {:?}, {});", _id, _id, _route, _extensions) .infallible (0xbf41dd16);
620		}
621		
622		Ok (())
623	}
624	
625	
626	
627	
628	#[ cfg (feature = "builder-assets") ]
629	pub fn route_css (&mut self, _source_0 : &str, _route_builder : &(impl RoutePathBuilder + ?Sized), _extensions_builder : &(impl RouteExtensionsBuilder + ?Sized)) -> BuilderResult {
630		
631		let _css_sources = self.configuration.assets_sources.as_ref () .map (PathBuf::as_path);
632		let (_relative, _source) = self.resolve_file (_css_sources, _source_0) ?;
633		
634		let _route_base = self.configuration.css_route_base.clone ();
635		let _route_base = _route_base.as_ref () .map (PathBuf::as_path);
636		
637		self.route_asset_raw (&_relative, &_source, "css", _route_base, _route_builder, _extensions_builder, "resource_css", _source_0, None)
638	}
639	
640	
641	#[ cfg (feature = "builder-assets") ]
642	#[ cfg (feature = "builder-assets-sass") ]
643	pub fn route_sass (&mut self, _source_0 : &str, _route_builder : &(impl RoutePathBuilder + ?Sized), _extensions_builder : &(impl RouteExtensionsBuilder + ?Sized)) -> BuilderResult {
644		
645		let _css_sources = self.configuration.assets_sources.as_ref () .map (PathBuf::as_path);
646		let (_relative, _source) = self.resolve_file (_css_sources, _source_0) ?;
647		
648		let _relative_1 = _relative.with_extension ("css");
649		
650		let _route_base = self.configuration.css_route_base.clone ();
651		let _route_base = _route_base.as_ref () .map (PathBuf::as_path);
652		
653		if cfg! (any (not (feature = "builder-relaxed-dependencies"), not (feature = "builder-assets-sass-dynamic"), feature = "production")) {
654			
655			self.dependencies_include (&_source) ?;
656			
657			let _compiled = self.compile_sass (&_source) ?;
658			
659			let _output = self.configuration.outputs.join (fingerprint_data (&_compiled)) .with_extension ("css");
660			create_file_from_str (&_output, &_compiled, true, true) ?;
661			
662			// FIXME:  Here the second argument should be `_source`.
663			self.route_asset_raw (&_relative_1, &_output, "css", _route_base, _route_builder, _extensions_builder, "resource_sass", _source_0, None) ?;
664			
665			self.dependencies_exclude (&_output) ?;
666			
667		} else {
668			
669			let _route = _route_builder.build (&_relative_1, &_source, _route_base, None) ?;
670			let _extensions = _extensions_builder.build () ?;
671			
672			let _id = self.generate_id ();
673			
674			let _description = format! ("{} (file = `{}`)", "resource_sass", _source_0);
675			
676			self.route_names.push (format! ("Route_{}", _id));
677			
678			writeln! (self.generated, "::hyper_static_server::resource_sass_dynamic! (Resource_{}, {}, (relative_to_cwd, {:?}), {:?});", _id, "css", _source, _description) .infallible (0xb7dd2208);
679			writeln! (self.generated, "::hyper_static_server::route! (Route_{}, Resource_{}, {:?}, {});", _id, _id, _route, _extensions) .infallible (0x506e8636);
680		}
681		
682		Ok (())
683	}
684	
685	
686	
687	
688	#[ cfg (feature = "builder-assets") ]
689	pub fn route_js (&mut self, _source_0 : &str, _route_builder : &(impl RoutePathBuilder + ?Sized), _extensions_builder : &(impl RouteExtensionsBuilder + ?Sized)) -> BuilderResult {
690		
691		let _js_sources = self.configuration.assets_sources.as_ref () .map (PathBuf::as_path);
692		let (_relative, _source) = self.resolve_file (_js_sources, _source_0) ?;
693		
694		let _route_base = self.configuration.js_route_base.clone ();
695		let _route_base = _route_base.as_ref () .map (PathBuf::as_path);
696		
697		self.route_asset_raw (&_relative, &_source, "js", _route_base, _route_builder, _extensions_builder, "resource_js", _source_0, None)
698	}
699	
700	
701	
702	
703	#[ cfg (feature = "builder-assets") ]
704	pub fn route_image (&mut self, _source_0 : &str, _route_builder : &(impl RoutePathBuilder + ?Sized), _extensions_builder : &(impl RouteExtensionsBuilder + ?Sized)) -> BuilderResult {
705		
706		let _assets_sources = self.configuration.assets_sources.as_ref () .map (PathBuf::as_path);
707		let (_relative, _source) = self.resolve_file (_assets_sources, _source_0) ?;
708		
709		let _route_base = self.configuration.images_route_base.clone ();
710		let _route_base = _route_base.as_ref () .map (PathBuf::as_path);
711		
712		self.route_image_0 (&_relative, &_source, _route_base, _route_builder, _extensions_builder, "resource_image", _source_0, None)
713	}
714	
715	#[ cfg (feature = "builder-assets") ]
716	pub fn route_images (&mut self, _sources_0 : &str, _glob : Option<&str>, _route_builder : &(impl RoutePathBuilder + ?Sized), _extensions_builder : &(impl RouteExtensionsBuilder + ?Sized)) -> BuilderResult {
717		
718		let _assets_sources = self.configuration.assets_sources.as_ref () .map (PathBuf::as_path);
719		let (_files, _folders) = self.resolve_files (_assets_sources, _sources_0, _glob) ?;
720		
721		#[ cfg (any (not (feature = "builder-relaxed-dependencies"), feature = "production")) ]
722		self.dependencies_include_all (_folders.iter () .map (PathBuf::as_path)) ?;
723		
724		let _route_base = self.configuration.images_route_base.clone ();
725		let _route_base = _route_base.as_ref () .map (PathBuf::as_path);
726		
727		for (_relative, _source) in _files.into_iter () {
728			
729			self.route_image_0 (&_relative, &_source, _route_base, _route_builder, _extensions_builder, "resource_image", _sources_0, Some (_relative.as_path ())) ?;
730		}
731		
732		Ok (())
733	}
734	
735	
736	#[ cfg (feature = "builder-assets") ]
737	pub fn route_icon (&mut self, _source_0 : &str, _route_builder : &(impl RoutePathBuilder + ?Sized), _extensions_builder : &(impl RouteExtensionsBuilder + ?Sized)) -> BuilderResult {
738		
739		let _assets_sources = self.configuration.assets_sources.as_ref () .map (PathBuf::as_path);
740		let (_relative, _source) = self.resolve_file (_assets_sources, _source_0) ?;
741		
742		let _route_base = self.configuration.icons_route_base.clone ();
743		let _route_base = _route_base.as_ref () .map (PathBuf::as_path);
744		
745		self.route_image_0 (&_relative, &_source, _route_base, _route_builder, _extensions_builder, "resource_icon", _source_0, None)
746	}
747	
748	#[ cfg (feature = "builder-assets") ]
749	pub fn route_icons (&mut self, _sources_0 : &str, _glob : Option<&str>, _route_builder : &(impl RoutePathBuilder + ?Sized), _extensions_builder : &(impl RouteExtensionsBuilder + ?Sized)) -> BuilderResult {
750		
751		let _assets_sources = self.configuration.assets_sources.as_ref () .map (PathBuf::as_path);
752		let (_files, _folders) = self.resolve_files (_assets_sources, _sources_0, _glob) ?;
753		
754		#[ cfg (any (not (feature = "builder-relaxed-dependencies"), feature = "production")) ]
755		self.dependencies_include_all (_folders.iter () .map (PathBuf::as_path)) ?;
756		
757		let _route_base = self.configuration.icons_route_base.clone ();
758		let _route_base = _route_base.as_ref () .map (PathBuf::as_path);
759		
760		for (_relative, _source) in _files.into_iter () {
761			
762			self.route_image_0 (&_relative, &_source, _route_base, _route_builder, _extensions_builder, "resource_icon", _sources_0, Some (_relative.as_path ())) ?;
763		}
764		
765		Ok (())
766	}
767	
768	
769	#[ cfg (feature = "builder-assets") ]
770	pub fn route_favicon (&mut self, _source_0 : &str, _route_builder : &(impl RoutePathBuilder + ?Sized), _extensions_builder : &(impl RouteExtensionsBuilder + ?Sized)) -> BuilderResult {
771		
772		let _assets_sources = self.configuration.assets_sources.as_ref () .map (PathBuf::as_path);
773		let (_relative, _source) = self.resolve_file (_assets_sources, _source_0) ?;
774		
775		let _route_base = self.configuration.favicons_route_base.clone ();
776		let _route_base = _route_base.as_ref () .map (PathBuf::as_path);
777		
778		self.route_image_0 (&_relative, &_source, _route_base, _route_builder, _extensions_builder, "resource_favicon", _source_0, None)
779	}
780	
781	#[ cfg (feature = "builder-assets") ]
782	pub fn route_favicons (&mut self, _sources_0 : &str, _glob : Option<&str>, _route_builder : &(impl RoutePathBuilder + ?Sized), _extensions_builder : &(impl RouteExtensionsBuilder + ?Sized)) -> BuilderResult {
783		
784		let _assets_sources = self.configuration.assets_sources.as_ref () .map (PathBuf::as_path);
785		let (_files, _folders) = self.resolve_files (_assets_sources, _sources_0, _glob) ?;
786		
787		#[ cfg (any (not (feature = "builder-relaxed-dependencies"), feature = "production")) ]
788		self.dependencies_include_all (_folders.iter () .map (PathBuf::as_path)) ?;
789		
790		let _route_base = self.configuration.favicons_route_base.clone ();
791		let _route_base = _route_base.as_ref () .map (PathBuf::as_path);
792		
793		for (_relative, _source) in _files.into_iter () {
794			
795			self.route_image_0 (&_relative, &_source, _route_base, _route_builder, _extensions_builder, "resource_favicon", _sources_0, Some (_relative.as_path ())) ?;
796		}
797		
798		Ok (())
799	}
800	
801	
802	#[ cfg (feature = "builder-assets") ]
803	fn route_image_0 (&mut self, _relative : &Path, _source : &Path, _route_base : Option<&Path>, _route_builder : &(impl RoutePathBuilder + ?Sized), _extensions_builder : &(impl RouteExtensionsBuilder + ?Sized), _macro : &str, _source_0 : &str, _source_relative : Option<&Path>) -> BuilderResult {
804		
805		let _content_type = detect_content_type_from_extension (&_source) ?;
806		match _content_type {
807			"png" | "jpeg" | "icon" | "svg" =>
808				(),
809			_ =>
810				return Err (error_with_format (0x0fd2d804, format_args! ("{}", _source.display ()))),
811		};
812		
813		self.route_asset_raw (_relative, _source, _content_type, _route_base, _route_builder, _extensions_builder, _macro, _source_0, _source_relative)
814	}
815	
816	
817	
818	
819	#[ cfg (feature = "builder-assets") ]
820	pub fn route_font (&mut self, _source_0 : &str, _route_builder : &(impl RoutePathBuilder + ?Sized), _extensions_builder : &(impl RouteExtensionsBuilder + ?Sized)) -> BuilderResult {
821		
822		let _assets_sources = self.configuration.assets_sources.as_ref () .map (PathBuf::as_path);
823		let (_relative, _source) = self.resolve_file (_assets_sources, _source_0) ?;
824		
825		let _route_base = self.configuration.fonts_route_base.clone ();
826		let _route_base = _route_base.as_ref () .map (PathBuf::as_path);
827		
828		self.route_font_0 (&_relative, &_source, _route_base, _route_builder, _extensions_builder, _source_0, None)
829	}
830	
831	#[ cfg (feature = "builder-assets") ]
832	pub fn route_fonts (&mut self, _sources_0 : &str, _glob : Option<&str>, _route_builder : &(impl RoutePathBuilder + ?Sized), _extensions_builder : &(impl RouteExtensionsBuilder + ?Sized)) -> BuilderResult {
833		
834		let _assets_sources = self.configuration.assets_sources.as_ref () .map (PathBuf::as_path);
835		let (_files, _folders) = self.resolve_files (_assets_sources, _sources_0, _glob) ?;
836		
837		#[ cfg (any (not (feature = "builder-relaxed-dependencies"), feature = "production")) ]
838		self.dependencies_include_all (_folders.iter () .map (PathBuf::as_path)) ?;
839		
840		let _route_base = self.configuration.fonts_route_base.clone ();
841		let _route_base = _route_base.as_ref () .map (PathBuf::as_path);
842		
843		for (_relative, _source) in _files.into_iter () {
844			
845			self.route_font_0 (&_relative, &_source, _route_base, _route_builder, _extensions_builder, _sources_0, Some (_relative.as_path ())) ?;
846		}
847		
848		Ok (())
849	}
850	
851	
852	#[ cfg (feature = "builder-assets") ]
853	fn route_font_0 (&mut self, _relative : &Path, _source : &Path, _route_base : Option<&Path>, _route_builder : &(impl RoutePathBuilder + ?Sized), _extensions_builder : &(impl RouteExtensionsBuilder + ?Sized), _source_0 : &str, _source_relative : Option<&Path>) -> BuilderResult {
854		
855		let _content_type = detect_content_type_from_extension (&_source) ?;
856		match _content_type {
857			"font_ttf" | "font_otf" | "font_woff" | "font_woff2" =>
858				(),
859			_ =>
860				return Err (error_with_format (0x1a4ccbf4, format_args! ("{}", _source.display ()))),
861		};
862		
863		self.route_asset_raw (_relative, _source, _content_type, _route_base, _route_builder, _extensions_builder, "resource_font", _source_0, _source_relative)
864	}
865	
866	
867	
868	
869	#[ cfg (feature = "builder-assets") ]
870	pub fn route_asset (&mut self, _source_0 : &str, _content_type : Option<&str>, _route_builder : &(impl RoutePathBuilder + ?Sized), _extensions_builder : &(impl RouteExtensionsBuilder + ?Sized)) -> BuilderResult {
871		
872		let _assets_sources = self.configuration.assets_sources.as_ref () .map (PathBuf::as_path);
873		let (_relative, _source) = self.resolve_file (_assets_sources, _source_0) ?;
874		
875		let _route_base = self.configuration.assets_route_base.clone ();
876		let _route_base = _route_base.as_ref () .map (PathBuf::as_path);
877		
878		self.route_asset_0 (&_relative, &_source, _content_type, _route_base, _route_builder, _extensions_builder, _source_0, None)
879	}
880	
881	#[ cfg (feature = "builder-assets") ]
882	pub fn route_assets (&mut self, _sources_0 : &str, _glob : Option<&str>, _content_type : Option<&str>, _route_builder : &(impl RoutePathBuilder + ?Sized), _extensions_builder : &(impl RouteExtensionsBuilder + ?Sized)) -> BuilderResult {
883		
884		let _assets_sources = self.configuration.assets_sources.as_ref () .map (PathBuf::as_path);
885		let (_files, _folders) = self.resolve_files (_assets_sources, _sources_0, _glob) ?;
886		
887		#[ cfg (any (not (feature = "builder-relaxed-dependencies"), feature = "production")) ]
888		self.dependencies_include_all (_folders.iter () .map (PathBuf::as_path)) ?;
889		
890		let _route_base = self.configuration.assets_route_base.clone ();
891		let _route_base = _route_base.as_ref () .map (PathBuf::as_path);
892		
893		for (_relative, _source) in _files.into_iter () {
894			
895			self.route_asset_0 (&_relative, &_source, _content_type, _route_base, _route_builder, _extensions_builder, _sources_0, Some (_relative.as_path ())) ?;
896		}
897		
898		Ok (())
899	}
900	
901	
902	#[ cfg (feature = "builder-assets") ]
903	fn route_asset_0 (&mut self, _relative : &Path, _source : &Path, _content_type : Option<&str>, _route_base : Option<&Path>, _route_builder : &(impl RoutePathBuilder + ?Sized), _extensions_builder : &(impl RouteExtensionsBuilder + ?Sized), _source_0 : &str, _source_relative : Option<&Path>) -> BuilderResult {
904		
905		let _content_type = _content_type.map_or_else (|| detect_content_type_from_extension (&_source), |_content_type| Ok (_content_type)) ?;
906		
907		self.route_asset_raw (_relative, _source, _content_type, _route_base, _route_builder, _extensions_builder, "resource_asset", _source_0, _source_relative)
908	}
909	
910	
911	
912	
913	#[ cfg (feature = "builder-sitemaps") ]
914	pub fn route_sitemap (&mut self, _prefix : &str, _format : &str, _route_builder : &(impl RoutePathBuilder + ?Sized), _extensions_builder : &(impl RouteExtensionsBuilder + ?Sized)) -> BuilderResult {
915		
916		let _route = _route_builder.build (Path::new (""), Path::new (""), None, None) ?;
917		let _extensions = _extensions_builder.build () ?;
918		let _format = token_tree_parse (_format) ?;
919		
920		let _id = self.generate_id ();
921		
922		self.route_names.push (format! ("Route_{}", _id));
923		
924		writeln! (self.generated, "::hyper_static_server::route_sitemap! (Route_{}, {:?}, {:?}, {}, {});", _id, _route, _prefix, _format, _extensions) .infallible (0x5f529a53);
925		
926		Ok (())
927	}
928	
929	
930	
931	
932	#[ cfg (feature = "builder-assets") ]
933	pub fn watch_asset (&mut self, _source : &str) -> BuilderResult {
934		
935		let _assets_sources = self.configuration.assets_sources.as_ref () .map (PathBuf::as_path);
936		let (_relative, _source) = self.resolve_file (_assets_sources, _source) ?;
937		
938		#[ cfg (any (not (feature = "builder-relaxed-dependencies"), feature = "production")) ]
939		self.dependencies_include (&_source) ?;
940		
941		Ok (())
942	}
943	
944	#[ cfg (feature = "builder-assets") ]
945	pub fn watch_assets (&mut self, _sources : &str, _glob : Option<&str>) -> BuilderResult {
946		
947		let _assets_sources = self.configuration.assets_sources.as_ref () .map (PathBuf::as_path);
948		let (_files, _folders) = self.resolve_files (_assets_sources, _sources, _glob) ?;
949		
950		#[ cfg (any (not (feature = "builder-relaxed-dependencies"), feature = "production")) ]
951		self.dependencies_include_all (_folders.iter () .map (PathBuf::as_path)) ?;
952		
953		#[ cfg (any (not (feature = "builder-relaxed-dependencies"), feature = "production")) ]
954		self.dependencies_include_all (_files.iter () .map (|_pair| _pair.1.as_path ())) ?;
955		
956		Ok (())
957	}
958	
959	
960	
961	
962	pub fn generate (mut self) -> BuilderResult {
963		
964		self.dependencies_extend () ?;
965		
966		writeln! (self.generated, "::hyper_static_server::routes! (Routes, [") .infallible (0x4bf5618f);
967		for _route_name in self.route_names.into_iter () {
968			writeln! (self.generated, "\t{},", _route_name) .infallible (0x894377dd);
969		}
970		writeln! (self.generated, "]);") .infallible (0x28d1ed4d);
971		
972		writeln! (self.generated, "::hyper_static_server::dependencies! (Dependencies, [") .infallible (0x1a6c02cd);
973		for _dependency in self.dependencies.iter () {
974			writeln! (self.generated, "\t{:?},", _dependency) .infallible (0x9df69eb7);
975		}
976		writeln! (self.generated, "]);") .infallible (0x57d05438);
977		
978		create_file_from_str (&self.configuration.generated, &self.generated, false, true) ?;
979		
980		if false {
981			eprintln! ("--------------------------------------------------------------------------------");
982			eprintln! ("{}", self.generated);
983			eprintln! ("--------------------------------------------------------------------------------");
984		}
985		
986		for _dependency in self.dependencies {
987			println! ("cargo:rerun-if-changed={}", _dependency.display ());
988		}
989		
990		Ok (())
991	}
992}
993
994
995
996
997impl Builder {
998	
999	
1000	fn resolve_file (&self, _root : Option<&Path>, _source : &str) -> BuilderResult<(PathBuf, PathBuf)> {
1001		
1002		let (_path, _relative_root) = self.resolve_source (_root, _source, true) ?;
1003		
1004		if ! _path.is_file () {
1005			return Err (error_with_format (0x039d945b, format_args! ("{}", _path.display ())));
1006		}
1007		
1008		self.resolve_relative_and_path (&_path, &_relative_root)
1009	}
1010	
1011	
1012	fn resolve_files (&self, _root : Option<&Path>, _sources : &str, _glob : Option<&str>) -> BuilderResult<(Vec<(PathBuf, PathBuf)>, Vec<PathBuf>)> {
1013		
1014		let (_root, _relative_root) = self.resolve_source (_root, _sources, false) ?;
1015		
1016		if ! _root.is_dir () {
1017			return Err (error_with_code (0x621693a6));
1018		}
1019		
1020		let _glob = _glob.map (|_pattern| globset::Glob::new (_pattern) .or_wrap (0xf68023ce)) .transpose () ?;
1021		let _glob = _glob.map (|_pattern| _pattern.compile_matcher ());
1022		
1023		let mut _files = Vec::new ();
1024		let mut _folders = Vec::new ();
1025		
1026		let _walker = walkdir::WalkDir::new (&_root)
1027				.follow_links (true)
1028				.sort_by (|_left, _right| ffi::OsStr::cmp (_left.file_name (), _right.file_name ()));
1029		
1030		for _entry in _walker {
1031			let _entry = _entry ?;
1032			let _path = _entry.path ();
1033			
1034			if _path.is_file () {
1035				
1036				if let Some (_glob) = _glob.as_ref () {
1037					if ! _glob.is_match (_path) {
1038						continue;
1039					}
1040				}
1041				
1042				let _relative_and_path = self.resolve_relative_and_path (_path, &_relative_root) ?;
1043				
1044				_files.push (_relative_and_path);
1045			}
1046			
1047			if _path.is_dir () {
1048				
1049				let _path = normalize_path (_path) ?;
1050				
1051				_folders.push (_path);
1052			}
1053		}
1054		
1055		Ok ((_files, _folders))
1056	}
1057	
1058	
1059	fn resolve_source (&self, _root : Option<&Path>, _source : &str, _name_only : bool) -> BuilderResult<(PathBuf, PathBuf)> {
1060		
1061		let _path = if _source.starts_with ("_/") || (_source == "_") {
1062			let _root = _root.or_wrap (0x6e3319c9) ?;
1063			if _source != "_" {
1064				_root.join (&_source[2..])
1065			} else {
1066				_root.to_owned ()
1067			}
1068			
1069		} else if _source.starts_with ("./") || _source.starts_with ("..") || (_source == ".") || (_source == "..") {
1070			let _root = self.configuration.sources.as_ref () .or_wrap (0x0791a9b4) ?;
1071			_root.join (&_source)
1072			
1073		} else if _source.starts_with (">") {
1074			PathBuf::from (&_source[1..])
1075			
1076		} else {
1077			return Err (error_with_code (0x41071330));
1078		};
1079		
1080		if ! _path.exists () {
1081			return Err (error_with_format (0x1086bd9d, format_args! ("{}", _path.display ())));
1082		}
1083		
1084		if _name_only {
1085			let _relative_root = _path.parent () .or_wrap (0x067a2cad) ? .to_path_buf ();
1086			Ok ((_path, _relative_root))
1087		} else {
1088			Ok ((_path.clone (), _path))
1089		}
1090	}
1091	
1092	
1093	fn resolve_relative_and_path (&self, _path : &Path, _relative_root : &Path) -> BuilderResult<(PathBuf, PathBuf)> {
1094		
1095		let _relative = _path.strip_prefix (_relative_root) .or_wrap (0x546e7cd9) ? .to_str () .or_wrap (0xa48f283c) ?;
1096		let _relative = ["/", _relative].concat () .into ();
1097		
1098		let _path = normalize_path (&_path) ?;
1099		
1100		Ok ((_relative, _path))
1101	}
1102}
1103
1104
1105
1106
1107impl Builder {
1108	
1109	
1110	fn dependencies_include (&mut self, _path : &Path) -> BuilderResult {
1111		
1112		self.dependencies.insert (_path.into ());
1113		
1114		Ok (())
1115	}
1116	
1117	fn dependencies_include_all <'a> (&mut self, _paths : impl Iterator<Item = &'a Path>) -> BuilderResult {
1118		
1119		for _path in _paths {
1120			self.dependencies_include (_path) ?;
1121		}
1122		
1123		Ok (())
1124	}
1125	
1126	#[ allow (dead_code) ]
1127	fn dependencies_exclude (&mut self, _path : &Path) -> BuilderResult {
1128		
1129		self.dependencies.remove (_path.into ());
1130		
1131		Ok (())
1132	}
1133	
1134	fn dependencies_extend (&mut self) -> BuilderResult {
1135		
1136		let mut _extra = Vec::new ();
1137		
1138		for _dependency in self.dependencies.iter () {
1139			
1140			let _metadata = fs::symlink_metadata (_dependency) .or_wrap (0x06a4fbd5) ?;
1141			
1142			if _metadata.file_type () .is_symlink () {
1143				let _target = _dependency.canonicalize () .or_wrap (0x8df4310e) ?;
1144				_extra.push (_target);
1145			}
1146		}
1147		
1148		for _dependency in _extra.into_iter () {
1149			self.dependencies.insert (_dependency);
1150		}
1151		
1152		self.dependencies.insert (PathBuf::from (file! ()));
1153		
1154		Ok (())
1155	}
1156}
1157
1158
1159
1160
1161impl Builder {
1162	
1163	
1164	fn generate_id (&mut self) -> String {
1165		let _id = self.counter;
1166		self.counter += 1;
1167		format! ("{:04}", _id)
1168	}
1169}
1170
1171
1172
1173
1174#[ cfg (feature = "builder-assets-sass") ]
1175impl Builder {
1176	
1177	
1178	fn compile_sass (&mut self, _source : &Path) -> BuilderResult<String> {
1179		crate::support_sass::compile_sass (_source)
1180	}
1181}
1182
1183
1184
1185
1186#[ cfg (feature = "builder-markdown") ]
1187impl Builder {
1188	
1189	fn compile_markdown_body (&self, _source : &Path, _title_detect : bool) -> BuilderResult<crate::support_markdown::MarkdownOutput> {
1190		let mut _options = crate::support_markdown::MarkdownOptions::default ();
1191		_options.title_detect = _title_detect;
1192		crate::support_markdown::compile_markdown_from_path (_source, Some (&_options))
1193	}
1194	
1195	fn compile_markdown_html (&self, _source : &Path, _header : Option<&Path>, _footer : Option<&Path>) -> BuilderResult<String> {
1196		crate::support_markdown::compile_markdown_html_from_path (_source, _header, _footer, None)
1197	}
1198}
1199
1200
1201
1202
1203fn create_file_from_str (_path : &Path, _data : &str, _skip_if_exists : bool, _skip_if_same : bool) -> BuilderResult {
1204	
1205	fs::create_dir_all (_path.parent () .or_wrap (0x370af23d) ?) ?;
1206	
1207	let _metadata = match fs::symlink_metadata (_path) {
1208		Ok (_metadata) =>
1209			if _metadata.is_file () {
1210				Some (_metadata)
1211			} else {
1212				return Err (error_with_format (0x7b58f13c, format_args! ("{}", _path.display ())));
1213			}
1214		Err (_error) if _error.kind () == io::ErrorKind::NotFound =>
1215			None,
1216		Err (_error) =>
1217			return Err (_error.wrap (0xb30cd904)),
1218	};
1219	if _skip_if_exists && _metadata.is_some () {
1220		return Ok (());
1221	}
1222	if _skip_if_same && _metadata.is_some () {
1223		let _data_old = fs::read (_path) .or_wrap (0x6c311b95) ?;
1224		let _data_old_fingerprint = fingerprint_data (_data_old);
1225		let _data_new_fingerprint = fingerprint_data (_data);
1226		if _data_old_fingerprint == _data_new_fingerprint {
1227			return Ok (());
1228		}
1229	}
1230	
1231	// FIXME:  Use temporary file then rename!
1232	let mut _file = fs::File::create (_path) ?;
1233	_file.write_all (_data.as_bytes ()) ?;
1234	
1235	Ok (())
1236}
1237
1238
1239
1240
1241pub trait RoutePathBuilder {
1242	
1243	fn build (&self, _source_relative : &Path, _source_path : &Path, _route_prefix_hint : Option<&Path>, _route_infix_hint : Option<&Path>) -> BuilderResult<PathBuf>;
1244}
1245
1246
1247impl RoutePathBuilder for () {
1248	
1249	fn build (&self, _source_relative : &Path, _source_path : &Path, _route_prefix_hint : Option<&Path>, _route_infix_hint : Option<&Path>) -> BuilderResult<PathBuf> {
1250		generate_route (_source_relative, _route_prefix_hint, _route_infix_hint)
1251	}
1252}
1253
1254
1255impl RoutePathBuilder for (bool, &str) {
1256	
1257	fn build (&self, _source_relative : &Path, _source_path : &Path, _route_prefix_hint : Option<&Path>, _route_infix_hint : Option<&Path>) -> BuilderResult<PathBuf> {
1258		if self.0 {
1259			generate_route (_source_relative, Some (Path::new (self.1)), None)
1260		} else {
1261			normalize_route (Path::new (self.1), true, false)
1262		}
1263	}
1264}
1265
1266
1267
1268
1269pub trait RouteExtensionsBuilder {
1270	
1271	fn build (&self) -> BuilderResult<proc_macro2::TokenTree>;
1272}
1273
1274
1275impl RouteExtensionsBuilder for () {
1276	
1277	fn build (&self) -> BuilderResult<proc_macro2::TokenTree> {
1278		Ok (proc_macro2::Group::new (proc_macro2::Delimiter::Parenthesis, proc_macro2::TokenStream::new ()) .into ())
1279	}
1280}
1281
1282
1283impl RouteExtensionsBuilder for str {
1284	
1285	fn build (&self) -> BuilderResult<proc_macro2::TokenTree> {
1286		token_tree_parse (self)
1287	}
1288}
1289
1290
1291
1292
1293fn generate_route (_source_relative : &Path, _route_prefix : Option<&Path>, _route_infix : Option<&Path>) -> BuilderResult<PathBuf> {
1294	
1295	let _route_prefix = _route_prefix.or_wrap (0x1ba00780) ?;
1296	
1297	if ! _route_prefix.starts_with ("/") || (_route_prefix.ends_with ("/") && _route_prefix != Path::new ("/")) {
1298		return Err (error_with_code (0x6fc9256c));
1299	}
1300	if ! _source_relative.starts_with ("/") || _source_relative.ends_with ("/") {
1301		return Err (error_with_code (0xace09af4));
1302	}
1303	if let Some (_route_infix) = _route_infix {
1304		if _route_infix.starts_with ("/") || _route_infix.ends_with ("/") {
1305			return Err (error_with_code (0xd224b592));
1306		}
1307	}
1308	
1309	let _source_relative = _source_relative.strip_prefix ("/") .or_wrap (0xbd4b80bd) ?;
1310	
1311	let _route = if let Some (_route_infix) = _route_infix {
1312		let _route_infix = _route_infix.strip_prefix ("/") .or_wrap (0x1a7e3353) ?;
1313		_route_prefix.join (_route_infix) .join (_source_relative)
1314	} else {
1315		_route_prefix.join (_source_relative)
1316	};
1317	
1318	normalize_route (&_route, false, false)
1319}
1320
1321
1322fn normalize_route (_path_0 : &Path, _keep_trailing_slash : bool, _force_trailing_slash : bool) -> BuilderResult<PathBuf> {
1323	
1324	if ! _path_0.starts_with ("/") {
1325		return Err (error_with_code (0x1e7f7bc0));
1326	}
1327	
1328	let mut _path = PathBuf::new ();
1329	_path.push ("/");
1330	for _component in _path_0.components () {
1331		_path.push (_component);
1332	}
1333	
1334	if (_keep_trailing_slash || _force_trailing_slash) && (_path != Path::new ("/")) {
1335		if _path_0.to_string_lossy () .ends_with ("/") || _force_trailing_slash {
1336			let mut _path_1 = _path.clone () .into_os_string ();
1337			_path_1.push ("/");
1338			_path = _path_1.into ();
1339		}
1340	}
1341	
1342	Ok (_path)
1343}
1344
1345
1346fn normalize_path (_path_0 : &Path) -> BuilderResult<PathBuf> {
1347	
1348	let mut _path = PathBuf::new ();
1349	for _component in _path_0.components () {
1350		_path.push (_component);
1351	}
1352	
1353	Ok (_path)
1354}
1355
1356
1357
1358
1359fn detect_content_type_from_extension (_source : &Path) -> BuilderResult<&'static str> {
1360	
1361	let _extension = _source.extension () .or_wrap (0x29957dc8) ? .to_str () .or_wrap (0x908aeea6) ?;
1362	
1363	let _content_type = match _extension {
1364		"text" | "txt" => "text",
1365		"md" => "text",
1366		"html" | "htm" => "html",
1367		"css" => "css",
1368		"js" => "js",
1369		"json" => "json",
1370		"xml" => "xml",
1371		"png" => "png",
1372		"jpeg" | "jpg" => "jpeg",
1373		"ico" => "icon",
1374		"svg" => "svg",
1375		"ttf" => "font_ttf",
1376		"otf" => "font_otf",
1377		"woff" => "font_woff",
1378		"woff2" => "font_woff2",
1379		_ => "unknown",
1380	};
1381	
1382	Ok (_content_type)
1383}
1384
1385
1386
1387
1388fn token_tree_parse (_string : &str) -> BuilderResult<proc_macro2::TokenTree> {
1389	let _stream = proc_macro2::TokenStream::from_str (_string) .or_wrap (0x72524db6) ?;
1390	let mut _stream = _stream.into_iter ();
1391	let _token = if let Some (_token) = _stream.next () {
1392		_token
1393	} else {
1394		return Err (error_with_code (0xe9c8879a))
1395	};
1396	if _stream.next () .is_some () {
1397		return Err (error_with_code (0xd96714a4))
1398	}
1399	Ok (_token)
1400}
1401
1402
1403
1404
1405#[ allow (dead_code) ]
1406fn fingerprint_data (_data : impl AsRef<[u8]>) -> String {
1407	use blake2::Digest as _;
1408	let mut _hasher = blake2::Blake2b::new ();
1409	_hasher.update (_data.as_ref ());
1410	let _hash = _hasher.finalize ();
1411	format! ("{:x}", _hash)
1412}
1413