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
|
//! templated file handling
//!
//! Reads files from the filesystem, processes them as a template, and prepares
//! a `Response` for them.
//!
//! See [`templated`] for how templates are handled
use axum::{body::Body, response::Response};
use bempline::{Document, Options, options::IncludeMethod};
use paige::Templated;
use crate::{
RuntimeError,
config::Settings,
fs::{self, RequestPath, SafePathBuf},
state::SplormState,
templated::TemplateVariables,
};
pub async fn send_file(
path: RequestPath,
state: SplormState,
settings: &Settings,
) -> Result<Response, RuntimeError> {
let safe = path.system_path().to_owned();
let string = fs::read_file_to_string(path.system_path()).await?;
let template = Templated::parse(&string)
.map_err(|_| RuntimeError::not_a_template(path.system_path().to_path_buf()))?;
let tvars = TemplateVariables::build(safe.as_path(), &template.frontmatter);
tracing::trace!(
"page {} has features {:?}",
path.web_path(),
tvars.features()
);
let pt_path = match tvars.template() {
Some(name) => {
let path = RequestPath::verify_safe(settings.template_dir(), &format!("{name}.html"))?;
path.system_path().to_owned()
}
None => {
tracing::trace!(
"using default template: {}",
settings.default_template_name()
);
settings.default_template_path()
}
};
let mut page_template = get_template(pt_path).await?;
tvars.apply_title(&mut page_template);
tvars.apply_styles(&mut page_template);
tvars.apply_published(&mut page_template);
tvars.apply_pathnav(&mut page_template, &path);
tvars.apply_opengraph(&mut page_template, &settings, &path);
let content = if !tvars.features().is_empty() {
let with_features = tvars.apply_features(template.content, &state).await;
tvars.apply_markup(&mut page_template, &with_features)
} else {
tvars.apply_markup(&mut page_template, template.content)
};
page_template.set("main", content);
Response::builder()
.status(200)
.header("content-type", "text/html")
.body(Body::from(page_template.compile()))
.map_err(|_| RuntimeError::Unknown)
}
async fn get_template(path: SafePathBuf) -> Result<Document, RuntimeError> {
let options = Options::new().include_path(IncludeMethod::Path(path.as_std_path().to_owned()));
let str = fs::read_file_to_string(path.as_path()).await?;
Document::from_str(str, options)
.map_err(|perr| RuntimeError::template_parse_error(perr, path.to_path_buf()))
}
|