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
|
#![cfg_attr(feature = "cargo-clippy", allow(unused_parens))]
extern crate serde;
#[macro_use]
extern crate serde_derive;
#[cfg(feature = "serde-json")]
extern crate serde_json;
extern crate toml;
use std::env;
use std::fs;
use std::path::{Path, PathBuf};
mod error;
mod escaping;
pub use error::{Error, Result};
pub use escaping::MarkupDisplay;
pub mod filters;
pub struct Config {
pub dirs: Vec<PathBuf>,
}
impl Config {
pub fn new() -> Config {
let root = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
let filename = root.join(CONFIG_FILE_NAME);
if filename.exists() {
Self::from_str(&fs::read_to_string(&filename)
.expect(&format!("unable to read {}", filename.to_str().unwrap())))
} else {
Self::from_str("")
}
}
pub fn from_str(s: &str) -> Self {
let root = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
let default = vec![root.join("templates")];
let raw: RawConfig =
toml::from_str(&s).expect(&format!("invalid TOML in {}", CONFIG_FILE_NAME));
let dirs = raw.dirs
.map(|dirs| dirs.into_iter().map(|dir| root.join(dir)).collect())
.unwrap_or_else(|| default);
Self { dirs }
}
pub fn find_template(&self, path: &str, start_at: Option<&Path>) -> PathBuf {
if let Some(root) = start_at {
let relative = root.with_file_name(path);
if relative.exists() {
return relative.to_owned();
}
}
for dir in &self.dirs {
let rooted = dir.join(path);
if rooted.exists() {
return rooted;
}
}
panic!(
"template {:?} not found in directories {:?}",
path, self.dirs
)
}
}
#[derive(Deserialize)]
struct RawConfig {
dirs: Option<Vec<String>>,
}
static CONFIG_FILE_NAME: &str = "askama.toml";
#[cfg(test)]
mod tests {
use super::Config;
use std::env;
use std::path::{Path, PathBuf};
fn assert_eq_rooted(actual: &Path, expected: &str) {
let mut root = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
root.push("templates");
let mut inner = PathBuf::new();
inner.push(expected);
assert_eq!(actual.strip_prefix(root).unwrap(), inner);
}
#[test]
fn find_absolute() {
let config = Config::new();
let root = config.find_template("a.html", None);
let path = config.find_template("sub/b.html", Some(&root));
assert_eq_rooted(&path, "sub/b.html");
}
#[test]
#[should_panic]
fn find_relative_nonexistent() {
let config = Config::new();
let root = config.find_template("a.html", None);
config.find_template("b.html", Some(&root));
}
#[test]
fn find_relative() {
let config = Config::new();
let root = config.find_template("sub/b.html", None);
let path = config.find_template("c.html", Some(&root));
assert_eq_rooted(&path, "sub/c.html");
}
#[test]
fn find_relative_sub() {
let config = Config::new();
let root = config.find_template("sub/b.html", None);
let path = config.find_template("sub1/d.html", Some(&root));
assert_eq_rooted(&path, "sub/sub1/d.html");
}
}
|