1use std::{
2 fs,
3 path::{Path, PathBuf},
4};
5
6use crate::{context::Context, data, jinja::init_environment, Entity, Generator};
7
8use anyhow::Result;
9
10#[derive(Debug)]
11pub(crate) struct GenkitEngine<G> {
12 source: PathBuf,
13 dest: PathBuf,
14 generator: G,
15}
16
17impl<G> GenkitEngine<G>
18where
19 G: Generator + Send,
20{
21 pub fn new(source: impl AsRef<Path>, dest: impl AsRef<Path>, generator: G) -> Result<Self> {
22 let dest = dest.as_ref().to_path_buf();
23 if !dest.exists() {
24 fs::create_dir_all(&dest)?;
25 }
26 Ok(GenkitEngine {
27 source: source.as_ref().to_path_buf(),
28 dest,
29 generator,
30 })
31 }
32
33 pub fn build(&mut self, reload: bool) -> Result<()> {
34 let instant = std::time::Instant::now();
35 let source = self.source.as_ref();
36 let dest = self.dest.as_ref();
37 let mut entity = if reload {
38 self.generator.on_reload(source)?
39 } else {
40 self.generator.on_load(source)?
41 };
42
43 entity.parse(source)?;
44
45 let env = self
46 .generator
47 .on_extend_environment(source, init_environment(), &entity);
48
49 if let Some(markdown_config) = self.generator.get_markdown_config(&entity) {
50 let mut guard = data::write();
51 guard.set_markdown_config(markdown_config);
52 }
53
54 let context = Context::new();
55 entity
56 .render(&env, context.clone(), dest)
57 .expect("Render failed.");
58
59 self.generator
60 .on_render(&env, context, &entity, source, dest)?;
61 println!("Build cost: {}ms", instant.elapsed().as_millis());
62 Ok(())
63 }
64}