use std::collections::{HashMap, HashSet};
use std::path::{Path, PathBuf};
use crate::error::ScrapsResult;
use crate::service::tera_render::{render_to_file, user_template_glob};
use crate::usecase::build::model::backlinks_map::BacklinksMap;
use crate::usecase::build::model::html::HtmlMetadata;
use crate::usecase::build::model::scrap_detail::ScrapDetail;
use crate::usecase::build::model::site_nav::SiteNav;
use scraps_libs::model::base_url::BaseUrl;
use scraps_libs::model::file::ScrapFileStem;
use scraps_libs::model::key::ScrapKey;
use scraps_libs::model::scrap::Scrap;
use tera::Tera;
use crate::usecase::build::html::templates;
use super::serde::link_scraps::LinkScrapsTera;
use super::serde::scrap_detail::ScrapDetailTera;
use super::serde::tag::TagTera;
pub struct ScrapRender {
tera: Tera,
output_scraps_dir_path: PathBuf,
}
impl ScrapRender {
pub fn new(static_dir_path: &Path, output_dir_path: &Path) -> ScrapsResult<ScrapRender> {
let tera = templates::scrap(&user_template_glob(static_dir_path, "*.html"))?;
Ok(ScrapRender {
tera,
output_scraps_dir_path: output_dir_path.join("scraps"),
})
}
pub fn run(
&self,
base_url: &BaseUrl,
metadata: &HtmlMetadata,
scrap_detail: &ScrapDetail,
backlinks_map: &BacklinksMap,
scraps_by_key: &HashMap<ScrapKey, Scrap>,
site_nav: &SiteNav,
) -> ScrapsResult<()> {
let mut context = templates::context(base_url, metadata);
templates::insert_site_nav(&mut context, "", site_nav, backlinks_map);
let scrap = &scrap_detail.scrap();
context.insert("scrap", &ScrapDetailTera::from(scrap_detail.clone()));
let scrap_tags = scrap
.tags()
.iter()
.map(|tag| TagTera::new(tag, backlinks_map))
.collect::<Vec<_>>();
context.insert("scrap_tags", &scrap_tags);
let linked_scraps = backlinks_map.get(&scrap.self_key());
context.insert("linked_scraps", &LinkScrapsTera::new(&linked_scraps));
let mut seen = HashSet::new();
let outbound_scraps = scrap
.links()
.iter()
.filter(|key| seen.insert((*key).clone()))
.filter_map(|key| scraps_by_key.get(key).cloned())
.collect::<Vec<_>>();
context.insert("outbound_scraps", &LinkScrapsTera::new(&outbound_scraps));
let file_path = self
.output_scraps_dir_path
.join(format!("{}.html", ScrapFileStem::from(scrap.self_key())));
render_to_file(&self.tera, "__builtins/scrap.html", &context, &file_path)
}
}
#[cfg(test)]
mod tests {
use std::fs;
use url::Url;
use crate::usecase::build::model::backlinks_map::BacklinksMap;
use crate::usecase::build::model::html::HtmlMetadata;
use scraps_libs::lang::LangCode;
use scraps_libs::model::base_url::BaseUrl;
use scraps_libs::model::scrap::Scrap;
use scraps_libs::model::tags::Tags;
use super::*;
#[test]
fn it_run() {
let base_url = &BaseUrl::new(Url::parse("http://localhost:1112/").unwrap()).unwrap();
let metadata = HtmlMetadata::new(
&LangCode::default(),
"Scrap",
&Some("Scrap Wiki".to_string()),
&Some(Url::parse("https://github.io/image.png").unwrap()),
);
let test_resource_path =
PathBuf::from("tests/resource/build/html/render/it_render_scrap_htmls");
let static_dir_path = test_resource_path.join("static");
let output_dir_path = test_resource_path.join("_site");
let commited_ts1 = None;
let scrap1 = &Scrap::new("scrap 1", &None, "# header1");
let scrap2 = &Scrap::new(
"scrap 2",
&Some("Context".into()),
"[[scrap 1]] #[[design]]",
);
let scraps = vec![scrap1.to_owned(), scrap2.to_owned()];
let scrap_texts = scraps
.iter()
.map(|scrap| (scrap.self_key(), scrap.md_text().to_string()))
.collect();
let backlinks_map = BacklinksMap::new(&scraps);
let site_nav = SiteNav::new(
scraps.len(),
Tags::new(&scraps),
true,
chrono_tz::UTC,
false,
);
let scraps_by_key: HashMap<_, _> = scraps
.iter()
.map(|scrap| (scrap.self_key(), scrap.clone()))
.collect();
let scrap1_html_path = output_dir_path.join("scraps/scrap-1.html");
let scrap2_html_path = output_dir_path.join("scraps/context/scrap-2.html");
let render = ScrapRender::new(&static_dir_path, &output_dir_path).unwrap();
render
.run(
base_url,
&metadata,
&ScrapDetail::new(scrap1, &commited_ts1, base_url, &scrap_texts),
&backlinks_map,
&scraps_by_key,
&site_nav,
)
.unwrap();
let result2 = fs::read_to_string(scrap1_html_path).unwrap();
assert!(result2.contains(">backlinks · 1"));
assert!(!result2.contains(">links ·"));
assert!(!result2.contains("corsproxy"));
render
.run(
base_url,
&metadata,
&ScrapDetail::new(scrap2, &commited_ts1, base_url, &scrap_texts),
&backlinks_map,
&scraps_by_key,
&site_nav,
)
.unwrap();
let result4 = fs::read_to_string(scrap2_html_path).unwrap();
assert!(result4.contains(">links · 1"));
assert!(result4.contains("tags/design.html"));
assert!(result4.contains("#[["));
}
}