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
use std::collections::BTreeMap;
use std::fs::{self, File};
use std::path::{Path, PathBuf};
use mustache;
use error::{Error, Result};
use parser;
use template::TemplateMap;
pub type Header = BTreeMap<String, String>;
#[derive(PartialEq, Debug)]
pub struct Document {
data: Header,
content: String,
}
impl Document {
pub fn new(header: Header, content: &str) -> Document {
Document { data: header, content: content.to_owned() }
}
pub fn as_html(&self) -> Result<String> {
let template = mustache::compile_str(&self.content);
let mut buf = Vec::<u8>::new();
try!(template.render(&mut buf, &self.data));
String::from_utf8(buf).map_err(Error::from)
}
pub fn render_to_file(&self, file_path: &Path, templates: &TemplateMap) -> Result<()> {
let template_path = try!(self.template());
let template = try!(templates.get(&template_path.to_owned())
.ok_or(Error::TemplateNotFound));
let parent_path = file_path.parent().ok_or_else(|| Error::missing_parent_path(&file_path));
try!(fs::create_dir_all(&try!(parent_path)));
let mut file = try!(File::create(file_path));
let mut data = BTreeMap::new();
data.insert("content", try!(self.as_html()));
for (key, value) in &self.data {
data.insert(key, value.clone());
}
let template = mustache::compile_str(template);
try!(template.render(&mut file, &data));
info!("Created {}", file_path.display());
Ok(())
}
fn template(&self) -> Result<&String> {
self.data.get(&"template".to_owned())
.ok_or(Error::MissingTemplateField)
}
}
pub fn load_documents_from_disk<F>(documents_path: &Path, mut criteria: F) -> Result<BTreeMap<PathBuf, Document>>
where F : FnMut(&Path) -> bool
{
use util;
let mut documents = BTreeMap::new();
try!(util::walk_dir(
documents_path,
&mut |path| {
if !criteria(&path) || !path.is_file() {
return Ok(());
}
let content = {
use std::io::Read;
let mut buf = String::new();
let mut file = try!(File::open(&path));
try!(file.read_to_string(&mut buf));
buf
};
let document = try!(parser::parse_document(&content));
let relative_path = try!(path.strip_prefix(documents_path));
documents.insert(relative_path.with_extension("").to_path_buf(), document);
Ok(())
},
));
Ok(documents)
}