1pub mod context;
10pub mod error;
11pub mod language;
12pub mod lexer;
13
14pub use context::Context;
15pub use error::Error;
16pub use lexer::{Lexer, ToTemplateValue, Token, TokenWithContext, Tokenize, Value};
17
18use crate::http::Response;
19use crate::view::Templates;
20
21use language::Program;
22
23use std::fs::read_to_string;
24use std::path::{Path, PathBuf};
25use std::sync::Arc;
26
27#[allow(dead_code)]
31#[derive(Clone, Debug)]
32pub struct Template {
33 program: Program,
34 path: Option<PathBuf>,
35}
36
37impl Template {
38 pub fn new(path: impl AsRef<Path> + std::marker::Copy) -> Result<Self, Error> {
40 let text = match read_to_string(path) {
41 Ok(text) => text,
42 Err(_) => return Err(Error::TemplateDoesNotExist(path.as_ref().to_owned())),
43 };
44
45 Ok(Template {
46 program: Program::from_str(&text)?,
47 path: Some(path.as_ref().to_owned()),
48 })
49 }
50
51 pub fn from_str(template: &str) -> Result<Self, Error> {
63 Ok(Template {
64 program: Program::from_str(template)?,
65 path: None,
66 })
67 }
68
69 pub fn render(&self, context: impl TryInto<Context, Error = Error>) -> Result<String, Error> {
72 let context: Context = context.try_into()?;
73
74 match self.program.evaluate(&context) {
75 Ok(result) => Ok(result),
76 Err(err) => {
77 if let Some(path) = &self.path {
78 Err(err.pretty_from_path(path))
79 } else {
80 Err(err)
81 }
82 }
83 }
84 }
85
86 pub fn render_default(&self) -> Result<String, Error> {
89 self.render(&Context::default())
90 }
91
92 pub fn cached(path: impl AsRef<Path> + Copy) -> Result<Arc<Self>, Error> {
95 match Templates::cache().get(path) {
96 Ok(template) => Ok(template),
97 Err(err) => Err(err.pretty_from_path(path)),
98 }
99 }
100
101 pub fn load(path: impl AsRef<Path> + Copy) -> Result<Arc<Self>, Error> {
103 Self::cached(path)
104 }
105
106 pub fn defaults(context: Context) {
109 Context::defaults(context);
110 }
111
112 pub fn cached_static(path: impl AsRef<Path> + Copy) -> Result<Response, Error> {
119 match Self::cached(path) {
120 Ok(template) => Ok(template.try_into()?),
121 Err(err) => Ok(Response::internal_error(err)),
122 }
123 }
124}
125
126impl TryFrom<&Template> for Response {
127 type Error = Error;
128
129 fn try_from(template: &Template) -> Result<Response, Self::Error> {
130 let text = template.render_default()?;
131 Ok(Response::new().html(text))
132 }
133}
134
135impl TryFrom<Arc<Template>> for Response {
136 type Error = Error;
137
138 fn try_from(template: Arc<Template>) -> Result<Response, Self::Error> {
139 use std::ops::Deref;
140 template.deref().try_into()
141 }
142}