use anyhow::Result;
use serde_json::Value;
use std::{
fs,
io::{self, BufRead, Write},
path::PathBuf,
};
use tera::{Context, Tera};
pub fn render_file(path: PathBuf, json: Value) -> Result<String> {
let template = fs::read_to_string(&path)?;
let name = path.to_str().unwrap_or("template");
let mut tera = Tera::default();
tera.add_raw_template(name, &template)?;
let context = Context::from_serialize(&json)?;
Ok(tera.render(name, &context)?)
}
pub fn render_inline(raw: String, json: Value) -> Result<String> {
let mut tera = Tera::default();
tera.add_raw_template("inline", &raw)?;
let context = Context::from_serialize(&json)?;
Ok(tera.render("inline", &context)?)
}
fn embed_rendered(srcpath: &PathBuf, lookup: &str, rendered: &str) -> Result<()> {
let src = fs::File::open(srcpath)?;
let read = io::BufReader::new(src);
let dstpath = srcpath.with_added_extension(".wefter");
let dst = fs::File::create(&dstpath)?;
let mut wrt = io::BufWriter::new(dst);
let mut rlines = read.lines();
while let Some(l) = rlines.next() {
let l = l?;
if l.contains(lookup) {
let indent_len = l.find(|c: char| !c.is_whitespace()).unwrap_or(l.len());
let indent = &l[..indent_len];
for line in rendered.lines() {
if line.is_empty() {
writeln!(wrt)?;
} else {
writeln!(wrt, "{}{}", indent, line)?;
}
}
}
writeln!(wrt, "{}", l)?;
}
wrt.flush()?;
fs::rename(dstpath, srcpath)?;
Ok(())
}
pub fn embed_file(srcpath: PathBuf, lookup: String, template: PathBuf, tjson: Value) -> Result<()> {
let t = render_file(template, tjson)?;
embed_rendered(&srcpath, &lookup, &t)
}
pub fn embed_inline(srcpath: PathBuf, lookup: String, template_str: String, tjson: Value) -> Result<()> {
let t = render_inline(template_str, tjson)?;
embed_rendered(&srcpath, &lookup, &t)
}